ram: Rework main RAM interface
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 23 Oct 2019 01:08:55 +0000 (12:08 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 30 Oct 2019 02:18:58 +0000 (13:18 +1100)
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>
24 files changed:
Makefile
README.md
core_tb.vhdl
dcache_tb.vhdl
dmi_dtm_tb.vhdl
fpga/main_bram.vhdl [new file with mode: 0644]
fpga/mw_soc_memory.vhdl [deleted file]
icache_tb.vhdl
microwatt.core
scripts/run_test.sh
scripts/test_micropython.py
scripts/test_micropython_long.py
sim_bram.vhdl [new file with mode: 0644]
sim_bram_helpers.vhdl [new file with mode: 0644]
sim_bram_helpers_c.c [new file with mode: 0644]
simple_ram_behavioural.vhdl [deleted file]
simple_ram_behavioural_helpers.vhdl [deleted file]
simple_ram_behavioural_helpers_c.c [deleted file]
simple_ram_behavioural_tb.bin [deleted file]
simple_ram_behavioural_tb.vhdl [deleted file]
soc.vhdl
wishbone_bram_tb.bin [new file with mode: 0644]
wishbone_bram_tb.vhdl [new file with mode: 0644]
wishbone_bram_wrapper.vhdl [new file with mode: 0644]

index 1c68ff40745da014c248db29a7d06de8c3eb3ab4..85a02627dacb57c0a350a6b8f19045867b20deb3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@ GHDL=ghdl
 GHDLFLAGS=--std=08 -Psim-unisim
 CFLAGS=-O2 -Wall
 
-all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb dcache_tb multiply_tb dmi_dtm_tb divider_tb \
-       rotator_tb countzero_tb
+all = core_tb soc_reset_tb icache_tb dcache_tb multiply_tb dmi_dtm_tb divider_tb \
+       rotator_tb countzero_tb wishbone_bram_tb
 
 # XXX
 # loadstore_tb fetch_tb
@@ -35,11 +35,14 @@ helpers.o:
 cache_ram.o:
 plru.o:
 plru_tb.o: plru.o
-icache_tb.o: common.o wishbone_types.o icache.o simple_ram_behavioural.o
-dcache_tb.o: common.o wishbone_types.o dcache.o simple_ram_behavioural.o
 utils.o:
+sim_bram.o: sim_bram_helpers.o utils.o
+wishbone_bram_wrapper.o: wishbone_types.o sim_bram.o utils.o
+wishbone_bram_tb.o: wishbone_bram_wrapper.o
 icache.o: utils.o common.o wishbone_types.o plru.o cache_ram.o utils.o
+icache_tb.o: common.o wishbone_types.o icache.o wishbone_bram_wrapper.o
 dcache.o: utils.o common.o wishbone_types.o plru.o cache_ram.o utils.o
+dcache_tb.o: common.o wishbone_types.o dcache.o wishbone_bram_wrapper.o
 insn_helpers.o:
 loadstore1.o: common.o helpers.o
 logical.o: decode_types.o
@@ -52,11 +55,8 @@ register_file.o: common.o
 rotator.o: common.o
 rotator_tb.o: common.o glibc_random.o ppc_fx_insns.o insn_helpers.o rotator.o
 sim_console.o:
-simple_ram_behavioural_helpers.o:
-simple_ram_behavioural_tb.o: wishbone_types.o simple_ram_behavioural.o
-simple_ram_behavioural.o: wishbone_types.o simple_ram_behavioural_helpers.o
 sim_uart.o: wishbone_types.o sim_console.o
-soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o simple_ram_behavioural.o dmi_dtm_xilinx.o wishbone_debug_master.o
+soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o wishbone_bram_wrapper.o dmi_dtm_xilinx.o wishbone_debug_master.o
 wishbone_arbiter.o: wishbone_types.o
 wishbone_types.o:
 writeback.o: common.o crhelpers.o
@@ -74,17 +74,17 @@ fpga/soc_reset_tb.o: fpga/soc_reset.o
 soc_reset_tb: fpga/soc_reset_tb.o fpga/soc_reset.o
        $(GHDL) -e $(GHDLFLAGS) soc_reset_tb
 
-core_tb: core_tb.o simple_ram_behavioural_helpers_c.o sim_console_c.o sim_jtag_socket_c.o
-       $(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o -Wl,sim_console_c.o -Wl,sim_jtag_socket_c.o $@
+core_tb: core_tb.o sim_bram_helpers_c.o sim_console_c.o sim_jtag_socket_c.o
+       $(GHDL) -e $(GHDLFLAGS) -Wl,sim_bram_helpers_c.o -Wl,sim_console_c.o -Wl,sim_jtag_socket_c.o $@
 
 fetch_tb: fetch_tb.o
        $(GHDL) -e $(GHDLFLAGS) $@
 
 icache_tb: icache_tb.o
-       $(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o $@
+       $(GHDL) -e $(GHDLFLAGS) -Wl,sim_bram_helpers_c.o $@
 
 dcache_tb: dcache_tb.o
-       $(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o $@
+       $(GHDL) -e $(GHDLFLAGS) -Wl,sim_bram_helpers_c.o $@
 
 plru_tb: plru_tb.o
        $(GHDL) -e $(GHDLFLAGS) $@
@@ -107,11 +107,11 @@ countzero_tb: countzero_tb.o
 simple_ram_tb: simple_ram_tb.o
        $(GHDL) -e $(GHDLFLAGS) $@
 
-simple_ram_behavioural_tb: simple_ram_behavioural_helpers_c.o simple_ram_behavioural_tb.o
-       $(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o $@
+wishbone_bram_tb: sim_bram_helpers_c.o wishbone_bram_tb.o
+       $(GHDL) -e $(GHDLFLAGS) -Wl,sim_bram_helpers_c.o $@
 
-dmi_dtm_tb: dmi_dtm_tb.o simple_ram_behavioural_helpers_c.o
-       $(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o $@
+dmi_dtm_tb: dmi_dtm_tb.o sim_bram_helpers_c.o
+       $(GHDL) -e $(GHDLFLAGS) -Wl,sim_bram_helpers_c.o $@
 
 tests = $(sort $(patsubst tests/%.out,%,$(wildcard tests/*.out)))
 
index 86e9e2265754d20044e4e8ee422d54184e82e97e..7c6bc11f6d8946b3767e3807a0a0d9baa470349b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ make
 - Link in the micropython image:
 
 ```
-ln -s ../micropython/ports/powerpc/build/firmware.bin simple_ram_behavioural.bin
+ln -s ../micropython/ports/powerpc/build/firmware.bin main_ram.bin
 ```
 
 - Now run microwatt, sending debug output to /dev/null:
index 672b4246b342b5f786689037075be452cdd61d1f..90fc30c28c5dbcf430b2a40a004ce38ca2e8ca29 100644 (file)
@@ -20,7 +20,7 @@ begin
        generic map(
            SIM => true,
            MEMORY_SIZE => 524288,
-           RAM_INIT_FILE => "simple_ram_behavioural.bin",
+           RAM_INIT_FILE => "main_ram.bin",
            RESET_LOW => false
            )
        port map(
index 0edbdb7a45a1469b84956fda566e9471f8d6886b..437fd7d3312ae9691ce2a1acd00c94fd4b87af9f 100644 (file)
@@ -35,9 +35,9 @@ begin
             );
 
     -- BRAM Memory slave
-    bram0: entity work.mw_soc_memory
+    bram0: entity work.wishbone_bram_wrapper
         generic map(
-            MEMORY_SIZE   => 128,
+            MEMORY_SIZE   => 1024,
             RAM_INIT_FILE => "icache_test.bin"
             )
         port map(
@@ -121,7 +121,6 @@ begin
         d_in.valid <= '1';
        wait until rising_edge(clk);
        d_in.valid <= '0';
-
        wait until rising_edge(clk) and d_out.write_enable = '1';
         assert d_out.valid = '1';
         assert d_out.write_data = x"0000004100000040"
@@ -130,7 +129,10 @@ begin
            " expected 0000004100000040"
            severity failure;
 
-       wait for clk_period*4;
+       wait until rising_edge(clk);
+       wait until rising_edge(clk);
+       wait until rising_edge(clk);
+       wait until rising_edge(clk);
 
         assert false report "end of test" severity failure;
         wait;
index fe60c12356d3412ac3c06ca3f35730dd594ce1b2..069426650e3039cbb0acd36fd93fae39d97a208b 100644 (file)
@@ -50,8 +50,8 @@ begin
            dmi_ack     => dmi_ack
            );
 
-    simple_ram_0: entity work.mw_soc_memory
-       generic map(RAM_INIT_FILE => "simple_ram_behavioural.bin",
+    simple_ram_0: entity work.wishbone_bram_wrapper
+       generic map(RAM_INIT_FILE => "main_ram.bin",
                    MEMORY_SIZE => 524288)
        port map(clk => clk, rst => rst,
                 wishbone_in => wishbone_ram_out,
diff --git a/fpga/main_bram.vhdl b/fpga/main_bram.vhdl
new file mode 100644 (file)
index 0000000..810d60c
--- /dev/null
@@ -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;
diff --git a/fpga/mw_soc_memory.vhdl b/fpga/mw_soc_memory.vhdl
deleted file mode 100644 (file)
index 7e998b2..0000000
+++ /dev/null
@@ -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;
index a50cabe165fb4fca41ee818a6471db32054b03e0..ea5cf3ab9c54924172f9395dfdb947d80755046e 100644 (file)
@@ -36,9 +36,9 @@ begin
             );
 
     -- BRAM Memory slave
-    bram0: entity work.mw_soc_memory
+    bram0: entity work.wishbone_bram_wrapper
         generic map(
-            MEMORY_SIZE   => 128,
+            MEMORY_SIZE   => 1024,
             RAM_INIT_FILE => "icache_test.bin"
             )
         port map(
@@ -70,14 +70,18 @@ begin
         i_out.nia <= (others => '0');
        i_out.stop_mark <= '0';
 
-        wait for 4*clk_period;
+        wait until rising_edge(clk);
+        wait until rising_edge(clk);
+        wait until rising_edge(clk);
+        wait until rising_edge(clk);
 
         i_out.req <= '1';
         i_out.nia <= x"0000000000000004";
 
         wait for 30*clk_period;
+        wait until rising_edge(clk);
 
-        assert i_in.valid = '1';
+        assert i_in.valid = '1' severity failure;
         assert i_in.insn = x"00000001"
            report "insn @" & to_hstring(i_out.nia) &
            "=" & to_hstring(i_in.insn) &
@@ -86,27 +90,29 @@ begin
 
         i_out.req <= '0';
 
-        wait for clk_period;
+        wait until rising_edge(clk);
 
         -- hit
         i_out.req <= '1';
         i_out.nia <= x"0000000000000008";
-        wait for clk_period;
-        assert i_in.valid = '1';
+        wait until rising_edge(clk);
+        wait until rising_edge(clk);
+        assert i_in.valid = '1' severity failure;
         assert i_in.insn = x"00000002"
            report "insn @" & to_hstring(i_out.nia) &
            "=" & to_hstring(i_in.insn) &
            " expected 00000002"
            severity failure;
-        wait for clk_period;
+        wait until rising_edge(clk);
 
         -- another miss
         i_out.req <= '1';
         i_out.nia <= x"0000000000000040";
 
         wait for 30*clk_period;
+        wait until rising_edge(clk);
 
-        assert i_in.valid = '1';
+        assert i_in.valid = '1' severity failure;
         assert i_in.insn = x"00000010"
            report "insn @" & to_hstring(i_out.nia) &
            "=" & to_hstring(i_in.insn) &
@@ -116,13 +122,15 @@ begin
         -- test something that aliases
         i_out.req <= '1';
         i_out.nia <= x"0000000000000100";
-        wait for clk_period;
-        assert i_in.valid = '0';
-        wait for clk_period;
+        wait until rising_edge(clk);
+        wait until rising_edge(clk);
+        assert i_in.valid = '0' severity failure;
+        wait until rising_edge(clk);
 
         wait for 30*clk_period;
+        wait until rising_edge(clk);
 
-        assert i_in.valid = '1';
+        assert i_in.valid = '1' severity failure;
         assert i_in.insn = x"00000040"
            report "insn @" & to_hstring(i_out.nia) &
            "=" & to_hstring(i_in.insn) &
index 35ada86608c9693125d5981fd8968f1420d74f3b..ee48376d52bd4dc056d433c266a4f4a472604f7f 100644 (file)
@@ -36,20 +36,22 @@ filesets:
       - plru.vhdl
       - cache_ram.vhdl
       - core_debug.vhdl
+      - utils.vhdl
     file_type : vhdlSource-2008
 
   soc:
     files:
       - wishbone_arbiter.vhdl
       - wishbone_debug_master.vhdl
+      - wishbone_bram_wrapper.vhdl
       - soc.vhdl
     file_type : vhdlSource-2008
 
   fpga:
     files:
-      - fpga/pp_fifo.vhd
-      - fpga/mw_soc_memory.vhdl
+      - fpga/main_bram.vhdl
       - fpga/soc_reset.vhdl
+      - fpga/pp_fifo.vhd
       - fpga/pp_soc_uart.vhd
       - fpga/pp_utilities.vhd
       - fpga/toplevel.vhdl
index b6f2ee6370d80893b74f3870741cbe32ab4a3798..ef737feda63905f6106539daacd122109d1de014 100755 (executable)
@@ -21,7 +21,7 @@ Y=$(${MICROWATT_DIR}/scripts/hash.py tests/${TEST}.out)
 
 cd $TMPDIR
 
-cp ${MICROWATT_DIR}/tests/${TEST}.bin simple_ram_behavioural.bin
+cp ${MICROWATT_DIR}/tests/${TEST}.bin main_ram.bin
 
 X=$( ${MICROWATT_DIR}/core_tb | ${MICROWATT_DIR}/scripts/hash.py )
 
index d7ffb2d0caf0f8811d3b31b50a19e2e94b4c637c..edc076f61221aa235045a51395b39443cbfcb53b 100755 (executable)
@@ -13,7 +13,7 @@ cwd = os.getcwd()
 os.chdir(tempdir.name)
 
 copyfile(os.path.join(cwd, 'tests/micropython.bin'),
-        os.path.join(tempdir.name, 'simple_ram_behavioural.bin'))
+        os.path.join(tempdir.name, 'main_ram.bin'))
 
 cmd = [ os.path.join(cwd, './core_tb') ]
 
index 805c6b2ca751cc4f292f5e97da56cd5bbf54a91d..6dea3a434fae1f1700ee077a6b45eb012cc78532 100755 (executable)
@@ -13,7 +13,7 @@ cwd = os.getcwd()
 os.chdir(tempdir.name)
 
 copyfile(os.path.join(cwd, 'tests/micropython.bin'),
-        os.path.join(tempdir.name, 'simple_ram_behavioural.bin'))
+        os.path.join(tempdir.name, 'main_ram.bin'))
 
 cmd = [ os.path.join(cwd, './core_tb') ]
 
diff --git a/sim_bram.vhdl b/sim_bram.vhdl
new file mode 100644 (file)
index 0000000..d2d4f1b
--- /dev/null
@@ -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;
diff --git a/sim_bram_helpers.vhdl b/sim_bram_helpers.vhdl
new file mode 100644 (file)
index 0000000..c511a6e
--- /dev/null
@@ -0,0 +1,30 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+package sim_bram_helpers is
+    function behavioural_initialize (filename: String; size: integer) return integer;
+    attribute foreign of behavioural_initialize : function is "VHPIDIRECT behavioural_initialize";
+
+    procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier:integer);
+    attribute foreign of behavioural_read : procedure is "VHPIDIRECT behavioural_read";
+
+    procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer);
+    attribute foreign of behavioural_write : procedure is "VHPIDIRECT behavioural_write";
+end sim_bram_helpers;
+
+package body sim_bram_helpers is
+    function behavioural_initialize (filename: String; size: integer) return integer is
+    begin
+        assert false report "VHPI" severity failure;
+    end behavioural_initialize;
+
+    procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer) is
+    begin
+        assert false report "VHPI" severity failure;
+    end behavioural_read;
+
+    procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer) is
+    begin
+        assert false report "VHPI" severity failure;
+    end behavioural_write;
+end sim_bram_helpers;
diff --git a/sim_bram_helpers_c.c b/sim_bram_helpers_c.c
new file mode 100644 (file)
index 0000000..c5678e7
--- /dev/null
@@ -0,0 +1,258 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#undef DEBUG
+
+#define ALIGN_UP(VAL, SIZE)    (((VAL) + ((SIZE)-1)) & ~((SIZE)-1))
+
+#define vhpi0  2       /* forcing 0 */
+#define vhpi1  3       /* forcing 1 */
+
+struct int_bounds
+{
+       int left;
+       int right;
+       char dir;
+       unsigned int len;
+};
+
+struct fat_pointer
+{
+       void *base;
+       struct int_bounds *bounds;
+};
+
+static char *from_string(void *__p)
+{
+       struct fat_pointer *p = __p;
+       unsigned long len = p->bounds->len;
+       char *m;
+
+       m = malloc(len+1);
+       if (!m) {
+               perror("malloc");
+               exit(1);
+       }
+
+       memcpy(m, p->base, len);
+       m[len] = 0x0;
+
+       return m;
+}
+
+static uint64_t from_std_logic_vector(unsigned char *p, unsigned long len)
+{
+       unsigned long ret = 0;
+
+       if (len > 64) {
+               fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
+               exit(1);
+       }
+
+       for (unsigned long i = 0; i < len; i++) {
+               unsigned char bit;
+
+               if (*p == vhpi0) {
+                       bit = 0;
+               } else if (*p == vhpi1) {
+                       bit = 1;
+               } else {
+                       fprintf(stderr, "%s: bad bit %d\n", __func__, *p);
+                       bit = 0;
+               }
+
+               ret = (ret << 1) | bit;
+               p++;
+       }
+
+       return ret;
+}
+
+static void to_std_logic_vector(unsigned long val, unsigned char *p,
+                               unsigned long len)
+{
+       if (len > 64) {
+               fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
+               exit(1);
+       }
+
+       for (unsigned long i = 0; i < len; i++) {
+               if ((val >> (len-1-i) & 1))
+                       *p = vhpi1;
+               else
+                       *p = vhpi0;
+
+               p++;
+       }
+}
+
+#define MAX_REGIONS 128
+
+struct ram_behavioural {
+       char *filename;
+       unsigned long size;
+       void *m;
+};
+
+static struct ram_behavioural behavioural_regions[MAX_REGIONS];
+static unsigned long region_nr;
+
+unsigned long behavioural_initialize(void *__f, unsigned long size)
+{
+       struct ram_behavioural *r;
+       int fd;
+       struct stat buf;
+       unsigned long tmp_size;
+       void *mem;
+
+       if (region_nr == MAX_REGIONS) {
+               fprintf(stderr, "%s: too many regions, bump MAX_REGIONS\n", __func__);
+               exit(1);
+       }
+
+       r = &behavioural_regions[region_nr];
+
+       r->filename = from_string(__f);
+       r->size = ALIGN_UP(size, getpagesize());
+
+       fd = open(r->filename, O_RDWR);
+       if (fd == -1) {
+               fprintf(stderr, "%s: could not open %s\n", __func__,
+                       r->filename);
+               exit(1);
+       }
+
+       if (fstat(fd, &buf)) {
+               perror("fstat");
+               exit(1);
+       }
+
+       /* XXX Do we need to truncate the underlying file? */
+       tmp_size = ALIGN_UP(buf.st_size, getpagesize());
+
+       if (r->size > tmp_size) {
+               void *m;
+
+               /*
+                * We have to pad the file. Allocate the total size, then
+                * create a space for the file.
+                */
+               mem = mmap(NULL, r->size, PROT_READ|PROT_WRITE,
+                               MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+               if (mem == MAP_FAILED) {
+                       perror("mmap");
+                       exit(1);
+               }
+
+               if (tmp_size) {
+                       munmap(mem, tmp_size);
+
+                       m = mmap(mem, tmp_size, PROT_READ|PROT_WRITE,
+                                       MAP_PRIVATE|MAP_FIXED, fd, 0);
+                       if (m == MAP_FAILED) {
+                               perror("mmap");
+                               exit(1);
+                       }
+                       if (m != mem) {
+                               fprintf(stderr, "%s: mmap(MAP_FIXED) failed\n",
+                                       __func__);
+                               exit(1);
+                       }
+               }
+       } else {
+               mem = mmap(NULL, tmp_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+                               fd, 0);
+               if (mem == MAP_FAILED) {
+                       perror("mmap");
+                       exit(1);
+               }
+       }
+
+       behavioural_regions[region_nr].m = mem;
+       return region_nr++;
+}
+
+void behavioural_read(unsigned char *__val, unsigned char *__addr,
+                       unsigned long sel, int identifier)
+{
+       struct ram_behavioural *r;
+       unsigned long val = 0;
+       unsigned long addr = from_std_logic_vector(__addr, 64);
+       unsigned char *p;
+
+       if (identifier > region_nr) {
+               fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
+               exit(1);
+       }
+
+       r = &behavioural_regions[identifier];
+
+       for (unsigned long i = 0; i < 8; i++) {
+#if 0
+               /* sel only used on writes */
+               if (!(sel & (1UL << i)))
+                       continue;
+#endif
+
+               if ((addr + i) > r->size) {
+                       fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
+                               addr+i, r->size);
+                       exit(1);
+               }
+
+               p = (unsigned char *)(((unsigned long)r->m) + addr + i);
+               val |= (((unsigned long)*p) << (i*8));
+       }
+
+#ifdef DEBUG
+       printf("MEM behave %d read  %016lx addr %016lx sel %02lx\n", identifier, val,
+               addr, sel);
+#endif
+
+       to_std_logic_vector(val, __val, 64);
+}
+
+void behavioural_write(unsigned char *__val, unsigned char *__addr,
+                       unsigned int sel, int identifier)
+{
+       struct ram_behavioural *r;
+       unsigned long val = from_std_logic_vector(__val, 64);
+       unsigned long addr = from_std_logic_vector(__addr, 64);
+       unsigned char *p;
+
+       if (identifier > region_nr) {
+               fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
+               exit(1);
+       }
+
+       r = &behavioural_regions[identifier];
+
+       p = (unsigned char *)(((unsigned long)r->m) + addr);
+
+#ifdef DEBUG
+       printf("MEM behave %d write %016lx addr %016lx sel %02x\n", identifier, val,
+               addr, sel);
+#endif
+
+       for (unsigned long i = 0; i < 8; i++) {
+               if (!(sel & (1UL << i)))
+                       continue;
+
+               if ((addr + i) > r->size) {
+                       fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
+                               addr+i, r->size);
+                       exit(1);
+               }
+
+               p = (unsigned char *)(((unsigned long)r->m) + addr + i);
+               *p = (val >> (i*8)) & 0xff;
+       }
+}
diff --git a/simple_ram_behavioural.vhdl b/simple_ram_behavioural.vhdl
deleted file mode 100644 (file)
index d6255b8..0000000
+++ /dev/null
@@ -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;
diff --git a/simple_ram_behavioural_helpers.vhdl b/simple_ram_behavioural_helpers.vhdl
deleted file mode 100644 (file)
index 507594f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-library ieee;
-use ieee.std_logic_1164.all;
-
-package simple_ram_behavioural_helpers is
-    function behavioural_initialize (filename: String; size: integer) return integer;
-    attribute foreign of behavioural_initialize : function is "VHPIDIRECT behavioural_initialize";
-
-    procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer);
-    attribute foreign of behavioural_read : procedure is "VHPIDIRECT behavioural_read";
-
-    procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer);
-    attribute foreign of behavioural_write : procedure is "VHPIDIRECT behavioural_write";
-end simple_ram_behavioural_helpers;
-
-package body simple_ram_behavioural_helpers is
-    function behavioural_initialize (filename: String; size: integer) return integer is
-    begin
-        assert false report "VHPI" severity failure;
-    end behavioural_initialize;
-
-    procedure behavioural_read (val: out std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer; reload: integer) is
-    begin
-        assert false report "VHPI" severity failure;
-    end behavioural_read;
-
-    procedure behavioural_write (val: std_ulogic_vector(63 downto 0); addr: std_ulogic_vector(63 downto 0); length: integer; identifier: integer) is
-    begin
-        assert false report "VHPI" severity failure;
-    end behavioural_write;
-end simple_ram_behavioural_helpers;
diff --git a/simple_ram_behavioural_helpers_c.c b/simple_ram_behavioural_helpers_c.c
deleted file mode 100644 (file)
index c5678e7..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#undef DEBUG
-
-#define ALIGN_UP(VAL, SIZE)    (((VAL) + ((SIZE)-1)) & ~((SIZE)-1))
-
-#define vhpi0  2       /* forcing 0 */
-#define vhpi1  3       /* forcing 1 */
-
-struct int_bounds
-{
-       int left;
-       int right;
-       char dir;
-       unsigned int len;
-};
-
-struct fat_pointer
-{
-       void *base;
-       struct int_bounds *bounds;
-};
-
-static char *from_string(void *__p)
-{
-       struct fat_pointer *p = __p;
-       unsigned long len = p->bounds->len;
-       char *m;
-
-       m = malloc(len+1);
-       if (!m) {
-               perror("malloc");
-               exit(1);
-       }
-
-       memcpy(m, p->base, len);
-       m[len] = 0x0;
-
-       return m;
-}
-
-static uint64_t from_std_logic_vector(unsigned char *p, unsigned long len)
-{
-       unsigned long ret = 0;
-
-       if (len > 64) {
-               fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
-               exit(1);
-       }
-
-       for (unsigned long i = 0; i < len; i++) {
-               unsigned char bit;
-
-               if (*p == vhpi0) {
-                       bit = 0;
-               } else if (*p == vhpi1) {
-                       bit = 1;
-               } else {
-                       fprintf(stderr, "%s: bad bit %d\n", __func__, *p);
-                       bit = 0;
-               }
-
-               ret = (ret << 1) | bit;
-               p++;
-       }
-
-       return ret;
-}
-
-static void to_std_logic_vector(unsigned long val, unsigned char *p,
-                               unsigned long len)
-{
-       if (len > 64) {
-               fprintf(stderr, "%s: invalid length %lu\n", __func__, len);
-               exit(1);
-       }
-
-       for (unsigned long i = 0; i < len; i++) {
-               if ((val >> (len-1-i) & 1))
-                       *p = vhpi1;
-               else
-                       *p = vhpi0;
-
-               p++;
-       }
-}
-
-#define MAX_REGIONS 128
-
-struct ram_behavioural {
-       char *filename;
-       unsigned long size;
-       void *m;
-};
-
-static struct ram_behavioural behavioural_regions[MAX_REGIONS];
-static unsigned long region_nr;
-
-unsigned long behavioural_initialize(void *__f, unsigned long size)
-{
-       struct ram_behavioural *r;
-       int fd;
-       struct stat buf;
-       unsigned long tmp_size;
-       void *mem;
-
-       if (region_nr == MAX_REGIONS) {
-               fprintf(stderr, "%s: too many regions, bump MAX_REGIONS\n", __func__);
-               exit(1);
-       }
-
-       r = &behavioural_regions[region_nr];
-
-       r->filename = from_string(__f);
-       r->size = ALIGN_UP(size, getpagesize());
-
-       fd = open(r->filename, O_RDWR);
-       if (fd == -1) {
-               fprintf(stderr, "%s: could not open %s\n", __func__,
-                       r->filename);
-               exit(1);
-       }
-
-       if (fstat(fd, &buf)) {
-               perror("fstat");
-               exit(1);
-       }
-
-       /* XXX Do we need to truncate the underlying file? */
-       tmp_size = ALIGN_UP(buf.st_size, getpagesize());
-
-       if (r->size > tmp_size) {
-               void *m;
-
-               /*
-                * We have to pad the file. Allocate the total size, then
-                * create a space for the file.
-                */
-               mem = mmap(NULL, r->size, PROT_READ|PROT_WRITE,
-                               MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-               if (mem == MAP_FAILED) {
-                       perror("mmap");
-                       exit(1);
-               }
-
-               if (tmp_size) {
-                       munmap(mem, tmp_size);
-
-                       m = mmap(mem, tmp_size, PROT_READ|PROT_WRITE,
-                                       MAP_PRIVATE|MAP_FIXED, fd, 0);
-                       if (m == MAP_FAILED) {
-                               perror("mmap");
-                               exit(1);
-                       }
-                       if (m != mem) {
-                               fprintf(stderr, "%s: mmap(MAP_FIXED) failed\n",
-                                       __func__);
-                               exit(1);
-                       }
-               }
-       } else {
-               mem = mmap(NULL, tmp_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
-                               fd, 0);
-               if (mem == MAP_FAILED) {
-                       perror("mmap");
-                       exit(1);
-               }
-       }
-
-       behavioural_regions[region_nr].m = mem;
-       return region_nr++;
-}
-
-void behavioural_read(unsigned char *__val, unsigned char *__addr,
-                       unsigned long sel, int identifier)
-{
-       struct ram_behavioural *r;
-       unsigned long val = 0;
-       unsigned long addr = from_std_logic_vector(__addr, 64);
-       unsigned char *p;
-
-       if (identifier > region_nr) {
-               fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
-               exit(1);
-       }
-
-       r = &behavioural_regions[identifier];
-
-       for (unsigned long i = 0; i < 8; i++) {
-#if 0
-               /* sel only used on writes */
-               if (!(sel & (1UL << i)))
-                       continue;
-#endif
-
-               if ((addr + i) > r->size) {
-                       fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
-                               addr+i, r->size);
-                       exit(1);
-               }
-
-               p = (unsigned char *)(((unsigned long)r->m) + addr + i);
-               val |= (((unsigned long)*p) << (i*8));
-       }
-
-#ifdef DEBUG
-       printf("MEM behave %d read  %016lx addr %016lx sel %02lx\n", identifier, val,
-               addr, sel);
-#endif
-
-       to_std_logic_vector(val, __val, 64);
-}
-
-void behavioural_write(unsigned char *__val, unsigned char *__addr,
-                       unsigned int sel, int identifier)
-{
-       struct ram_behavioural *r;
-       unsigned long val = from_std_logic_vector(__val, 64);
-       unsigned long addr = from_std_logic_vector(__addr, 64);
-       unsigned char *p;
-
-       if (identifier > region_nr) {
-               fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
-               exit(1);
-       }
-
-       r = &behavioural_regions[identifier];
-
-       p = (unsigned char *)(((unsigned long)r->m) + addr);
-
-#ifdef DEBUG
-       printf("MEM behave %d write %016lx addr %016lx sel %02x\n", identifier, val,
-               addr, sel);
-#endif
-
-       for (unsigned long i = 0; i < 8; i++) {
-               if (!(sel & (1UL << i)))
-                       continue;
-
-               if ((addr + i) > r->size) {
-                       fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
-                               addr+i, r->size);
-                       exit(1);
-               }
-
-               p = (unsigned char *)(((unsigned long)r->m) + addr + i);
-               *p = (val >> (i*8)) & 0xff;
-       }
-}
diff --git a/simple_ram_behavioural_tb.bin b/simple_ram_behavioural_tb.bin
deleted file mode 100644 (file)
index b66efb8..0000000
Binary files a/simple_ram_behavioural_tb.bin and /dev/null differ
diff --git a/simple_ram_behavioural_tb.vhdl b/simple_ram_behavioural_tb.vhdl
deleted file mode 100644 (file)
index bee7d2e..0000000
+++ /dev/null
@@ -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;
index b9a821557dc19a89e1276a9878d577d42ffd559a..6ed6bf745c4d22fdb04bbdd039305c7250bc1c5e 100644 (file)
--- a/soc.vhdl
+++ b/soc.vhdl
@@ -170,7 +170,7 @@ begin
     wb_uart0_out.stall <= '0' when wb_uart0_in.cyc = '0' else not wb_uart0_out.ack;
 
     -- BRAM Memory slave
-    bram0: entity work.mw_soc_memory
+    bram0: entity work.wishbone_bram_wrapper
        generic map(
            MEMORY_SIZE   => MEMORY_SIZE,
            RAM_INIT_FILE => RAM_INIT_FILE
diff --git a/wishbone_bram_tb.bin b/wishbone_bram_tb.bin
new file mode 100644 (file)
index 0000000..b66efb8
Binary files /dev/null and b/wishbone_bram_tb.bin differ
diff --git a/wishbone_bram_tb.vhdl b/wishbone_bram_tb.vhdl
new file mode 100644 (file)
index 0000000..be64db6
--- /dev/null
@@ -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;
diff --git a/wishbone_bram_wrapper.vhdl b/wishbone_bram_wrapper.vhdl
new file mode 100644 (file)
index 0000000..a711c3d
--- /dev/null
@@ -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;