ram: Rework main RAM interface
This replaces the simple_ram_behavioural and mw_soc_memory modules with a common wishbone_bram_wrapper.vhdl that interfaces the pipelined WB with a lower-level RAM module, along with an FPGA and a sim variants of the latter. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>pull/118/head
							parent
							
								
									9a63c098a5
								
							
						
					
					
						commit
						8e0389b973
					
				@ -0,0 +1,83 @@
 | 
			
		||||
-- Single port Block RAM with one cycle output buffer
 | 
			
		||||
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.std_logic_unsigned.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
use std.textio.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
 | 
			
		||||
entity main_bram is
 | 
			
		||||
    generic(
 | 
			
		||||
	WIDTH        : natural := 64;
 | 
			
		||||
	HEIGHT_BITS  : natural := 1024;
 | 
			
		||||
	MEMORY_SIZE  : natural := 65536;
 | 
			
		||||
	RAM_INIT_FILE : string
 | 
			
		||||
	);
 | 
			
		||||
    port(
 | 
			
		||||
	clk  : in std_logic;
 | 
			
		||||
	addr : in std_logic_vector(HEIGHT_BITS - 1 downto 0) ;
 | 
			
		||||
	di   : in std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
	do   : out std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
	sel  : in std_logic_vector((WIDTH/8)-1 downto 0);
 | 
			
		||||
	re   : in std_ulogic;
 | 
			
		||||
	we   : in std_ulogic
 | 
			
		||||
	);
 | 
			
		||||
end entity main_bram;
 | 
			
		||||
 | 
			
		||||
architecture behaviour of main_bram is
 | 
			
		||||
 | 
			
		||||
    constant WIDTH_BYTES : natural := WIDTH / 8;
 | 
			
		||||
 | 
			
		||||
    -- RAM type definition
 | 
			
		||||
    type ram_t is array(0 to (MEMORY_SIZE / WIDTH_BYTES) - 1) of std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
 | 
			
		||||
    -- RAM loading
 | 
			
		||||
    impure function init_ram(name : STRING) return ram_t is
 | 
			
		||||
        file ram_file : text open read_mode is name;
 | 
			
		||||
        variable ram_line : line;
 | 
			
		||||
        variable temp_word : std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
        variable temp_ram : ram_t := (others => (others => '0'));
 | 
			
		||||
    begin
 | 
			
		||||
        for i in 0 to (MEMORY_SIZE / WIDTH_BYTES) - 1 loop
 | 
			
		||||
            exit when endfile(ram_file);
 | 
			
		||||
            readline(ram_file, ram_line);
 | 
			
		||||
            hread(ram_line, temp_word);
 | 
			
		||||
            temp_ram(i) := temp_word;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        return temp_ram;
 | 
			
		||||
    end function;
 | 
			
		||||
 | 
			
		||||
    -- RAM instance
 | 
			
		||||
    signal memory : ram_t := init_ram(RAM_INIT_FILE);
 | 
			
		||||
    attribute ram_style : string;
 | 
			
		||||
    attribute ram_style of memory : signal is "block";
 | 
			
		||||
    attribute ram_decomp : string;
 | 
			
		||||
    attribute ram_decomp of memory : signal is "power";
 | 
			
		||||
 | 
			
		||||
    -- Others
 | 
			
		||||
    signal obuf : std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
begin
 | 
			
		||||
 | 
			
		||||
    -- Actual RAM template    
 | 
			
		||||
    memory_0: process(clk)
 | 
			
		||||
    begin
 | 
			
		||||
	if rising_edge(clk) then
 | 
			
		||||
	    if we = '1' then
 | 
			
		||||
		for i in 0 to 7 loop
 | 
			
		||||
		    if sel(i) = '1' then
 | 
			
		||||
			memory(conv_integer(addr))((i + 1) * 8 - 1 downto i * 8) <=
 | 
			
		||||
			    di((i + 1) * 8 - 1 downto i * 8);
 | 
			
		||||
		    end if;
 | 
			
		||||
		end loop;
 | 
			
		||||
	    end if;
 | 
			
		||||
	    if re = '1' then
 | 
			
		||||
		obuf <= memory(conv_integer(addr));
 | 
			
		||||
	    end if;
 | 
			
		||||
	    do <= obuf;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
