//Synthesis attribute ram_style of RAM is distributed reg [31:0] ram[0:15]; reg [3:0] addra_reg; wire [3:0] addra_temp; //Added temporary address signal
always @ (posedge clka) addra_reg <= addra;
always @ (posedge clkb) begin if (write) ram[addrb] <= di; end
assign dob = ram[addrb]; assign doa = ram[addra_temp]; //Using temporary address signal for the RAM
assign addra_temp = addra_reg; //Assigning the registered address signal to the temporary address signal
endmodule
2
Due to a problem with XST, if the address lines for the RAM is registered, XST will infer Block RAM regardless of the synthesis directive.
To work around this problem, use an intermediate address signal:
VHDL:
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;
entity infer_ram is port (doa, dob : out std_logic_vector (31 downto 0); di : in std_logic_vector (31 downto 0); addra, addrb : in std_logic_vector (3 downto 0); clka, clkb, write : in std_logic); end entity;
architecture infer_ram_arch of infer_ram is
type ram_type is array (0 to 15) of std_logic_vector (31 downto 0); signal ram : ram_type; signal addra_reg : std_logic_vector (3 downto 0);
begin
process (clka) is begin if clka'event and clka = '1' then addra_reg <= addra; end if; end process;
process (clkb) is begin if clkb'event and clkb = '1' then if (write = '1') then ram(conv_integer(addrb)) <= di; end if; end if; end process;
dob <= ram(conv_integer(addrb)); doa <= ram(conv_integer(addra_reg));
end architecture;
Work-around:
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;
entity infer_ram is port (doa, dob : out std_logic_vector (31 downto 0); di : in std_logic_vector (31 downto 0); addra, addrb : in std_logic_vector (3 downto 0); clka, clkb, write : in std_logic); end entity;
architecture infer_ram_arch of infer_ram is
type ram_type is array (0 to 15) of std_logic_vector (31 downto 0); signal ram : ram_type; signal addra_reg : std_logic_vector (3 downto 0); signal addra_temp : std_logic_vector (3 downto 0); --Added temporary address signal
begin
process (clka) is begin if clka'event and clka = '1' then addra_reg <= addra; end if; end process;
process (clkb) is begin if clkb'event and clkb = '1' then if (write = '1') then ram(conv_integer(addrb)) <= di; end if; end if; end process;
dob <= ram(conv_integer(addrb)); doa <= ram(conv_integer(addra_temp)); --Using temporary address signal for the RAM
addra_temp <= addra_reg; --Assigning the registered address signal to the temporary address signal