library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.textio.all; library work; use work.utils.all; use work.wishbone_types.all; --! @brief Simple memory module for use in Wishbone-based systems. entity wishbone_bram_wrapper is generic( MEMORY_SIZE : natural := 4096; --! Memory size in bytes. RAM_INIT_FILE : string ); port( clk : in std_logic; rst : in std_logic; -- Wishbone interface: wishbone_in : in wishbone_master_out; wishbone_out : out wishbone_slave_out ); end entity wishbone_bram_wrapper; architecture behaviour of wishbone_bram_wrapper is constant ram_addr_bits : integer := log2ceil(MEMORY_SIZE-1) - 3; -- RAM interface signal ram_addr : std_logic_vector(ram_addr_bits - 1 downto 0); signal ram_we : std_ulogic; signal ram_re : std_ulogic; -- Others signal ack, ack_buf : std_ulogic; begin -- Actual RAM template ram_0: entity work.main_bram generic map( WIDTH => 64, HEIGHT_BITS => ram_addr_bits, MEMORY_SIZE => MEMORY_SIZE, RAM_INIT_FILE => RAM_INIT_FILE ) port map( clk => clk, addr => ram_addr, din => wishbone_in.dat, dout => wishbone_out.dat, sel => wishbone_in.sel, re => ram_re, we => ram_we ); -- Wishbone interface ram_addr <= wishbone_in.adr(ram_addr_bits - 1 downto 0); ram_we <= wishbone_in.stb and wishbone_in.cyc and wishbone_in.we; ram_re <= wishbone_in.stb and wishbone_in.cyc and not wishbone_in.we; wishbone_out.stall <= '0'; wishbone_out.ack <= ack_buf; wb_0: process(clk) begin if rising_edge(clk) then if rst = '1' or wishbone_in.cyc = '0' then ack_buf <= '0'; ack <= '0'; else -- On loads, we have a delay cycle due to BRAM bufferring -- but not on stores. So try to send an early ack on a -- store if we aren't behind an existing load ack. -- if ram_we = '1' and ack = '0' then ack_buf <= '1'; else ack <= wishbone_in.stb; ack_buf <= ack; end if; end if; end if; end process; end architecture behaviour;