end architecture behaviour;
 | 
			
		||||
@ -1,112 +0,0 @@
 | 
			
		||||
-- Based on:
 | 
			
		||||
-- The Potato Processor - A simple processor for FPGAs
 | 
			
		||||
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
 | 
			
		||||
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.std_logic_unsigned.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
use std.textio.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
 | 
			
		||||
use work.pp_utilities.all;
 | 
			
		||||
 | 
			
		||||
--! @brief Simple memory module for use in Wishbone-based systems.
 | 
			
		||||
entity mw_soc_memory 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 mw_soc_memory;
 | 
			
		||||
 | 
			
		||||
architecture behaviour of mw_soc_memory is
 | 
			
		||||
    -- RAM type definition
 | 
			
		||||
    type ram_t is array(0 to (MEMORY_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
 | 
			
		||||
 | 
			
		||||
    -- RAM loading
 | 
			
		||||
    impure function init_ram(name : STRING) return ram_t is
 | 
			
		||||
        file ram_file : text open read_mode is name;
 | 
			
		||||
        variable ram_line : line;
 | 
			
		||||
        variable temp_word : std_logic_vector(63 downto 0);
 | 
			
		||||
        variable temp_ram : ram_t := (others => (others => '0'));
 | 
			
		||||
    begin
 | 
			
		||||
        for i in 0 to (MEMORY_SIZE/8)-1 loop
 | 
			
		||||
            exit when endfile(ram_file);
 | 
			
		||||
            readline(ram_file, ram_line);
 | 
			
		||||
            hread(ram_line, temp_word);
 | 
			
		||||
            temp_ram(i) := temp_word;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        return temp_ram;
 | 
			
		||||
    end function;
 | 
			
		||||
 | 
			
		||||
    -- RAM instance
 | 
			
		||||
    signal memory : ram_t := init_ram(RAM_INIT_FILE);
 | 
			
		||||
    attribute ram_style : string;
 | 
			
		||||
    attribute ram_style of memory : signal is "block";
 | 
			
		||||
    attribute ram_decomp : string;
 | 
			
		||||
    attribute ram_decomp of memory : signal is "power";
 | 
			
		||||
 | 
			
		||||
    -- RAM interface
 | 
			
		||||
    constant ram_addr_bits : integer := log2(MEMORY_SIZE) - 3;
 | 
			
		||||
    signal ram_addr : std_logic_vector(ram_addr_bits - 1 downto 0);
 | 
			
		||||
    signal ram_di   : std_logic_vector(63 downto 0);
 | 
			
		||||
    signal ram_do   : std_logic_vector(63 downto 0);
 | 
			
		||||
    signal ram_sel  : std_logic_vector(7 downto 0);
 | 
			
		||||
    signal ram_we   : std_ulogic;
 | 
			
		||||
 | 
			
		||||
    -- Others
 | 
			
		||||
    signal ram_obuf      : std_logic_vector(63 downto 0);
 | 
			
		||||
    signal ack, ack_obuf : std_ulogic;
 | 
			
		||||
begin
 | 
			
		||||
 | 
			
		||||
    -- Actual RAM template    
 | 
			
		||||
    memory_0: process(clk)
 | 
			
		||||
    begin
 | 
			
		||||
	if rising_edge(clk) then
 | 
			
		||||
	    if ram_we = '1' then
 | 
			
		||||
		for i in 0 to 7 loop
 | 
			
		||||
		    if ram_sel(i) = '1' then
 | 
			
		||||
			memory(conv_integer(ram_addr))((i + 1) * 8 - 1 downto i * 8) <=
 | 
			
		||||
			    ram_di((i + 1) * 8 - 1 downto i * 8);
 | 
			
		||||
		    end if;
 | 
			
		||||
		end loop;
 | 
			
		||||
	    end if;
 | 
			
		||||
	    ram_do <= memory(conv_integer(ram_addr));
 | 
			
		||||
	    ram_obuf <= ram_do;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    -- Wishbone interface
 | 
			
		||||
    ram_addr <= wishbone_in.adr(ram_addr_bits + 2 downto 3);
 | 
			
		||||
    ram_di <= wishbone_in.dat;
 | 
			
		||||
    ram_sel <= wishbone_in.sel;
 | 
			
		||||
    ram_we <= wishbone_in.we and wishbone_in.stb and wishbone_in.cyc;
 | 
			
		||||
    wishbone_out.stall <= '0';
 | 
			
		||||
    wishbone_out.ack <= ack_obuf;
 | 
			
		||||
    wishbone_out.dat <= ram_obuf;
 | 
			
		||||
 | 
			
		||||
    wb_0: process(clk)
 | 
			
		||||
    begin
 | 
			
		||||
	if rising_edge(clk) then
 | 
			
		||||
	    if rst = '1' or wishbone_in.cyc = '0' then
 | 
			
		||||
		ack_obuf <= '0';
 | 
			
		||||
		ack <= '0';
 | 
			
		||||
	    else
 | 
			
		||||
		ack <= wishbone_in.stb;
 | 
			
		||||
		ack_obuf <= ack;
 | 
			
		||||
	    end if;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
end architecture behaviour;
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
-- Single port Block RAM with one cycle output buffer
 | 
			
		||||
--
 | 
			
		||||
-- Simulated via C helpers
 | 
			
		||||
 | 
			
		||||
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.sim_bram_helpers.all;
 | 
			
		||||
 | 
			
		||||
entity main_bram is
 | 
			
		||||
    generic(
 | 
			
		||||
	WIDTH        : natural := 64;
 | 
			
		||||
	HEIGHT_BITS  : natural := 1024;
 | 
			
		||||
	MEMORY_SIZE  : natural := 65536;
 | 
			
		||||
	RAM_INIT_FILE : string
 | 
			
		||||
	);
 | 
			
		||||
    port(
 | 
			
		||||
	clk  : in std_logic;
 | 
			
		||||
	addr : in std_logic_vector(HEIGHT_BITS - 1 downto 0) ;
 | 
			
		||||
	di   : in std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
	do   : out std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
	sel  : in std_logic_vector((WIDTH/8)-1 downto 0);
 | 
			
		||||
	re   : in std_ulogic;
 | 
			
		||||
	we   : in std_ulogic
 | 
			
		||||
	);
 | 
			
		||||
end entity main_bram;
 | 
			
		||||
 | 
			
		||||
architecture sim of main_bram is
 | 
			
		||||
 | 
			
		||||
    constant WIDTH_BYTES : natural := WIDTH / 8;
 | 
			
		||||
    constant pad_zeros   : std_ulogic_vector(log2(WIDTH_BYTES)-1 downto 0)
 | 
			
		||||
	:= (others => '0');
 | 
			
		||||
 | 
			
		||||
    signal identifier : integer := behavioural_initialize(filename => RAM_INIT_FILE,
 | 
			
		||||
							  size => MEMORY_SIZE);
 | 
			
		||||
    -- Others
 | 
			
		||||
    signal obuf : std_logic_vector(WIDTH-1 downto 0);
 | 
			
		||||
begin
 | 
			
		||||
 | 
			
		||||
    -- Actual RAM template    
 | 
			
		||||
    memory_0: process(clk)
 | 
			
		||||
	variable ret_dat_v : std_ulogic_vector(63 downto 0);
 | 
			
		||||
	variable addr64    : std_ulogic_vector(63 downto 0);
 | 
			
		||||
    begin
 | 
			
		||||
	if rising_edge(clk) then
 | 
			
		||||
	    addr64 := (others => '0');
 | 
			
		||||
	    addr64(HEIGHT_BITS + 2 downto 3) := addr;
 | 
			
		||||
	    if we = '1' then	
 | 
			
		||||
		report "RAM writing " & to_hstring(di) & " to " &
 | 
			
		||||
		    to_hstring(addr & pad_zeros) & " sel:" & to_hstring(sel);
 | 
			
		||||
		behavioural_write(di, addr64, to_integer(unsigned(sel)), identifier);
 | 
			
		||||
	    end if;
 | 
			
		||||
	    if re = '1' then
 | 
			
		||||
		behavioural_read(ret_dat_v, addr64, to_integer(unsigned(sel)), identifier);
 | 
			
		||||
		report "RAM reading from " & to_hstring(addr & pad_zeros) &
 | 
			
		||||
		    " returns " & to_hstring(ret_dat_v);
 | 
			
		||||
		obuf <= ret_dat_v(obuf'left downto 0);
 | 
			
		||||
	    end if;
 | 
			
		||||
	    do <= obuf;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
end architecture sim;
 | 
			
		||||
@ -1,133 +0,0 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
use std.textio.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
use work.simple_ram_behavioural_helpers.all;
 | 
			
		||||
 | 
			
		||||
entity mw_soc_memory is
 | 
			
		||||
    generic (
 | 
			
		||||
        RAM_INIT_FILE  : string;
 | 
			
		||||
        MEMORY_SIZE    : integer;
 | 
			
		||||
	PIPELINE_DEPTH : integer := 1
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    port (
 | 
			
		||||
        clk          : in std_ulogic;
 | 
			
		||||
        rst          : in std_ulogic;
 | 
			
		||||
 | 
			
		||||
        wishbone_in  : in wishbone_master_out;
 | 
			
		||||
        wishbone_out : out wishbone_slave_out
 | 
			
		||||
        );
 | 
			
		||||
end mw_soc_memory;
 | 
			
		||||
 | 
			
		||||
architecture behave of mw_soc_memory is
 | 
			
		||||
    type wishbone_state_t is (IDLE, ACK);
 | 
			
		||||
 | 
			
		||||
    signal state      : wishbone_state_t := IDLE;
 | 
			
		||||
    signal ret_ack    : std_ulogic := '0';
 | 
			
		||||
    signal identifier : integer := behavioural_initialize(filename => RAM_INIT_FILE, size => MEMORY_SIZE);
 | 
			
		||||
    signal reload     : integer := 0;
 | 
			
		||||
    signal ret_dat    : wishbone_data_type;
 | 
			
		||||
 | 
			
		||||
    subtype pipe_idx_t is integer range 0 to PIPELINE_DEPTH-1;
 | 
			
		||||
    type pipe_ack_t is array(pipe_idx_t) of std_ulogic;
 | 
			
		||||
    type pipe_dat_t is array(pipe_idx_t) of wishbone_data_type;
 | 
			
		||||
begin
 | 
			
		||||
 | 
			
		||||
    pipe_big: if PIPELINE_DEPTH > 1 generate
 | 
			
		||||
	signal pipe_ack : pipe_ack_t;
 | 
			
		||||
	signal pipe_dat : pipe_dat_t;
 | 
			
		||||
    begin
 | 
			
		||||
	wishbone_out.stall <= '0';
 | 
			
		||||
	wishbone_out.ack <= pipe_ack(0);
 | 
			
		||||
	wishbone_out.dat <= pipe_dat(0);
 | 
			
		||||
 | 
			
		||||
	pipe_big_sync: process(clk)
 | 
			
		||||
	begin	
 | 
			
		||||
	    if rising_edge(clk) then
 | 
			
		||||
		pipe_stages: for i in 0 to PIPELINE_DEPTH-2 loop
 | 
			
		||||
		    pipe_ack(i) <= pipe_ack(i+1);
 | 
			
		||||
		    pipe_dat(i) <= pipe_dat(i+1);
 | 
			
		||||
		end loop;
 | 
			
		||||
		pipe_ack(PIPELINE_DEPTH-1) <= ret_ack;
 | 
			
		||||
		pipe_dat(PIPELINE_DEPTH-1) <= ret_dat;
 | 
			
		||||
	    end if;
 | 
			
		||||
	end process;
 | 
			
		||||
    end generate;
 | 
			
		||||
 | 
			
		||||
    pipe_one: if PIPELINE_DEPTH = 1 generate
 | 
			
		||||
	signal pipe_ack : std_ulogic;
 | 
			
		||||
	signal pipe_dat : wishbone_data_type;
 | 
			
		||||
    begin
 | 
			
		||||
	wishbone_out.stall <= '0';
 | 
			
		||||
	wishbone_out.ack <= pipe_ack;
 | 
			
		||||
	wishbone_out.dat <= pipe_dat;
 | 
			
		||||
 | 
			
		||||
	pipe_one_sync: process(clk)
 | 
			
		||||
	begin
 | 
			
		||||
	    if rising_edge(clk) then
 | 
			
		||||
		pipe_ack <= ret_ack;
 | 
			
		||||
		pipe_dat <= ret_dat;
 | 
			
		||||
	    end if;
 | 
			
		||||
	end process;
 | 
			
		||||
    end generate;
 | 
			
		||||
 | 
			
		||||
    pipe_none: if PIPELINE_DEPTH = 0 generate
 | 
			
		||||
    begin
 | 
			
		||||
	wishbone_out.ack <= ret_ack;
 | 
			
		||||
	wishbone_out.dat <= ret_dat;
 | 
			
		||||
	wishbone_out.stall <= wishbone_in.cyc and not ret_ack;
 | 
			
		||||
    end generate;
 | 
			
		||||
    
 | 
			
		||||
    wishbone_process: process(clk)
 | 
			
		||||
	variable ret_dat_v : wishbone_data_type;
 | 
			
		||||
	variable adr       : std_ulogic_vector(63 downto 0);
 | 
			
		||||
    begin
 | 
			
		||||
        if rising_edge(clk) then
 | 
			
		||||
            if rst = '1' then
 | 
			
		||||
                state <= IDLE;
 | 
			
		||||
                ret_ack <= '0';
 | 
			
		||||
            else
 | 
			
		||||
                ret_dat <= x"FFFFFFFFFFFFFFFF";
 | 
			
		||||
		ret_ack <= '0';
 | 
			
		||||
 | 
			
		||||
                -- Active
 | 
			
		||||
                if wishbone_in.cyc = '1' then
 | 
			
		||||
                    case state is
 | 
			
		||||
                        when IDLE =>
 | 
			
		||||
                            if wishbone_in.stb = '1' then
 | 
			
		||||
				adr := (wishbone_in.adr'left downto 0 => wishbone_in.adr,
 | 
			
		||||
					others => '0');
 | 
			
		||||
                                -- write
 | 
			
		||||
                                if wishbone_in.we = '1' then
 | 
			
		||||
                                    assert not(is_x(wishbone_in.dat)) and not(is_x(wishbone_in.adr)) severity failure;
 | 
			
		||||
                                    report "RAM writing " & to_hstring(wishbone_in.dat) & " to " & to_hstring(wishbone_in.adr);
 | 
			
		||||
                                    behavioural_write(wishbone_in.dat, adr, to_integer(unsigned(wishbone_in.sel)), identifier);
 | 
			
		||||
                                    reload <= reload + 1;
 | 
			
		||||
                                    ret_ack <= '1';
 | 
			
		||||
				    if PIPELINE_DEPTH = 0 then
 | 
			
		||||
					state <= ACK;
 | 
			
		||||
				    end if;
 | 
			
		||||
                                else
 | 
			
		||||
                                    behavioural_read(ret_dat_v, adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload);
 | 
			
		||||
                                    report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat_v);
 | 
			
		||||
				    ret_dat <= ret_dat_v;
 | 
			
		||||
                                    ret_ack <= '1';
 | 
			
		||||
				    if PIPELINE_DEPTH = 0 then
 | 
			
		||||
					state <= ACK;
 | 
			
		||||
				    end if;
 | 
			
		||||
                                end if;
 | 
			
		||||
                            end if;
 | 
			
		||||
                        when ACK =>
 | 
			
		||||
                            state <= IDLE;
 | 
			
		||||
                    end case;
 | 
			
		||||
                else
 | 
			
		||||
                    state <= IDLE;
 | 
			
		||||
                end if;
 | 
			
		||||
            end if;
 | 
			
		||||
        end if;
 | 
			
		||||
    end process;
 | 
			
		||||
end behave;
 | 
			
		||||
@ -1,246 +0,0 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
 | 
			
		||||
entity simple_ram_behavioural_tb is
 | 
			
		||||
end simple_ram_behavioural_tb;
 | 
			
		||||
 | 
			
		||||
architecture behave of simple_ram_behavioural_tb is
 | 
			
		||||
    signal clk          : std_ulogic;
 | 
			
		||||
    signal rst          : std_ulogic := '1';
 | 
			
		||||
 | 
			
		||||
    constant clk_period : time := 10 ns;
 | 
			
		||||
 | 
			
		||||
    signal w_in         : wishbone_slave_out;
 | 
			
		||||
    signal w_out        : wishbone_master_out;
 | 
			
		||||
 | 
			
		||||
    impure function to_adr(a: integer) return std_ulogic_vector is
 | 
			
		||||
    begin
 | 
			
		||||
	return std_ulogic_vector(to_unsigned(a, w_out.adr'length));
 | 
			
		||||
    end;
 | 
			
		||||
begin
 | 
			
		||||
    simple_ram_0: entity work.mw_soc_memory
 | 
			
		||||
        generic map (
 | 
			
		||||
            RAM_INIT_FILE => "simple_ram_behavioural_tb.bin",
 | 
			
		||||
            MEMORY_SIZE => 16
 | 
			
		||||
            )
 | 
			
		||||
        port map (
 | 
			
		||||
            clk => clk,
 | 
			
		||||
            rst => rst,
 | 
			
		||||
            wishbone_out => w_in,
 | 
			
		||||
            wishbone_in => w_out
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
    clock: process
 | 
			
		||||
    begin
 | 
			
		||||
        clk <= '1';
 | 
			
		||||
        wait for clk_period / 2;
 | 
			
		||||
        clk <= '0';
 | 
			
		||||
        wait for clk_period / 2;
 | 
			
		||||
    end process clock;
 | 
			
		||||
 | 
			
		||||
    stim: process
 | 
			
		||||
    begin
 | 
			
		||||
        w_out.adr <= (others => '0');
 | 
			
		||||
        w_out.dat <= (others => '0');
 | 
			
		||||
        w_out.cyc <= '0';
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        w_out.sel <= (others => '0');
 | 
			
		||||
        w_out.we  <= '0';
 | 
			
		||||
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        rst <= '0';
 | 
			
		||||
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
 | 
			
		||||
        w_out.cyc <= '1';
 | 
			
		||||
 | 
			
		||||
        -- test various read lengths and alignments
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000001";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(7 downto 0) = x"00" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000001";
 | 
			
		||||
        w_out.adr <= to_adr(1);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(7 downto 0) = x"01" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000001";
 | 
			
		||||
        w_out.adr <= to_adr(7);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(7 downto 0) = x"07" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000011";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(15 downto 0) = x"0100" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000011";
 | 
			
		||||
        w_out.adr <= to_adr(1);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(15 downto 0) = x"0201" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000011";
 | 
			
		||||
        w_out.adr <= to_adr(7);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(15 downto 0) = x"0807" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00001111";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(31 downto 0) = x"03020100" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00001111";
 | 
			
		||||
        w_out.adr <= to_adr(1);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(31 downto 0) = x"04030201" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00001111";
 | 
			
		||||
        w_out.adr <= to_adr(7);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(31 downto 0) = x"0A090807" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"0706050403020100" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(1);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"0807060504030201" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(7);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"0E0D0C0B0A090807" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        -- test various write lengths and alignments
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000001";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        w_out.we <= '1';
 | 
			
		||||
        w_out.dat(7 downto 0) <= x"0F";
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000001";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        w_out.we <= '0';
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(7 downto 0) = x"0F" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(7);
 | 
			
		||||
        w_out.we <= '1';
 | 
			
		||||
        w_out.dat <= x"BADC0FFEBADC0FFE";
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(7);
 | 
			
		||||
        w_out.we <= '0';
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat = x"BADC0FFEBADC0FFE" report to_hstring(w_in.dat);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        assert false report "end of test" severity failure;
 | 
			
		||||
        wait;
 | 
			
		||||
    end process;
 | 
			
		||||
end behave;
 | 
			
		||||
@ -0,0 +1,175 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
 | 
			
		||||
entity wishbone_bram_tb is
 | 
			
		||||
end wishbone_bram_tb;
 | 
			
		||||
 | 
			
		||||
architecture behave of wishbone_bram_tb is
 | 
			
		||||
    signal clk          : std_ulogic;
 | 
			
		||||
    signal rst          : std_ulogic := '1';
 | 
			
		||||
 | 
			
		||||
    constant clk_period : time := 10 ns;
 | 
			
		||||
 | 
			
		||||
    signal w_in         : wishbone_slave_out;
 | 
			
		||||
    signal w_out        : wishbone_master_out;
 | 
			
		||||
 | 
			
		||||
    impure function to_adr(a: integer) return std_ulogic_vector is
 | 
			
		||||
    begin
 | 
			
		||||
	return std_ulogic_vector(to_unsigned(a, w_out.adr'length));
 | 
			
		||||
    end;
 | 
			
		||||
begin
 | 
			
		||||
    simple_ram_0: entity work.wishbone_bram_wrapper
 | 
			
		||||
        generic map (
 | 
			
		||||
            RAM_INIT_FILE => "wishbone_bram_tb.bin",
 | 
			
		||||
            MEMORY_SIZE => 16
 | 
			
		||||
            )
 | 
			
		||||
        port map (
 | 
			
		||||
            clk => clk,
 | 
			
		||||
            rst => rst,
 | 
			
		||||
            wishbone_out => w_in,
 | 
			
		||||
            wishbone_in => w_out
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
    clock: process
 | 
			
		||||
    begin
 | 
			
		||||
        clk <= '1';
 | 
			
		||||
        wait for clk_period / 2;
 | 
			
		||||
        clk <= '0';
 | 
			
		||||
        wait for clk_period / 2;
 | 
			
		||||
    end process clock;
 | 
			
		||||
 | 
			
		||||
    stim: process
 | 
			
		||||
    begin
 | 
			
		||||
        w_out.adr <= (others => '0');
 | 
			
		||||
        w_out.dat <= (others => '0');
 | 
			
		||||
        w_out.cyc <= '0';
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        w_out.sel <= (others => '0');
 | 
			
		||||
        w_out.we  <= '0';
 | 
			
		||||
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        rst <= '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
 | 
			
		||||
        w_out.cyc <= '1';
 | 
			
		||||
 | 
			
		||||
	-- Test read 0
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"0706050403020100" report to_hstring(w_in.dat);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test read 8
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(8);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"0F0E0D0C0B0A0908" report to_hstring(w_in.dat);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test write byte at 0
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "00000001";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        w_out.we <= '1';
 | 
			
		||||
        w_out.dat(7 downto 0) <= x"0F";
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk) and w_in.ack = '1';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test read back
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        w_out.we <= '0';
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"070605040302010F" report to_hstring(w_in.dat);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test write dword at 4
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11110000";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        w_out.we <= '1';
 | 
			
		||||
        w_out.dat(63 downto 32) <= x"BAADFEED";
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk) and w_in.ack = '1';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test read back
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(0);
 | 
			
		||||
        w_out.we <= '0';
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"BAADFEED0302010F" report to_hstring(w_in.dat);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test write qword at 8
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(8);
 | 
			
		||||
        w_out.we <= '1';
 | 
			
		||||
        w_out.dat(63 downto 0) <= x"0001020304050607";
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk) and w_in.ack = '1';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
	-- Test read back
 | 
			
		||||
        w_out.stb <= '1';
 | 
			
		||||
        w_out.sel <= "11111111";
 | 
			
		||||
        w_out.adr <= to_adr(8);
 | 
			
		||||
        w_out.we <= '0';
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        w_out.stb <= '0';
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '1';
 | 
			
		||||
        assert w_in.dat(63 downto 0) = x"0001020304050607" report to_hstring(w_in.dat);
 | 
			
		||||
        wait until rising_edge(clk);
 | 
			
		||||
        assert w_in.ack = '0';
 | 
			
		||||
 | 
			
		||||
        assert false report "end of test" severity failure;
 | 
			
		||||
        wait;
 | 
			
		||||
    end process;
 | 
			
		||||
end behave;
 | 
			
		||||
@ -0,0 +1,76 @@
 | 
			
		||||
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 := log2(MEMORY_SIZE) - 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,
 | 
			
		||||
	    di => wishbone_in.dat,
 | 
			
		||||
	    do => wishbone_out.dat,
 | 
			
		||||
	    sel => wishbone_in.sel,
 | 
			
		||||
	    re => ram_re,
 | 
			
		||||
	    we => ram_we
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    -- Wishbone interface
 | 
			
		||||
    ram_addr <= wishbone_in.adr(ram_addr_bits + 2 downto 3);
 | 
			
		||||
    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
 | 
			
		||||
		ack <= wishbone_in.stb;
 | 
			
		||||
		ack_buf <= ack;
 | 
			
		||||
	    end if;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
end architecture behaviour;
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue