From: Benjamin Herrenschmidt Date: Wed, 10 Jun 2020 03:35:10 +0000 (+1000) Subject: spi: Add simulation support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a89e1469ef9eaee0a85cf48731dd3a3aa102dea0;p=microwatt.git spi: Add simulation support 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=/model Signed-off-by: Benjamin Herrenschmidt --- diff --git a/Makefile b/Makefile index bafbb82..692704e 100644 --- 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 diff --git a/core_dram_tb.vhdl b/core_dram_tb.vhdl index 3f95775..d72b1e7 100644 --- a/core_dram_tb.vhdl +++ b/core_dram_tb.vhdl @@ -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 index 0000000..6575aa5 --- /dev/null +++ b/core_flash_tb.vhdl @@ -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 index 0000000..9113c69 --- /dev/null +++ b/sim_no_flash.vhdl @@ -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;