Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21611 Discussions

ROM contents confusion

Altera_Forum
Honored Contributor II
1,655 Views

Hai, 

 

I have vhdl code for store a constant in ROM. The ROM is divided into odd and even; ROMO and ROME as shown below: 

library IEEE; use IEEE.STD_LOGIC_1164.all; -- use ieee.STD_LOGIC_signed.all; use IEEE.STD_LOGIC_arith.all; use WORK.MDCT_PKG.all; entity ROMO is port( addr : in STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); clk : in STD_LOGIC; datao : out STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0) ); end ROMO; architecture RTL of ROMO is type ROM_TYPE is array (0 to 2**ROMADDR_W-1) of STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0); constant rom : ROM_TYPE := ( (others => '0'), conv_std_logic_vector( GP,ROMDATA_W ), conv_std_logic_vector( FP,ROMDATA_W ), conv_std_logic_vector( FP+GP,ROMDATA_W ), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( EP+GP,ROMDATA_W ), conv_std_logic_vector( EP+FP,ROMDATA_W ), conv_std_logic_vector( EP+FP+GP,ROMDATA_W ), conv_std_logic_vector( DP,ROMDATA_W ), conv_std_logic_vector( DP+GP,ROMDATA_W ), conv_std_logic_vector( DP+FP,ROMDATA_W ), conv_std_logic_vector( DP+FP+GP,ROMDATA_W ), conv_std_logic_vector( DP+EP,ROMDATA_W ), conv_std_logic_vector( DP+EP+GP,ROMDATA_W ), conv_std_logic_vector( DP+EP+FP,ROMDATA_W ), conv_std_logic_vector( DP+EP+FP+GP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( FM,ROMDATA_W ), conv_std_logic_vector( DM,ROMDATA_W ), conv_std_logic_vector( DM+FM,ROMDATA_W ), conv_std_logic_vector( GM,ROMDATA_W ), conv_std_logic_vector( GM+FM,ROMDATA_W ), conv_std_logic_vector( GM+DM,ROMDATA_W ), conv_std_logic_vector( GM+DM+FM,ROMDATA_W ), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( EP+FM,ROMDATA_W ), conv_std_logic_vector( EP+DM,ROMDATA_W ), conv_std_logic_vector( EP+DM+FM,ROMDATA_W ), conv_std_logic_vector( EP+GM,ROMDATA_W ), conv_std_logic_vector( EP+GM+FM,ROMDATA_W ), conv_std_logic_vector( EP+GM+DM,ROMDATA_W ), conv_std_logic_vector( EP+GM+DM+FM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( GP,ROMDATA_W ), conv_std_logic_vector( EP+GP,ROMDATA_W ), conv_std_logic_vector( DM,ROMDATA_W ), conv_std_logic_vector( DM+EP,ROMDATA_W ), conv_std_logic_vector( DM+GP,ROMDATA_W ), conv_std_logic_vector( DM+GP+EP,ROMDATA_W ), conv_std_logic_vector( FP,ROMDATA_W ), conv_std_logic_vector( FP+EP,ROMDATA_W ), conv_std_logic_vector( FP+GP,ROMDATA_W ), conv_std_logic_vector( FP+GP+EP,ROMDATA_W ), conv_std_logic_vector( FP+DM,ROMDATA_W ), conv_std_logic_vector( FP+DM+EP,ROMDATA_W ), conv_std_logic_vector( FP+DM+GP,ROMDATA_W ), conv_std_logic_vector( FP+DM+GP+EP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( DM,ROMDATA_W ), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( EP+DM,ROMDATA_W ), conv_std_logic_vector( FM,ROMDATA_W ), conv_std_logic_vector( FM+DM,ROMDATA_W ), conv_std_logic_vector( FM+EP,ROMDATA_W ), conv_std_logic_vector( FM+EP+DM,ROMDATA_W ), conv_std_logic_vector( GP,ROMDATA_W ), conv_std_logic_vector( GP+DM,ROMDATA_W ), conv_std_logic_vector( GP+EP,ROMDATA_W ), conv_std_logic_vector( GP+EP+DM,ROMDATA_W ), conv_std_logic_vector( GP+FM,ROMDATA_W ), conv_std_logic_vector( GP+FM+DM,ROMDATA_W ), conv_std_logic_vector( GP+FM+EP,ROMDATA_W ), conv_std_logic_vector( GP+FM+EP+DM,ROMDATA_W ) ); begin process(clk) begin if clk = '1' and clk'event then datao <= rom( CONV_INTEGER(UNSIGNED(addr)) ); end if; end process; end RTL;  

library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_arith.all; use WORK.MDCT_PKG.all; entity ROME is port( addr : in STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); clk : in STD_LOGIC; datao : out STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0) ); end ROME; architecture RTL of ROME is type ROM_TYPE is array (0 to (2**ROMADDR_W)-1) of STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0); constant rom : ROM_TYPE := ( (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP+AP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( CM+BM,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), conv_std_logic_vector( CP+BM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( BP+CM,ROMDATA_W ), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( BP+CP,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), (others => '0'), (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AM+AM,ROMDATA_W ), conv_std_logic_vector( AM,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AM,ROMDATA_W ), (others => '0'), (others => '0'), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), conv_std_logic_vector( BP+CM,ROMDATA_W ), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( BM+CM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( CP+BP,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), conv_std_logic_vector( CP+BM,ROMDATA_W ), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), (others => '0') ); begin process(clk) begin if clk = '1' and clk'event then datao <= rom(CONV_INTEGER(UNSIGNED(addr)) ); end if; end process; end RTL;  

 

The constant values are AP:1448,BP:1892,CP:784,DP:2009,EP:1703,FP:1138,GP: 400,AM:-1448,BM:-1892,CM:-784,DM:-2009,EM:-1703,FM:-1138,GM:-400. 

I run the testbench to see the output. However, I do not understand how they build the ROME and ROMO table. How they manage 6 bits address with the constant value? I try to write back the table with address and the constant values at a paper, but I still don't get it. As I know, they splits the constant into odd and even values and build the table. I really need help from anyone expert here http://www.edaboard.com/images/smilies/icon_sad.gif . Very appreciate your help. Thank in advance
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
911 Views

I'm sorry you code is extremely difficult to read. Could you repost it with newlines? In any case, it seems to use the (bad) conv_std_logic_vector function a lot...

0 Kudos
Altera_Forum
Honored Contributor II
911 Views

 

--- Quote Start ---  

I'm sorry you code is extremely difficult to read. Could you repost it with newlines? In any case, it seems to use the (bad) conv_std_logic_vector function a lot... 

--- Quote End ---  

 

 

Hai Daixiwen, 

 

Below is the code,hope you can help. Thanks in advance. 

-- 5:0 -- 5:4 = select matrix row (1 out of 4) -- 3:0 = select precomputed MAC ( 1 out of 16) library IEEE; use IEEE.STD_LOGIC_1164.all; -- use ieee.STD_LOGIC_signed.all; use IEEE.STD_LOGIC_arith.all; use WORK.MDCT_PKG.all; entity ROMO is port( addr : in STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); clk : in STD_LOGIC; datao : out STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0) ); end ROMO; architecture RTL of ROMO is type ROM_TYPE is array (0 to 2**ROMADDR_W-1) of STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0); constant rom : ROM_TYPE := ( (others => '0'), conv_std_logic_vector( GP,ROMDATA_W ), conv_std_logic_vector( FP,ROMDATA_W ), conv_std_logic_vector( FP+GP,ROMDATA_W ), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( EP+GP,ROMDATA_W ), conv_std_logic_vector( EP+FP,ROMDATA_W ), conv_std_logic_vector( EP+FP+GP,ROMDATA_W ), conv_std_logic_vector( DP,ROMDATA_W ), conv_std_logic_vector( DP+GP,ROMDATA_W ), conv_std_logic_vector( DP+FP,ROMDATA_W ), conv_std_logic_vector( DP+FP+GP,ROMDATA_W ), conv_std_logic_vector( DP+EP,ROMDATA_W ), conv_std_logic_vector( DP+EP+GP,ROMDATA_W ), conv_std_logic_vector( DP+EP+FP,ROMDATA_W ), conv_std_logic_vector( DP+EP+FP+GP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( FM,ROMDATA_W ), conv_std_logic_vector( DM,ROMDATA_W ), conv_std_logic_vector( DM+FM,ROMDATA_W ), conv_std_logic_vector( GM,ROMDATA_W ), conv_std_logic_vector( GM+FM,ROMDATA_W ), conv_std_logic_vector( GM+DM,ROMDATA_W ), conv_std_logic_vector( GM+DM+FM,ROMDATA_W ), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( EP+FM,ROMDATA_W ), conv_std_logic_vector( EP+DM,ROMDATA_W ), conv_std_logic_vector( EP+DM+FM,ROMDATA_W ), conv_std_logic_vector( EP+GM,ROMDATA_W ), conv_std_logic_vector( EP+GM+FM,ROMDATA_W ), conv_std_logic_vector( EP+GM+DM,ROMDATA_W ), conv_std_logic_vector( EP+GM+DM+FM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( GP,ROMDATA_W ), conv_std_logic_vector( EP+GP,ROMDATA_W ), conv_std_logic_vector( DM,ROMDATA_W ), conv_std_logic_vector( DM+EP,ROMDATA_W ), conv_std_logic_vector( DM+GP,ROMDATA_W ), conv_std_logic_vector( DM+GP+EP,ROMDATA_W ), conv_std_logic_vector( FP,ROMDATA_W ), conv_std_logic_vector( FP+EP,ROMDATA_W ), conv_std_logic_vector( FP+GP,ROMDATA_W ), conv_std_logic_vector( FP+GP+EP,ROMDATA_W ), conv_std_logic_vector( FP+DM,ROMDATA_W ), conv_std_logic_vector( FP+DM+EP,ROMDATA_W ), conv_std_logic_vector( FP+DM+GP,ROMDATA_W ), conv_std_logic_vector( FP+DM+GP+EP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( DM,ROMDATA_W ), conv_std_logic_vector( EP,ROMDATA_W ), conv_std_logic_vector( EP+DM,ROMDATA_W ), conv_std_logic_vector( FM,ROMDATA_W ), conv_std_logic_vector( FM+DM,ROMDATA_W ), conv_std_logic_vector( FM+EP,ROMDATA_W ), conv_std_logic_vector( FM+EP+DM,ROMDATA_W ), conv_std_logic_vector( GP,ROMDATA_W ), conv_std_logic_vector( GP+DM,ROMDATA_W ), conv_std_logic_vector( GP+EP,ROMDATA_W ), conv_std_logic_vector( GP+EP+DM,ROMDATA_W ), conv_std_logic_vector( GP+FM,ROMDATA_W ), conv_std_logic_vector( GP+FM+DM,ROMDATA_W ), conv_std_logic_vector( GP+FM+EP,ROMDATA_W ), conv_std_logic_vector( GP+FM+EP+DM,ROMDATA_W ) ); begin process(clk) begin if clk = '1' and clk'event then datao <= rom( CONV_INTEGER(UNSIGNED(addr)) ); end if; end process; end RTL;  

 

-- 5:0 -- 5:4 = select matrix row (1 out of 4) -- 3:0 = select precomputed MAC ( 1 out of 16) library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_arith.all; use WORK.MDCT_PKG.all; entity ROME is port( addr : in STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); clk : in STD_LOGIC; datao : out STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0) ); end ROME; architecture RTL of ROME is type ROM_TYPE is array (0 to (2**ROMADDR_W)-1) of STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0); constant rom : ROM_TYPE := ( (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP,ROMDATA_W ), conv_std_logic_vector( AP+AP+AP+AP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( CM+BM,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), conv_std_logic_vector( CP+BM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( BP+CM,ROMDATA_W ), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( BP+CP,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), (others => '0'), (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AM+AM,ROMDATA_W ), conv_std_logic_vector( AM,ROMDATA_W ), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AP+AP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( AP,ROMDATA_W ), conv_std_logic_vector( AM,ROMDATA_W ), (others => '0'), (others => '0'), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), conv_std_logic_vector( BP+CM,ROMDATA_W ), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( BM+CM,ROMDATA_W ), (others => '0'), conv_std_logic_vector( CM,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), (others => '0'), conv_std_logic_vector( CP+BP,ROMDATA_W ), conv_std_logic_vector( BP,ROMDATA_W ), conv_std_logic_vector( CP+BM,ROMDATA_W ), conv_std_logic_vector( BM,ROMDATA_W ), conv_std_logic_vector( CP,ROMDATA_W ), (others => '0') ); begin process(clk) begin if clk = '1' and clk'event then datao <= rom(CONV_INTEGER(UNSIGNED(addr)) ); end if; end process; end RTL;
0 Kudos
Altera_Forum
Honored Contributor II
911 Views

The question isn't clear. The ROM instances itself don't know about odd or even address, it's a matter how you connect address and data line externally, which isn't shown in your post. 

 

Ignorant question: why do you think to need to split the ROM in odd and even at all? For hardware processors, odd and even are used when e.g. two 8-bit ROMs are connected to a 16-bit databus. This won't be necessary in FPGA where you can define a 16-bit ROM directly.
0 Kudos
Altera_Forum
Honored Contributor II
911 Views

 

--- Quote Start ---  

Ignorant question: why do you think to need to split the ROM in odd and even at all? For hardware processors, odd and even are used when e.g. two 8-bit ROMs are connected to a 16-bit databus. This won't be necessary in FPGA where you can define a 16-bit ROM directly. 

--- Quote End ---  

 

 

Hai FvM, 

 

Actually I get the code in open source and I don't know why the ROM is splits to odd and even. That is the exact question that I try to ask. I build the ROM table refer to the code, but I don't understand how they manage the input address with the constant value.  

 

However, how to build the ROM table if I have eight constant values that will be multiply with eight input data? Is it not necessary if I split the constant to two ROM table (4 constant each ROM)?.. Thanks in advance
0 Kudos
Altera_Forum
Honored Contributor II
911 Views

How are those ROMs instantiated in the higher level component? If you want to write back a table with the input => output assignments in each ROM, you just need to read the data values in the order they are listed (and remember that (others => '0') means a data vector with all zeros). For example for ROMO: 

 

 

 

addr 

data 

 

 

000000 

 

 

000001 

GP 

 

 

000010 

FP 

 

 

000011 

FP+GP 

 

 

000100 

EP 

 

 

000101 

EP+GP 

 

 

000110 

EP+FP 

 

 

000111 

EP+FP+GP 

 

 

001000 

DP 

 

 

001001 

DP+GP 

 

 

001010 

DP+FP 

 

 

001011 

DP+FP+GP 

 

 

001100 

DP+EP 

 

 

001101 

DP+EP+GP 

 

 

001110 

DP+EP+FP 

 

 

001111 

DP+EP+FP+GP 

 

 

010000 

 

 

010001 

FM 

 

 

010010 

DM 

 

 

etc... 

That said, I think you could replace those ROMs by the actual arithmetic operations they are supposed to accelerate. The synthesizer should be smart enough to optimize this and I'm not sure that using a ROM block for that is actually a good optimization.
0 Kudos
Altera_Forum
Honored Contributor II
911 Views

Hai Daixiwen, 

 

Actually I want to create a ROM table with 8 constant values. All the constant values are in fixed point number (0.123,0.871,-0.99,..etc). In the main project, an input of std_logic_vector (7 downto 0) is used as an address for the ROM. Out of the topic, how to convert the fixed point number to std_logic_vector? Thanks in advance
0 Kudos
Altera_Forum
Honored Contributor II
911 Views

You can use the same principle and do the conversion from constant float to integer by doing a multiplication in each assignment, but if you have some time I'd suggest to use the new VHDL fixed point signed type. Then you can directly use those values and your code will be a lot easier to read. 

This type isn't officially supported in Quartus yet, but you can use a compatibility library and then use the type in your VHDL files. Have a look at this thread (http://www.alteraforum.com/forum/showthread.php?t=36362) for more information.
0 Kudos
Altera_Forum
Honored Contributor II
911 Views

Hai Daixiwen, 

 

I use to_slv function to convert the floating point to std_logic_vector type. Btw, thanks for your helps :)
0 Kudos
Reply