Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

VHDL Fixed point representation and for loop

Status
Not open for further replies.

bachoo786

Junior Member level 1
Joined
Oct 25, 2012
Messages
18
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,480
Hello smart people :)

I needed guidance on representing fixed point numbers on vhdl. I will present the problem:

exponent * log (2) where exponent= 2^8 and (log (2)) is constant.

I need to represent the values of the above equation in vhdl (256 entries) using 8 bits only. I am not allowed to use fixed point library to carry out this task. Can anyone out there help me please, time is not in my hands :(

Many thanks
 

Besides other ambiguities in your post, what does this mean:
I need to represent the values of the above equation in vhdl (256 entries) using 8 bits only.
Presumed you represent log (2) by a 8-Bit number (natural or decadic logarithm, by the way?), the product of 8-Bit exponent and and log(2) will be a 16-Bit number.

A fixed point representaion isn't but applying an arbitrary binary shift. E.g. log10(2)=0.30103. You get the best fixed point representation by a 9-Bit shift:

to_unsigned(to_integer(0.30103*2.0**9),8) = 154
 

Besides other ambiguities in your post, what does this mean:

Presumed you represent log (2) by a 8-Bit number (natural or decadic logarithm, by the way?), the product of 8-Bit exponent and and log(2) will be a 16-Bit number.

A fixed point representaion isn't but applying an arbitrary binary shift. E.g. log10(2)=0.30103. You get the best fixed point representation by a 9-Bit shift:

to_unsigned(to_integer(0.30103*2.0**9),8) = 154

As in what I meant was, if a=(log(2) * exponent) than a will be having 256 different values as the exponent varies from 0 to 255..and the log(2) is constant.

So for example when exponent is 1 than a=0.3010299957 this value needs to be represented in 8 bits I.e. 0.01001101000... Hence if you cut it down to 8 bits you get 0.0100110..now how can I represent this value? On top of that the value will be changing for example when exponent is 10, a=3.010299957 I.e. 11.000000..again this would not agree with specified no bits for a e.g. (-3 to 4)

Hope that makes it clearer.

- - - Updated - - -

**with the specified no of bits for a....
 

you are using the format QN.M, N stands for the integer, M for the decimal.
say, Q1.7 in your case, 0.0100110.

when I do multiplication in FPGA, I usually define the range of the multiplication results by matlab first, then assign different N and M to the QN.M.
for example, if 2.5*3.5= 8.7500, then the result requires Q5.3 format, which is 01000.110.

with this format set, I could assign different N and M to the 2.5, 3.5 or any other numbers, as long as truncate or round the multiplication result in Q5.3 format.
 

As in what I meant was, if a=(log(2) * exponent) than a will be having 256 different values as the exponent varies from 0 to 255..and the log(2) is constant.

So for example when exponent is 1 than a=0.3010299957 this value needs to be represented in 8 bits I.e. 0.01001101000... Hence if you cut it down to 8 bits you get 0.0100110..now how can I represent this value? On top of that the value will be changing for example when exponent is 10, a=3.010299957 I.e. 11.000000..again this would not agree with specified no bits for a e.g. (-3 to 4)

Hope that makes it clearer.

So you mean representing the result by log(2) * exponent with only 8 bit's?

That's impossible without either cutting all significant bits for low exponent values or truncating the result for high values. In other words, you get either no resolution or can't represent the full exponent range. If the constant log(2) requires n bit resolution, that the result needs n+8 bits to represent all possible exponent values.

The only way to represent the result with 8 bits is to scale log(2) to 1.0, which most likely doesn't work for the intended purpose.
 

Right, I had truncated my values to tell you the truth and its true that I had no resolution.

Basically, I am doing logarithm of a floating point number, single precision to start with. The general equation when you apply logarithm to a floating point number is exp * log(2) + log(mantissa). I will be using a LUTs to store my values for (exp * log(2) ) and (log(mantissa)). Finally an adder to add any 2 values of the 2 operands.

For the first part of the equation like I mentioned in my previous post exponent is 8 bits. The trouble is with the fraction part, so I truncated them but was advised not to do so and was informed that there is another way to represent these values. I had in mind the fixed point library but that is out of the question.

So is there any other way to represent these values that anyone can think of and help me?

Also, the values for (exp * log(2)) are needed to be assigned to 256 entries in the LUT. I know it is tedious, but I am trying to work out a way to use a FOR loop that assigns these values to the addresses in the LUT. Can anyone help me with the VHDL code?

Many thanks
 

There's no solution unless you'll give sufficient resolution to the result.
 

Thanks guys for all your inputs !

I did manage to generate values for my LUT by using base 2 instead of 10 and got whole numbers for my first operand i.e. (exp*log(2)). I have stored these values on a text file and I now need to assign them to individual addresses on my LUT i.e. 256 addresses.

Can anyone show me on how to initialise these values and assign them to the individual addresses on the LUT?

Many thanks!!
 

the easiest way is to define a 256 entre array type and then declare a constant with all entries you require. Make sure you follow the synthesis template for a ROM.
 

Thanks for the reply TrickyDicky.

I will use that approach for the first operand, but for my second operand i.e. log2(mantissa), I don’t have any constant and therefore I would need to initialise my values from a text file.

So I still need a bit of help with the coding. Can anyone help me please?

Many thanks.
 

I managed to get a code for initialising my generated values to the addresses in the LUT but I get the following errors:

-syntax error near for
-i is not declared
-synax error near loop
-unit behavioural ignored due to previous errors

I tried to resolve these errors but had no luck so far, I don't know if I am doing something wrong. Can anyone please help me? Thanks

Here's my code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use STD.TEXTIO.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;

Entity ROM_ent is
Port(
ADDR: IN std_logic_VECTOR(7 downto 0);
CLK: IN std_logic;
DATA: OUT std_logic_VECTOR(7 downto 0)
);
end ROM_ent;

Architecture Behavioral of ROM_ent is

type rom_type is array (255 downto 0) of std_logic_vector (7 downto 0);

FILE romfile : text open read_mode is "Doc1.Txt";
variable RomFileLine : line;
variable ROM : rom_type;
begin

for i in rom_type'range loop

readline(romfile, RomFileLine);
read(RomFileLine, ROM(i));

end loop;

begin

process (CLK)
begin
if(CLK'event and CLK = '1') then
DATA <= ROM(to_integer(unsigned(ADDR)));
end if;
end process;

end Behavioral;
 

you cannot put a for loop there, it has to be inside a process, function or procedure - a function is waht you want in your case. You also cannot put variables in architectyures, only in functions, procedures and processes. So wrap what you have in a function that sets a constant, then you're there.

PS. Make ROM a constant
 
Oh right...well I introduced an init function, here's my code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use STD.TEXTIO.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;

Entity ROM_ent is
Port(
ADDR: IN std_logic_VECTOR(7 downto 0);
CLK: IN std_logic;
DATA: OUT std_logic_VECTOR(7 downto 0)
);
end ROM_ent;

Architecture Behavioral of ROM_ent is

type rom_type is array (255 downto 0) of std_logic_vector (7 downto 0);

impure function InitRomFromFile (RomFileName : in string) return rom_type is

FILE romfile : text is in RomFileName;
variable RomFileLine : line;
variable ROM : rom_type;
begin

for i in rom_type'range loop

readline(romfile, RomFileLine);
read(RomFileLine, ROM(i));

end loop;
return ROM;
end function;

Constant ROM : rom_type := InitRomFromFile("Doc1.Txt");

begin

process (CLK)
begin
if(CLK'event and CLK = '1') then
DATA <= ROM(to_integer(unsigned(ADDR)));
end if;
end process;


end Behavioral;


Does that look alright to you?
 

much better. But this code will only synthesise in Xilinx, Altera does not support textio to initialise a ROM (I wish they would!)
 

You don't necessarily need a text file. All constants that can be represented by arithmetic functions, e.g. log(), can be calculated in VHDL at compile time using ieee.math_real.
 

well it works with altium designer and gives me no errors?!

- - - Updated - - -

You don't necessarily need a text file. All constants that can be represented by arithmetic functions, e.g. log(), can be calculated in VHDL at compile time using ieee.math_real.

I would still need a text file for my second operand as it’s not a constant! Also I am asked to use pre calculated values from matlab.
 

I am now running a testbench with FOR Loop and I need your help. I get errors and I tried to rectify them with no luck.

Here's my code, can someone shed some light please?

------------------------------------------------------------
-- VHDL Testbench for rom_ent
-- 2013 2 2 12 40 1
-- Created by "EditVHDL"
-- "Copyright (c) 2002 Altium Limited"
------------------------------------------------------------

Library IEEE;
Use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.ALL;
Use IEEE.std_logic_textio.all;
Use STD.textio.all;
use IEEE.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
------------------------------------------------------------

------------------------------------------------------------
entity Testrom_ent is
end Testrom_ent;
------------------------------------------------------------

------------------------------------------------------------
architecture stimulus of Testrom_ent is
file RESULTS: TEXT open WRITE_MODE is "results.txt";
procedure WRITE_RESULTS(
ADDR: std_logic_vector(7 downto 0);
CLK: std_logic;
DATA: std_logic_vector(7 downto 0)
) is
variable l_out : line;
begin
write(l_out, now, right, 15);
write(l_out, ADDR, right, 9);
write(l_out, CLK, right, 2);
write(l_out, DATA, right, 9);
writeline(RESULTS, l_out);
end procedure;

component rom_ent
port (
ADDR: in std_logic_vector(7 downto 0);
CLK: in std_logic;
DATA: out std_logic_vector(7 downto 0)
);
end component;

signal ADDR: std_logic_vector(7 downto 0);
signal CLK: std_logic :='0';
signal DATA: std_logic_vector(7 downto 0);

begin
DUT:rom_ent port map (
ADDR => ADDR,
CLK => CLK,
DATA => DATA
);

CLK <= not CLK after 5ns;

STIMULUS0:process
begin
-- insert stimulus here

this is where I have begun writing my code for the testbench:
variable err_cnt:integer:=0;

begin


for i in rom_type'range loop
wait for 20ns;

if ADDR < rom_type'range then
assert(DATA =ROM)
report "Something's Wrong"
severity error;

if(DATA /=ROM) then
err_cnt:=err_cnt + 1;
end if;
end if;

ADDR <= ADDR + '1';
end loop;


--summary of all test

if (err_cnt =0) then
assert false
report "Testbench completed succesfully"
severity note;

else

assert true
report "Something's wrong,try again"
severity error;
end if;


wait;
end process;

WRITE_RESULTS(
ADDR,
CLK,
DATA
);

end architecture;
------------------------------------------------------------

------------------------------------------------------------
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top