diff --git a/test/SimT.vhd b/test/SimT.vhd index 155f99d..d2d34ef 100644 --- a/test/SimT.vhd +++ b/test/SimT.vhd @@ -76,22 +76,25 @@ begin variable v_random : RandomPType; begin v_random.InitSeed(v_random'instance_name); - for mode in 0 to 3 loop - for i in 0 to 255 loop - v_send_data := v_random.RandSlv(C_DATA_WIDTH); - sv_mosi_queue.push(v_send_data); - spi_master (data_in => v_send_data, - data_out => v_receive_data, - sclk => s_sclk, - ste => s_ste, - mosi => s_mosi, - miso => s_miso, - cpol => mode / 2, - cpha => mode mod 2, - period => 1 us - ); - sv_miso_queue.pop(v_queue_data); - assert_equal(v_receive_data, v_queue_data); + for direction in 0 to 1 loop + for mode in 0 to 3 loop + for i in 0 to 255 loop + v_send_data := v_random.RandSlv(C_DATA_WIDTH); + sv_mosi_queue.push(v_send_data); + spi_master (data_in => v_send_data, + data_out => v_receive_data, + sclk => s_sclk, + ste => s_ste, + mosi => s_mosi, + miso => s_miso, + dir => direction, + cpol => mode / 2, + cpha => mode mod 2, + period => 1 us + ); + sv_miso_queue.pop(v_queue_data); + assert_equal(v_receive_data, v_queue_data); + end loop; end loop; end loop; wait; @@ -107,24 +110,27 @@ begin variable v_random : RandomPType; begin v_random.InitSeed(v_random'instance_name); - for mode in 0 to 3 loop - for i in 0 to 255 loop - v_send_data := v_random.RandSlv(C_DATA_WIDTH); - sv_miso_queue.push(v_send_data); - spi_slave (data_in => v_send_data, - data_out => v_receive_data, - sclk => s_sclk, - ste => s_ste, - mosi => s_mosi, - miso => s_miso, - cpol => mode / 2, - cpha => mode mod 2 - ); - sv_mosi_queue.pop(v_queue_data); - assert_equal(v_receive_data, v_queue_data); + for direction in 0 to 1 loop + for mode in 0 to 3 loop + for i in 0 to 255 loop + v_send_data := v_random.RandSlv(C_DATA_WIDTH); + sv_miso_queue.push(v_send_data); + spi_slave (data_in => v_send_data, + data_out => v_receive_data, + sclk => s_sclk, + ste => s_ste, + mosi => s_mosi, + miso => s_miso, + dir => direction, + cpol => mode / 2, + cpha => mode mod 2 + ); + sv_mosi_queue.pop(v_queue_data); + assert_equal(v_receive_data, v_queue_data); + end loop; end loop; end loop; - report "INFO: spi_* procedures tests finished successfully"; + report "INFO: All tests of valid spi_master() & spi_slave() combinations finished successfully"; s_tests_done(1) <= true; wait; end process SpiSlaveP; diff --git a/test/SpiT.vhd b/test/SpiT.vhd index 29b2213..ed62d57 100644 --- a/test/SpiT.vhd +++ b/test/SpiT.vhd @@ -97,7 +97,7 @@ architecture sim of SpiT is subtype t_spi_mode is natural range 0 to 3; --+ test done array with entry for each test - signal s_test_done : boolean_vector(t_spi_mode'low to 2*t_spi_mode'high+1) := (others => false); + signal s_test_done : boolean_vector(t_spi_mode'low to 4*t_spi_mode'high+3) := (others => false); begin @@ -109,278 +109,286 @@ begin s_reset_n <= '1' after 100 ns; - --+ SpiMasterE tests for all 4 modes - SpiMastersG : for mode in t_spi_mode'low to t_spi_mode'high generate + --* Generate tests for both direction + DataDirectionG : for direction in 0 to 1 generate - signal s_sclk : std_logic; - signal s_ste : std_logic; - signal s_mosi : std_logic; - signal s_miso : std_logic; - signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0); - signal s_din_valid : std_logic; - signal s_din_accept : std_logic; - signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0); - signal s_dout_valid : std_logic; - signal s_dout_accept : std_logic; + --* Generate SpiMasterE tests for all 4 modes + SpiMastersG : for mode in t_spi_mode'low to t_spi_mode'high generate - shared variable sv_mosi_queue : t_list_queue; - shared variable sv_miso_queue : t_list_queue; + signal s_sclk : std_logic; + signal s_ste : std_logic; + signal s_mosi : std_logic; + signal s_miso : std_logic; - begin + signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0); + signal s_din_valid : std_logic; + signal s_din_accept : std_logic; + signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0); + signal s_dout_valid : std_logic; + signal s_dout_accept : std_logic; + shared variable sv_mosi_queue : t_list_queue; + shared variable sv_miso_queue : t_list_queue; - --* Stimuli generator and BFM for the valid-accept interface - --* on the local data input of the DUT - --* - --* Generates random stimuli and serves it to the - --* valid-accept interface at the input of the DUT - --* - --* The stimuli data is also pushed into the mosi queue - --* which serves as simple abstract reference model - --* of the SPI transmit (master -> slave) channel - SpiMasterStimP : process is - variable v_random : RandomPType; - begin - v_random.InitSeed(v_random'instance_name); - s_din_valid <= '0'; - s_din <= (others => '0'); - wait until s_reset_n = '1'; - for i in 0 to integer'(2**C_DATA_WIDTH-1) loop - s_din <= v_random.RandSlv(C_DATA_WIDTH); - s_din_valid <= '1'; - wait until rising_edge(s_clk) and s_din_accept = '1'; - s_din_valid <= '0'; - sv_mosi_queue.push(s_din); - wait until rising_edge(s_clk); - end loop; - wait; - end process SpiMasterStimP; - - - --* DUT: SpiMasterE component - i_SpiMasterE : SpiMasterE - generic map ( - G_DATA_WIDTH => C_DATA_WIDTH, - G_DATA_DIR => 1, - G_SPI_CPOL => mode / 2, - G_SPI_CPHA => mode mod 2, - G_SCLK_DIVIDER => 10 - ) - port map ( - --+ system if - Reset_n_i => s_reset_n, - Clk_i => s_clk, - --+ SPI slave if - SpiSclk_o => s_sclk, - SpiSte_o => s_ste, - SpiMosi_o => s_mosi, - SpiMiso_i => s_miso, - --+ local VAI if - Data_i => s_din, - DataValid_i => s_din_valid, - DataAccept_o => s_din_accept, - Data_o => s_dout, - DataValid_o => s_dout_valid, - DataAccept_i => s_dout_accept - ); - - --* Checker and BFM for the valid-accept interface - --* on the local data output of the DUT - --* - --* Reads the output of the DUT and compares it to - --* data popped from the miso queue which serves as - --* simple abstract reference model of the SPI receive - --* (slave -> master) channel - SpiMasterCheckP : process is - variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); begin - s_dout_accept <= '0'; - wait until s_reset_n = '1'; - for i in 0 to integer'(2**C_DATA_WIDTH-1) loop - wait until rising_edge(s_clk) and s_dout_valid = '1'; - s_dout_accept <= '1'; - sv_miso_queue.pop(v_queue_data); - assert_equal(s_dout, v_queue_data); - wait until rising_edge(s_clk); - s_dout_accept <= '0'; - end loop; - report "INFO: SpiMaster (mode=" & to_string(mode) & ") test successfully"; - s_test_done(mode) <= true; - wait; - end process SpiMasterCheckP; - - - --* Stimuli generator and BFM for the SPI slave - --* interface on the SPI miso input of the DUT - --* - --* Generates random stimuli and serves it to the - --* SPI interface at the input of the DUT - --* - --* The stimuli data is also pushed into the miso queue - --* which serves as simple abstract reference model - --* of the SPI receive (slave -> master) channel - --* - --* Furthermore the data received by the SPI slave BFM - --* is checked against data popped from the mosi queue - --* which serves as simple abstract reference model of - --* the SPI receive (master -> slave) channel - SpiSlaveP : process is - variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - variable v_random : RandomPType; - begin - v_random.InitSeed(v_random'instance_name); - wait until s_reset_n = '1'; - for i in 0 to integer'(2**C_DATA_WIDTH-1) loop - v_send_data := v_random.RandSlv(C_DATA_WIDTH); - sv_miso_queue.push(v_send_data); - spi_slave (data_in => v_send_data, - data_out => v_receive_data, - sclk => s_sclk, - ste => s_ste, - mosi => s_mosi, - miso => s_miso, - cpol => mode / 2, - cpha => mode mod 2 - ); - sv_mosi_queue.pop(v_queue_data); - assert_equal(v_receive_data, v_queue_data); - end loop; - wait; - end process SpiSlaveP; - - - end generate SpiMastersG; - - - - --+ SpiSlaveE tests for all 4 modes - SpiSlavesG : for mode in t_spi_mode'low to t_spi_mode'high generate - - signal s_sclk : std_logic; - signal s_ste : std_logic; - signal s_mosi : std_logic; - signal s_miso : std_logic; - signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0); - signal s_din_valid : std_logic; - signal s_din_accept : std_logic; - signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0); - signal s_dout_valid : std_logic; - signal s_dout_accept : std_logic; - - shared variable sv_mosi_queue : t_list_queue; - shared variable sv_miso_queue : t_list_queue; - - - begin + --* Stimuli generator and BFM for the valid-accept interface + --* on the local data input of the DUT + --* + --* Generates random stimuli and serves it to the + --* valid-accept interface at the input of the DUT + --* + --* The stimuli data is also pushed into the mosi queue + --* which serves as simple abstract reference model + --* of the SPI transmit (master -> slave) channel + SpiMasterStimP : process is + variable v_random : RandomPType; + begin + v_random.InitSeed(v_random'instance_name); + s_din_valid <= '0'; + s_din <= (others => '0'); + wait until s_reset_n = '1'; + for i in 0 to integer'(2**C_DATA_WIDTH-1) loop + s_din <= v_random.RandSlv(C_DATA_WIDTH); + s_din_valid <= '1'; + wait until rising_edge(s_clk) and s_din_accept = '1'; + s_din_valid <= '0'; + sv_mosi_queue.push(s_din); + wait until rising_edge(s_clk); + end loop; + wait; + end process SpiMasterStimP; + + + --* DUT: SpiMasterE component + i_SpiMasterE : SpiMasterE + generic map ( + G_DATA_WIDTH => C_DATA_WIDTH, + G_DATA_DIR => direction, + G_SPI_CPOL => mode / 2, + G_SPI_CPHA => mode mod 2, + G_SCLK_DIVIDER => 10 + ) + port map ( + --+ system if + Reset_n_i => s_reset_n, + Clk_i => s_clk, + --+ SPI slave if + SpiSclk_o => s_sclk, + SpiSte_o => s_ste, + SpiMosi_o => s_mosi, + SpiMiso_i => s_miso, + --+ local VAI if + Data_i => s_din, + DataValid_i => s_din_valid, + DataAccept_o => s_din_accept, + Data_o => s_dout, + DataValid_o => s_dout_valid, + DataAccept_i => s_dout_accept + ); + + + --* Checker and BFM for the valid-accept interface + --* on the local data output of the DUT + --* + --* Reads the output of the DUT and compares it to + --* data popped from the miso queue which serves as + --* simple abstract reference model of the SPI receive + --* (slave -> master) channel + SpiMasterCheckP : process is + variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + begin + s_dout_accept <= '0'; + wait until s_reset_n = '1'; + for i in 0 to integer'(2**C_DATA_WIDTH-1) loop + wait until rising_edge(s_clk) and s_dout_valid = '1'; + s_dout_accept <= '1'; + sv_miso_queue.pop(v_queue_data); + assert_equal(s_dout, v_queue_data); + wait until rising_edge(s_clk); + s_dout_accept <= '0'; + end loop; + report "INFO: SpiMaster (direction=" & to_string(direction) & ", mode=" & to_string(mode) & ") test successfully"; + s_test_done(mode+direction*4) <= true; + wait; + end process SpiMasterCheckP; + + + --* Stimuli generator and BFM for the SPI slave + --* interface on the SPI miso input of the DUT + --* + --* Generates random stimuli and serves it to the + --* SPI interface at the input of the DUT + --* + --* The stimuli data is also pushed into the miso queue + --* which serves as simple abstract reference model + --* of the SPI receive (slave -> master) channel + --* + --* Furthermore the data received by the SPI slave BFM + --* is checked against data popped from the mosi queue + --* which serves as simple abstract reference model of + --* the SPI receive (master -> slave) channel + SpiSlaveP : process is + variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + variable v_random : RandomPType; + begin + v_random.InitSeed(v_random'instance_name); + wait until s_reset_n = '1'; + for i in 0 to integer'(2**C_DATA_WIDTH-1) loop + v_send_data := v_random.RandSlv(C_DATA_WIDTH); + sv_miso_queue.push(v_send_data); + spi_slave (data_in => v_send_data, + data_out => v_receive_data, + sclk => s_sclk, + ste => s_ste, + mosi => s_mosi, + miso => s_miso, + dir => direction, + cpol => mode / 2, + cpha => mode mod 2 + ); + sv_mosi_queue.pop(v_queue_data); + assert_equal(v_receive_data, v_queue_data); + end loop; + wait; + end process SpiSlaveP; + + + end generate SpiMastersG; + + + --* Generate SpiMasterE tests for all 4 modes + SpiSlavesG : for mode in t_spi_mode'low to t_spi_mode'high generate + + + signal s_sclk : std_logic; + signal s_ste : std_logic; + signal s_mosi : std_logic; + signal s_miso : std_logic; + + signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0); + signal s_din_valid : std_logic; + signal s_din_accept : std_logic; + signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0); + signal s_dout_valid : std_logic; + signal s_dout_accept : std_logic; + + shared variable sv_mosi_queue : t_list_queue; + shared variable sv_miso_queue : t_list_queue; - --* Unit test of spi master procedure, checks all combinations - --* of cpol & cpha against spi slave procedure - SpiMasterP : process is - variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - variable v_random : RandomPType; - begin - v_random.InitSeed(v_random'instance_name); - s_sclk <= '1'; - s_ste <= '1'; - s_mosi <= '1'; - wait until s_reset_n = '1'; - for i in 0 to integer'(2**C_DATA_WIDTH-1) loop - v_send_data := v_random.RandSlv(C_DATA_WIDTH); - sv_mosi_queue.push(v_send_data); - spi_master (data_in => v_send_data, - data_out => v_receive_data, - sclk => s_sclk, - ste => s_ste, - mosi => s_mosi, - miso => s_miso, - cpol => mode / 2, - cpha => mode mod 2, - period => 100 ns - ); - sv_miso_queue.pop(v_queue_data); - assert_equal(v_receive_data, v_queue_data); - end loop; - report "INFO: SpiSlave (mode=" & to_string(mode) & ") test successfully"; - s_test_done(mode+4) <= true; - wait; - end process SpiMasterP; - - - SpiSlaveStimP : process is - variable v_random : RandomPType; begin - v_random.InitSeed(v_random'instance_name); - s_din_valid <= '0'; - s_din <= (others => '0'); - wait until s_reset_n = '1'; - for i in 0 to integer'(2**C_DATA_WIDTH-1) loop - s_din <= v_random.RandSlv(C_DATA_WIDTH); - s_din_valid <= '1'; - wait until rising_edge(s_clk) and s_din_accept = '1'; - s_din_valid <= '0'; - sv_miso_queue.push(s_din); - wait until rising_edge(s_clk) and s_dout_valid = '1'; - end loop; - wait; - end process SpiSlaveStimP; - - - i_SpiSlaveE : SpiSlaveE - generic map ( - G_DATA_WIDTH => C_DATA_WIDTH, - G_DATA_DIR => 1, - G_SPI_CPOL => mode / 2, - G_SPI_CPHA => mode mod 2 - ) - port map ( - --+ system if - Reset_n_i => s_reset_n, - Clk_i => s_clk, - --+ SPI slave if - SpiSclk_i => s_sclk, - SpiSte_i => s_ste, - SpiMosi_i => s_mosi, - SpiMiso_o => s_miso, - --+ local VAI if - Data_i => s_din, - DataValid_i => s_din_valid, - DataAccept_o => s_din_accept, - Data_o => s_dout, - DataValid_o => s_dout_valid, - DataAccept_i => s_dout_accept - ); - SpiSlaveCheckP : process is - variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); - begin - s_dout_accept <= '0'; - wait until s_reset_n = '1'; - for i in 0 to integer'(2**C_DATA_WIDTH-1) loop - wait until rising_edge(s_clk) and s_dout_valid = '1'; - s_dout_accept <= '1'; - sv_mosi_queue.pop(v_queue_data); - assert_equal(s_dout, v_queue_data); - wait until rising_edge(s_clk); + --* Unit test of spi master procedure, checks all combinations + --* of cpol & cpha against spi slave procedure + SpiMasterP : process is + variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + variable v_random : RandomPType; + begin + v_random.InitSeed(v_random'instance_name); + s_sclk <= '1'; + s_ste <= '1'; + s_mosi <= '1'; + wait until s_reset_n = '1'; + for i in 0 to integer'(2**C_DATA_WIDTH-1) loop + v_send_data := v_random.RandSlv(C_DATA_WIDTH); + sv_mosi_queue.push(v_send_data); + spi_master (data_in => v_send_data, + data_out => v_receive_data, + sclk => s_sclk, + ste => s_ste, + mosi => s_mosi, + miso => s_miso, + dir => direction, + cpol => mode / 2, + cpha => mode mod 2, + period => C_PERIOD * 10 + ); + sv_miso_queue.pop(v_queue_data); + assert_equal(v_receive_data, v_queue_data); + end loop; + report "INFO: SpiSlave (direction=" & to_string(direction) & ", mode=" & to_string(mode) & ") test successfully"; + s_test_done(mode+8+direction*4) <= true; + wait; + end process SpiMasterP; + + + SpiSlaveStimP : process is + variable v_random : RandomPType; + begin + v_random.InitSeed(v_random'instance_name); + s_din_valid <= '0'; + s_din <= (others => '0'); + wait until s_reset_n = '1'; + for i in 0 to integer'(2**C_DATA_WIDTH-1) loop + s_din <= v_random.RandSlv(C_DATA_WIDTH); + s_din_valid <= '1'; + wait until rising_edge(s_clk) and s_din_accept = '1'; + s_din_valid <= '0'; + sv_miso_queue.push(s_din); + wait until rising_edge(s_clk) and s_dout_valid = '1'; + end loop; + wait; + end process SpiSlaveStimP; + + + i_SpiSlaveE : SpiSlaveE + generic map ( + G_DATA_WIDTH => C_DATA_WIDTH, + G_DATA_DIR => direction, + G_SPI_CPOL => mode / 2, + G_SPI_CPHA => mode mod 2 + ) + port map ( + --+ system if + Reset_n_i => s_reset_n, + Clk_i => s_clk, + --+ SPI slave if + SpiSclk_i => s_sclk, + SpiSte_i => s_ste, + SpiMosi_i => s_mosi, + SpiMiso_o => s_miso, + --+ local VAI if + Data_i => s_din, + DataValid_i => s_din_valid, + DataAccept_o => s_din_accept, + Data_o => s_dout, + DataValid_o => s_dout_valid, + DataAccept_i => s_dout_accept + ); + + + SpiSlaveCheckP : process is + variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); + begin s_dout_accept <= '0'; - end loop; - wait; - end process SpiSlaveCheckP; + wait until s_reset_n = '1'; + for i in 0 to integer'(2**C_DATA_WIDTH-1) loop + wait until rising_edge(s_clk) and s_dout_valid = '1'; + s_dout_accept <= '1'; + sv_mosi_queue.pop(v_queue_data); + assert_equal(s_dout, v_queue_data); + wait until rising_edge(s_clk); + s_dout_accept <= '0'; + end loop; + wait; + end process SpiSlaveCheckP; + + end generate SpiSlavesG; - end generate SpiSlavesG; + end generate DataDirectionG; end architecture sim;