spi: Add simulation support
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 10 Jun 2020 03:35:10 +0000 (13:35 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Sat, 13 Jun 2020 01:33:41 +0000 (11:33 +1000)
This require the s25fl128s.vhd flash model and FMF libraries,
which will be built when passed to the Makefile via the
FLASH_MODEL_PATH argument. Otherwise a dummy module is used
which ties MISO to '1'.

The model isn't included as I'm not sure its licence (GPL) is
at this point, but it can be obtained from

https://github.com/ozbenh/microspi

FLASH_MODEL_PATH=<path to microspi>/model

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Makefile
core_dram_tb.vhdl
core_flash_tb.vhdl [new file with mode: 0644]
sim_no_flash.vhdl [new file with mode: 0644]

index bafbb8220c0191179ff7c11f840492d64820a835..692704e3b9ae579bccbc2e2960fe07f135ca4e8e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,17 +50,13 @@ core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \
        loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \
        core.vhdl
 
-soc_files = wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \
-       wishbone_debug_master.vhdl xics.vhdl syscon.vhdl soc.vhdl
+soc_files = $(core_files) wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \
+       wishbone_debug_master.vhdl xics.vhdl syscon.vhdl soc.vhdl \
+       spi_rxtx.vhdl spi_flash_ctrl.vhdl
 
-soc_sim_files = sim_console.vhdl sim_uart.vhdl sim_bram_helpers.vhdl \
-       sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl
 
-unisim_lib = sim-unisim/unisim-obj08.cf
-unisim_lib_files = sim-unisim/BSCANE2.vhdl sim-unisim/BUFG.vhdl \
-       sim-unisim/unisim_vcomponents.vhdl
-$(unisim_lib): $(unisim_lib_files)
-       ghdl -i --std=08 --work=unisim --workdir=sim-unisim $^
+soc_sim_files = $(soc_files) sim_console.vhdl sim_uart.vhdl sim_bram_helpers.vhdl \
+       sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl
 
 soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \
        sim_jtag_socket_c.c
@@ -69,12 +65,39 @@ soc_sim_obj_files=$(soc_sim_c_files:.c=.o)
 comma := ,
 soc_sim_link=$(patsubst %,-Wl$(comma)%,$(soc_sim_obj_files))
 
+unisim_dir = sim-unisim
+unisim_lib = $(unisim_dir)/unisim-obj08.cf
+unisim_lib_files = $(unisim_dir)/BSCANE2.vhdl $(unisim_dir)/BUFG.vhdl \
+       $(unisim_dir)/unisim_vcomponents.vhdl
+$(unisim_lib): $(unisim_lib_files)
+       ghdl -i --std=08 --work=unisim --workdir=$(unisim_dir) $^
+GHDLFLAGS += -P$(unisim_dir)
+
 core_tbs = multiply_tb divider_tb rotator_tb countzero_tb
 soc_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb
+soc_flash_tbs = core_flash_tb
 soc_dram_tbs = dram_tb core_dram_tb
 
-$(soc_tbs): %: $(core_files) $(soc_files) $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) %.vhdl
-       $(GHDL) -c $(GHDLFLAGS) -Psim-unisim $(soc_sim_link) $(core_files) $(soc_files) $(soc_sim_files) $@.vhdl -e $@
+ifneq ($(FLASH_MODEL_PATH),)
+fmf_dir = $(FLASH_MODEL_PATH)/fmf
+fmf_lib = $(fmf_dir)/fmf-obj08.cf
+fmf_lib_files = $(wildcard $(fmf_dir)/*.vhd)
+GHDLFLAGS += -P$(fmf_dir)
+$(fmf_lib): $(fmf_lib_files)
+       ghdl -i --std=08 --work=fmf --workdir=$(fmf_dir) $^
+
+flash_model_files=$(FLASH_MODEL_PATH)/s25fl128s.vhd
+flash_model_files: $(fmf_lib)
+else
+flash_model_files=sim_no_flash.vhdl
+fmf_lib=
+endif
+
+$(soc_flash_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) $(fmf_lib) $(flash_model_files) %.vhdl 
+       $(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(soc_sim_files) $(flash_model_files) $@.vhdl $(unisim_files) -e $@
+
+$(soc_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) %.vhdl 
+       $(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(soc_sim_files) $@.vhdl -e $@
 
 $(core_tbs): %: $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl %.vhdl
        $(GHDL) -c $(GHDLFLAGS) $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl $@.vhdl -e $@
@@ -106,8 +129,8 @@ soc_dram_sim_obj_files = $(soc_sim_obj_files) sim_litedram_c.o
 dram_link_files=-Wl,obj_dir/Vlitedram_core__ALL.a -Wl,obj_dir/verilated.o -Wl,obj_dir/verilated_vcd_c.o -Wl,-lstdc++
 soc_dram_sim_link=$(patsubst %,-Wl$(comma)%,$(soc_dram_sim_obj_files)) $(dram_link_files)
 
-$(soc_dram_tbs): %: $(core_files) $(soc_dram_files) $(soc_dram_sim_files) $(soc_dram_sim_obj_files) $(unisim_lib) %.vhdl
-       $(GHDL) -c $(GHDLFLAGS) -Psim-unisim $(soc_dram_sim_link) $(core_files) $(soc_dram_files) $(soc_dram_sim_files) $@.vhdl -e $@
+$(soc_dram_tbs): %: $(soc_dram_files) $(soc_dram_sim_files) $(soc_dram_sim_obj_files) $(flash_model_files) $(unisim_lib) $(fmf_lib) %.vhdl 
+       $(GHDL) -c $(GHDLFLAGS) $(soc_dram_sim_link) $(soc_dram_files) $(soc_dram_sim_files) $(flash_model_files) $@.vhdl -e $@
 endif
 
 # Hello world
index 3f95775846bc6740065f8713053df021d7ac9673..d72b1e794ada194e7b1b7a389791f20af3973b7a 100644 (file)
@@ -5,6 +5,7 @@ use ieee.numeric_std.all;
 library work;
 use work.common.all;
 use work.wishbone_types.all;
+use work.utils.all;
 
 entity core_dram_tb is
     generic (
@@ -31,6 +32,17 @@ architecture behave of core_dram_tb is
     signal wb_dram_is_init  : std_ulogic;
     signal core_alt_reset : std_ulogic;
 
+    -- SPI
+    signal spi_sck     : std_ulogic;
+    signal spi_cs_n    : std_ulogic := '1';
+    signal spi_sdat_o  : std_ulogic_vector(3 downto 0);
+    signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
+    signal spi_sdat_i  : std_ulogic_vector(3 downto 0);
+    signal fl_hold_n   : std_logic;
+    signal fl_wp_n     : std_logic;
+    signal fl_mosi     : std_logic;
+    signal fl_miso     : std_logic;
+
     -- ROM size
     function get_rom_size return natural is
     begin
@@ -53,7 +65,10 @@ begin
             HAS_DRAM => true,
            DRAM_SIZE => 256 * 1024 * 1024,
             DRAM_INIT_SIZE => ROM_SIZE,
-           CLK_FREQ => 100000000
+           CLK_FREQ => 100000000,
+            HAS_SPI_FLASH    => true,
+            SPI_FLASH_DLINES => 4,
+            SPI_FLASH_OFFSET => 0
            )
        port map(
            rst => soc_rst,
@@ -66,9 +81,44 @@ begin
            wb_dram_ctrl_out => wb_dram_ctrl_out,
             wb_dram_is_csr => wb_dram_is_csr,
             wb_dram_is_init => wb_dram_is_init,
+            spi_flash_sck     => spi_sck,
+            spi_flash_cs_n    => spi_cs_n,
+            spi_flash_sdat_o  => spi_sdat_o,
+            spi_flash_sdat_oe => spi_sdat_oe,
+            spi_flash_sdat_i  => spi_sdat_i,
            alt_reset => core_alt_reset
            );
 
+        flash: entity work.s25fl128s
+        generic map (
+            TimingModel => "S25FL128SAGNFI000_R_30pF",
+            LongTimming => false,
+            tdevice_PU => 10 ns,
+            tdevice_PP256 => 100 ns,
+            tdevice_PP512 => 100 ns,
+            tdevice_WRR   => 100 ns,
+            UserPreload => TRUE
+            )
+        port map(
+            SCK => spi_sck,
+            SI => fl_mosi,
+            CSNeg => spi_cs_n,
+            HOLDNeg => fl_hold_n,
+            WPNeg => fl_wp_n,
+            RSTNeg => '1',
+            SO => fl_miso
+            );
+
+    fl_mosi   <= spi_sdat_o(0) when spi_sdat_oe(0) = '1' else 'Z';
+    fl_miso   <= spi_sdat_o(1) when spi_sdat_oe(1) = '1' else 'Z';
+    fl_wp_n   <= spi_sdat_o(2) when spi_sdat_oe(2) = '1' else 'Z';
+    fl_hold_n <= spi_sdat_o(3) when spi_sdat_oe(3) = '1' else '1' when spi_sdat_oe(0) = '1' else 'Z';
+
+    spi_sdat_i(0) <= fl_mosi;
+    spi_sdat_i(1) <= fl_miso;
+    spi_sdat_i(2) <= fl_wp_n;
+    spi_sdat_i(3) <= fl_hold_n;
+
     dram: entity work.litedram_wrapper
         generic map(
             DRAM_ABITS => 24,
diff --git a/core_flash_tb.vhdl b/core_flash_tb.vhdl
new file mode 100644 (file)
index 0000000..6575aa5
--- /dev/null
@@ -0,0 +1,119 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.common.all;
+use work.wishbone_types.all;
+
+entity core_flash_tb is
+end core_flash_tb;
+
+architecture behave of core_flash_tb is
+       signal clk, rst: std_logic;
+
+       -- testbench signals
+       constant clk_period : time := 10 ns;
+
+        -- Dummy DRAM
+       signal wb_dram_in : wishbone_master_out;
+       signal wb_dram_out : wishbone_slave_out;
+       signal wb_dram_ctrl_in : wb_io_master_out;
+       signal wb_dram_ctrl_out : wb_io_slave_out;
+
+        -- SPI
+        signal spi_sck     : std_ulogic;
+        signal spi_cs_n    : std_ulogic := '1';
+        signal spi_sdat_o  : std_ulogic_vector(3 downto 0);
+        signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
+        signal spi_sdat_i  : std_ulogic_vector(3 downto 0);
+        signal fl_hold_n   : std_logic;
+        signal fl_wp_n     : std_logic;
+        signal fl_mosi     : std_logic;
+        signal fl_miso     : std_logic;
+begin
+
+    soc0: entity work.soc
+       generic map(
+           SIM => true,
+           MEMORY_SIZE => (384*1024),
+           RAM_INIT_FILE => "main_ram.bin",
+           RESET_LOW => false,
+           CLK_FREQ => 100000000,
+            HAS_SPI_FLASH    => true,
+            SPI_FLASH_DLINES => 4,
+            SPI_FLASH_OFFSET => 0
+           )
+       port map(
+           rst => rst,
+           system_clk => clk,
+           uart0_rxd => '0',
+           uart0_txd => open,
+           wb_dram_in => wb_dram_in,
+           wb_dram_out => wb_dram_out,
+           wb_dram_ctrl_in => wb_dram_ctrl_in,
+           wb_dram_ctrl_out => wb_dram_ctrl_out,
+            spi_flash_sck     => spi_sck,
+            spi_flash_cs_n    => spi_cs_n,
+            spi_flash_sdat_o  => spi_sdat_o,
+            spi_flash_sdat_oe => spi_sdat_oe,
+            spi_flash_sdat_i  => spi_sdat_i,
+           alt_reset => '0'
+           );
+
+    flash: entity work.s25fl128s
+        generic map (
+            TimingModel => "S25FL128SAGNFI000_R_30pF",
+            LongTimming => false,
+            tdevice_PU => 10 ns,
+            tdevice_PP256 => 100 ns,
+            tdevice_PP512 => 100 ns,
+            tdevice_WRR   => 100 ns
+            )
+        port map(
+            SCK => spi_sck,
+            SI => fl_mosi,
+            CSNeg => spi_cs_n,
+            HOLDNeg => fl_hold_n,
+            WPNeg => fl_wp_n,
+            RSTNeg => '1',
+            SO => fl_miso
+            );
+
+    fl_mosi   <= spi_sdat_o(0) when spi_sdat_oe(0) = '1' else 'Z';
+    fl_miso   <= spi_sdat_o(1) when spi_sdat_oe(1) = '1' else 'Z';
+    fl_wp_n   <= spi_sdat_o(2) when spi_sdat_oe(2) = '1' else 'Z';
+    fl_hold_n <= spi_sdat_o(3) when spi_sdat_oe(3) = '1' else '1' when spi_sdat_oe(0) = '1' else 'Z';
+
+    spi_sdat_i(0) <= fl_mosi;
+    spi_sdat_i(1) <= fl_miso;
+    spi_sdat_i(2) <= fl_wp_n;
+    spi_sdat_i(3) <= fl_hold_n;
+    
+    clk_process: process
+    begin
+       clk <= '0';
+       wait for clk_period/2;
+       clk <= '1';
+       wait for clk_period/2;
+    end process;
+
+    rst_process: process
+    begin
+       rst <= '1';
+       wait for 10*clk_period;
+       rst <= '0';
+       wait;
+    end process;
+
+    jtag: entity work.sim_jtag;
+
+    -- Dummy DRAM
+    wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
+    wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
+    wb_dram_out.stall <= '0';
+    wb_dram_ctrl_out.ack <= wb_dram_ctrl_in.cyc and wb_dram_ctrl_in.stb;
+    wb_dram_ctrl_out.dat <= x"FFFFFFFF";
+    wb_dram_ctrl_out.stall <= '0';
+
+end;
diff --git a/sim_no_flash.vhdl b/sim_no_flash.vhdl
new file mode 100644 (file)
index 0000000..9113c69
--- /dev/null
@@ -0,0 +1,28 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity s25fl128s is
+    generic (
+        LongTimming       : boolean := true;
+        TimingModel       : string := "";
+        tdevice_PU        : time := 10 ns;
+        tdevice_PP256     : time := 10 ns;
+        tdevice_PP512     : time := 10 ns;
+        tdevice_WRR       : time := 10 ns;
+        UserPreload       : boolean := false
+    );
+    PORT (
+        SI                : inout std_ulogic := 'Z';
+        SO                : inout std_ulogic := 'Z';
+        SCK               : in    std_ulogic := 'Z';
+        CSNeg             : in    std_ulogic := 'Z';
+        RSTNeg            : in    std_ulogic := 'Z';
+        WPNeg             : inout std_ulogic := 'Z';
+        HOLDNeg           : inout std_ulogic := 'Z'
+    );
+end entity;
+
+architecture behaviour of s25fl128s is
+begin
+    SO <= '1';
+end architecture;