XST: Inferring dual-port RAM from VHDL with BlockRAM

Hi all,

Maybe this question has been asked before, but I couldn't find a suitable answer on this group until now. Having followed the coding styles recommended by Xilinx, I ended up with the following code:

library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;

entity dual_port_ram is generic ( WIDTH : integer := 32; DEPTH : integer := 10 ); port ( w_clk : in std_logic; w_en_in : in std_logic; w_addr_in : in std_logic_vector(DEPTH-1 downto 0); w_data_in : in std_logic_vector(WIDTH-1 downto 0);

r_clk : in std_logic; r_addr_in : in std_logic_vector(DEPTH-1 downto 0); r_data_out : out std_logic_vector(WIDTH-1 downto 0) ); end entity;

architecture xilinx of dual_port_ram is

type memory_type is array (natural range ) of std_logic_vector(WIDTH-1 downto 0); signal memory : memory_type(2**DEPTH-1 downto 0);

begin

write : process(w_clk) begin if w_clk'event and w_clk = '1' then if w_en_in = '1' then memory(to_integer(unsigned(w_addr_in)))

Reply to
Acciduzzu
Loading thread data ...

What logic family? If I recall correctly, Virtex, VirtexE, Spartan-2 and Spartan-2E all do not support Read_First, they only support Read-After-Write.

You might try targeting Virtex-2, Virtex-2 pro or Spartan-3.

--Å_?il Hays Phil_hays at posting domain should work for email

Reply to
Phil Hays

Hi Phil,

I am targeting a Spartan-IIe btw. What I do not know is what that read/write synchronization is. Maybe you know also how I can infer a dual-ram for Spartan-IIe?

Cheers

Reply to
Acciduzzu

If you cut & pasted from your code, I don't see anything wrong. The READ_FIRST should only be an issue when reading from / writing to the same port. Verify in your test case that you're not using the same clock and address in both ports such that the code sees that you "want" a single port memory even though the code should normally infer a dual-port.

If you are tying things together in the upper module, perhaps you can force the dual_port_ram entity not to be "optimized" into the single port by using compiler directives.

Reply to
John_H

If you cut & pasted from your code, I don't see anything wrong. The READ_FIRST should only be an issue when reading from / writing to the same port. Verify in your test case that you're not using the same clock and address in both ports such that the code sees that you "want" a single port memory even though the code should normally infer a dual-port.

If you are tying things together in the upper module, perhaps you can force the dual_port_ram entity not to be "optimized" into the single port by using compiler directives.

Reply to
John_H

BlockRAM read during write: In Virtex and Spartan2, (i.e. before Virtex-II and Spartan3,) a write operation also performs a read of the new data and puts it on the Do lines. (Nice, but not very useful)

In Virtex-II and Spartan3, the user can specify one of 3 options:

  1. Write before read (as described above),
  2. Read before write (i.e. reald the old data that is being overwritten)
  3. "no change", hold Do unchanged , whatever it was before.

Note that this only affects the read data output during a write operation, something most dsigners might not really be interested in. But if you want to read the previous data while you right the new one, then Virtex-II and Spartan3 offer an interesting option.

This is all clearly described in the data sheet / user guide. Peter Alfke

Reply to
Peter Alfke

READ_FIRST is one of a few new modes added to the BLOCKRAM functionality for the Virtex-II devices and later. This mode will put the "old data" on the output of the port being written to before writing the new contents to them memory array. Since Spartan-IIE is an older device using the previous architecture BlockRAM, it does not support this feature. To be honest, I do not think that message fully explains the problem though. Synthesis tools look at templates to decide how to transform code like this into appropriate resources. The code you chose looked most like the templates it expect to see to create a READ_FIRST RAM and thus that is why you got the result you saw. If you look at the XST Users Guide and take the code example for the two clock read-through RAM, it should be able to create the appropriate BlockRAM for the Spartan-IIE architecture. I would modify your code like the following and it should be able to create BlockRAMs for you:

---- Begining of code ------

library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;

entity dual_port_ram is generic ( WIDTH : integer := 32; DEPTH : integer := 10 ); port ( w_clk : in std_logic; w_en_in : in std_logic; w_addr_in : in std_logic_vector(DEPTH-1 downto 0); w_data_in : in std_logic_vector(WIDTH-1 downto 0);

r_clk : in std_logic; r_addr_in : in std_logic_vector(DEPTH-1 downto 0); r_data_out : out std_logic_vector(WIDTH-1 downto 0) ); end entity;

architecture xilinx of dual_port_ram is

type memory_type is array (natural range ) of std_logic_vector(WIDTH-1 downto 0); signal memory : memory_type(2**DEPTH-1 downto 0);

signal r_addr_int: std_logic_vector(DEPTH-1 downto 0);

begin

write : process(w_clk) begin if w_clk'event and w_clk = '1' then if w_en_in = '1' then memory(to_integer(unsigned(w_addr_in)))

Reply to
Brian Philofsky

Yes, you were right! Actually I had done the same mod to the code since I came to the same conclusion in the mean time. The new RAM module has now a boolean generic which selects between the two types of sync.

Thanks.

Reply to
Acciduzzu

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.