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
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
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
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) $@
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)))
- 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:
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(
);
-- 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(
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"
" 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;
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,
--- /dev/null
+-- 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;
+++ /dev/null
--- 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;
);
-- 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(
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) &
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) &
-- 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) &
- 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
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 )
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') ]
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') ]
--- /dev/null
+-- 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;
--- /dev/null
+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;
--- /dev/null
+#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;
+ }
+}
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-#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;
- }
-}
+++ /dev/null
-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;
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
--- /dev/null
+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;
--- /dev/null
+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;