-- Xilinx dualport BRAM template, write-first mode, no delay library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.lx_dad_pkg.all; entity xilinx_dualport_bram is generic ( -- Not all combinations are plausible for BRAMs -- byte width: 8, 9, 32, 36 -- we_width: 1, 2, 3, 4 byte_width : positive := 8; address_width : positive := 8; we_width : positive := 4; port_a_type : BRAM_type := READ_FIRST; port_b_type : BRAM_type := READ_FIRST ); port ( clka : in std_logic; rsta : in std_logic; ena : in std_logic; wea : in std_logic_vector((we_width-1) downto 0); addra : in std_logic_vector((address_width-1) downto 0); dina : in std_logic_vector(((byte_width*we_width)-1) downto 0); douta : out std_logic_vector(((byte_width*we_width)-1) downto 0); clkb : in std_logic; rstb : in std_logic; enb : in std_logic; web : in std_logic_vector((we_width-1) downto 0); addrb : in std_logic_vector((address_width-1) downto 0); dinb : in std_logic_vector(((byte_width*we_width)-1) downto 0); doutb : out std_logic_vector(((byte_width*we_width)-1) downto 0) ); end xilinx_dualport_bram; architecture Behavioral of xilinx_dualport_bram is type ram is array (0 to ((2**address_width) - 1)) of std_logic_vector(((byte_width*we_width)-1) downto 0); shared variable ram_block : ram := (others => (others => '0')); begin -- CLKA process ram_process_a: process begin wait until clka'event and clka = '1'; if ena = '1' then -- Depends on the port type case port_a_type is when READ_FIRST => -- Read if rsta = '1' then douta <= (others => '0'); else douta <= ram_block(to_integer(unsigned(addra))); end if; -- Write for i in 0 to (we_width-1) loop if wea(i) = '1' then ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width)) := dina(((i+1)*byte_width-1) downto (i*byte_width)); end if; end loop; when WRITE_FIRST => -- Write for i in 0 to (we_width-1) loop if wea(i) = '1' then ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width)) := dina(((i+1)*byte_width-1) downto (i*byte_width)); end if; end loop; -- Read if rsta = '1' then douta <= (others => '0'); else douta <= ram_block(to_integer(unsigned(addra))); end if; when NO_CHANGE => -- Write for i in 0 to (we_width-1) loop if wea(i) = '1' then ram_block(to_integer(unsigned(addra)))(((i+1)*byte_width-1) downto (i*byte_width)) := dina(((i+1)*byte_width-1) downto (i*byte_width)); end if; end loop; -- Read (if not writing) if to_integer(unsigned(wea)) = 0 then if rsta = '1' then douta <= (others => '0'); else douta <= ram_block(to_integer(unsigned(addra))); end if; end if; end case; end if; end process; -- CLKB process ram_process_b: process begin wait until clkb'event and clkb = '1'; if enb = '1' then -- Depends on the port type case port_b_type is when READ_FIRST => -- Read if rstb = '1' then doutb <= (others => '0'); else doutb <= ram_block(to_integer(unsigned(addrb))); end if; -- Write for i in 0 to (we_width-1) loop if web(i) = '1' then ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width)) := dinb(((i+1)*byte_width-1) downto (i*byte_width)); end if; end loop; when WRITE_FIRST => -- Write for i in 0 to (we_width-1) loop if web(i) = '1' then ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width)) := dinb(((i+1)*byte_width-1) downto (i*byte_width)); end if; end loop; -- Read if rstb = '1' then doutb <= (others => '0'); else doutb <= ram_block(to_integer(unsigned(addrb))); end if; when NO_CHANGE => -- Write for i in 0 to (we_width-1) loop if web(i) = '1' then ram_block(to_integer(unsigned(addrb)))(((i+1)*byte_width-1) downto (i*byte_width)) := dinb(((i+1)*byte_width-1) downto (i*byte_width)); end if; end loop; -- Read (if not writing) if to_integer(unsigned(web)) = 0 then if rstb = '1' then doutb <= (others => '0'); else doutb <= ram_block(to_integer(unsigned(addrb))); end if; end if; end case; end if; end process; end Behavioral;