- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Im trying to get Quartus to infer a vhdl array of record as dual port memory with write side being a 32bit, and read side a N*32bit datawidth. To make it even more difficult, I need it to be inferred as two separate memory banks with two different address pointers on the read side.
Is this possible to do the simple way? Im trying something like this, but it doesnt find the memory, even if I try to add the ramstyle attribute.
--pseudocode (not verified)
type TableEntry is record
x : std_logic_vector(15 downto 0);
y : std_logic_vector(15 downto 0);
size_x : std_logic_vector(15 downto 0);
size_y : std_logic_vector(15 downto 0);
end record;
type TableArray is array (integer range 127 downto 0) of TableEntry;
signal Table : TableArray;
alias write_wordadr : std_logic_vector(2 downto 0) is addr(2 downto 0);
alias wrire_index : std_logic_vector(addr'high-3 downto 0) is addr(addr'high downto 3);
--writing from cpu
case conv_integer(write_wordadr) is
when 0=>
Table(write_index).x <=data(31 downto 16);
Table(write_index).y <=data(15 downto 0);
when 1=>
Table(write_index).size_x <=data(31 downto 16);
Table(write_index).size_y <=data(15 downto 0);
when others=>
end case;
--reading x,y
testx<=Table(posindex).x;
testy<=Table(posindex).y;
--reading size_x,size_y with different index
testsizex<=Table(sizeindex).size_x;
testsizey<=Table(sizeindex).size_y;
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Inferencing rams is only garanteed to work for the code templates, and these will only work for arrays of normal types (like unsigned, std_logic_vector etc). I dont think you will get it to work with record types at all, unless you convert the records to single type arrays.
But you havent posted all of the code, just snippets, so I cannot see if the code is suitable for memory inference in the first place. The code has to follow a certain template before it will work - the ramstyle attribute only works when the templates are followed.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Inferencing rams is only garanteed to work for the code templates, and these will only work for arrays of normal types (like unsigned, std_logic_vector etc). I dont think you will get it to work with record types at all, unless you convert the records to single type arrays. --- Quote End --- I can get it to infer for records. The breaking part seems to be the different adressing schemes or bus widths on both sides, and Quartus doesnt seem to try splitting the record up in smaller blocks. Its all or nothing. --- Quote Start --- But you havent posted all of the code, just snippets, so I cannot see if the code is suitable for memory inference in the first place. The code has to follow a certain template before it will work - the ramstyle attribute only works when the templates are followed. --- Quote End --- I'd be glad for any code that would do this, so my code was just the essence of my current longer code. Of course I could write a implementable proof of concept code but I doubt that will help anyone. PS:Ive just tried to break the record into single signals, and it seems to do what I want. Its just uglier code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It would help. If it wont work when it should, you should raise an enhancement request in altera Mysupport. Given they have only just started to support mixed width dual port inference recently, I doubt they will allow more complex inputs (ie records) without enough ERs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- It would help. If it wont work when it should, you should raise an enhancement request in altera Mysupport. Given they have only just started to support mixed width dual port inference recently, I doubt they will allow more complex inputs (ie records) without enough ERs. --- Quote End --- Ok, I will spend some minutes on this and post a copy here.. Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is an example that builds horribly wrong. I expected Table to be split into any kind of memory even without the ramstyle attrib, but fails. It all goes into ALUT's (stratix III, Q10.1sp1 and Q11.0sp1).
I will try to raise my first ER on this case..
--testing the record to mem instanciation
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity record_mem is
port
(
--write bus
clk1 : in std_logic;
de1 : in std_logic;
adr1 : in std_logic_vector(8 downto 0);
data1 : in std_logic_vector(31 downto 0);
--32bit output from the record array
clk2 : in std_logic;
adr2 : in std_logic_vector(7 downto 0);
data2 : out std_logic_vector(31 downto 0);
--16bit output from the record array
clk3 : in std_logic;
adr3 : in std_logic_vector(7 downto 0);
data3 : out std_logic_vector(15 downto 0);
--8bit output from the record array
clk4 : in std_logic;
adr4 : in std_logic_vector(8 downto 0);
data4 : out std_logic_vector(7 downto 0)
);
end record_mem;
architecture rtl of record_mem is
type TableEntry is record
record_32bit_at_adr0 : std_logic_vector(31 downto 0);
record_16bit_at_adr1_high_word : std_logic_vector(15 downto 0);
record_8bit_at_adr1_low_word_low_byte : std_logic_vector(7 downto 0);
record_8bit_at_adr1_low_word_high_byte : std_logic_vector(7 downto 0);
end record;
type TableArray is array (integer range 255 downto 0) of TableEntry;
signal Table : TableArray;
alias adr1_wordadr : std_logic_vector(0 downto 0) is adr1(0 downto 0);
alias adr1_memidx : std_logic_vector(7 downto 0) is adr1(adr1'high downto 1);
alias adr4_wordadr : std_logic_vector(0 downto 0) is adr4(0 downto 0);
alias adr4_memidx : std_logic_vector(7 downto 0) is adr4(adr4'high downto 1);
begin
write_dp_mem:process (clk1)
begin
if(rising_edge(clk1)) then
if(de1='1') then
case conv_integer(adr1_wordadr) is
when 0=>
Table(conv_integer(adr1_memidx)).record_32bit_at_adr0 <=data1;
when 1=>
Table(conv_integer(adr1_memidx)).record_16bit_at_adr1_high_word <=data1(31 downto 16);
Table(conv_integer(adr1_memidx)).record_8bit_at_adr1_low_word_low_byte <=data1(7 downto 0);
Table(conv_integer(adr1_memidx)).record_8bit_at_adr1_low_word_high_byte <=data1(15 downto 8);
when others=>
end case;
end if;
end if;
end process;
read_32bit_mem:process (clk2)
begin
if(rising_edge(clk2)) then
data2<=Table(conv_integer(adr2)).record_32bit_at_adr0;
end if;
end process;
read_16bit_mem:process (clk3)
begin
if(rising_edge(clk3)) then
data3<=Table(conv_integer(adr3)).record_16bit_at_adr1_high_word;
end if;
end process;
read_8bit_mem:process (clk4)
begin
if(rising_edge(clk4)) then
if(conv_integer(adr4_wordadr)=0) then
data4<=Table(conv_integer(adr4_memidx)).record_8bit_at_adr1_low_word_low_byte;
else
data4<=Table(conv_integer(adr4_memidx)).record_8bit_at_adr1_low_word_high_byte;
end if;
end if;
end process;
end rtl;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think that the memory array definition is unsuitable from the start. Quartus is generally able to infer dual port rams with different port width, you'll find examples in the Quartus software handbook. Why don't you start with a known working example? Copying the record elements as "wires" to and from the memory shouldn't be a problem.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page