library IEEE; use IEEE.std_logic_1164.all; use IEEE.MATH_REAL.all; library work; use work.socbridge_driver_tb_pkg.all; library ganimede; use ganimede.io_types.all; entity socbridge_driver_tb is end entity socbridge_driver_tb; architecture tb of socbridge_driver_tb is signal clk : std_logic := '0'; signal rst : std_logic; signal cmd : command_t; signal address : std_logic_vector(31 downto 0); signal cmd_size : positive; signal ext_in : ext_socbridge_in_t; signal ext_out : ext_socbridge_out_t; signal int_in : int_socbridge_in_t; signal int_out : int_socbridge_out_t; signal curr_word : std_logic_vector(ext_in.payload'length - 1 downto 0); signal expected_out : std_logic_vector(ext_out.payload'length - 1 downto 0); constant CLK_PERIOD : TIME := 10 ns; constant SIMULATION_CYCLE_COUNT : INTEGER := 100; procedure fail(error_msg : string) is begin wait for CLK_PERIOD; report "Simulation ending due to: " & error_msg & ". Shutting down..." severity FAILURE; end procedure; procedure check_next_state(correct_state: state_t) is begin if(not (correct_state = G_next_state)) then report "Next State is not what was expected, found " & state_t'image(G_next_state) & " but expected " & state_t'image(correct_state) severity error; fail("Next State"); end if; end procedure; procedure check_data_out(correct_data: std_logic_vector(ext_out.payload'length - 1 downto 0)) is begin if(not (correct_data = ext_out.payload)) then report "Data out is not what was expected, found " & to_string(ext_out.payload) & " but expected " & to_string(correct_data) severity error; fail("Data out"); end if; end procedure; procedure check_parity(correct_data: std_logic_vector(ext_out.payload'length - 1 downto 0)) is begin if(not (calc_parity(correct_data) = calc_parity(ext_out.payload))) then report "Parity out is not what was expected, found " & std_logic'image(calc_parity(ext_out.payload)) & " but expected " & std_logic'image(calc_parity(correct_data)) severity error; fail("Parity out"); end if; end procedure; component socbridge_driver is port( clk : in std_logic; rst : in std_logic; cmd : in command_t; address : in std_logic_vector(31 downto 0); cmd_size: in positive; ext_in : in ext_socbridge_in_t; ext_out : out ext_socbridge_out_t; int_in : out int_socbridge_in_t; int_out : in int_socbridge_out_t ); end component socbridge_driver; begin socbridge_driver_inst: entity work.socbridge_driver port map( clk => clk, rst => rst, cmd => cmd, address => address, cmd_size => cmd_size, ext_in => ext_in, ext_out => ext_out, int_in => int_in, int_out => int_out ); ext_in.control(1) <= clk; real_clk_proc: process begin for x in 0 to SIMULATION_CYCLE_COUNT*2 loop clk <= not clk; wait for CLK_PERIOD / 2; end loop; wait; end process real_clk_proc; verify_clk: process variable last_clk : std_logic; begin wait for CLK_PERIOD / 2; for x in 0 to SIMULATION_CYCLE_COUNT loop if last_clk = ext_out.control(1) then report "Secondary side clk not correct." severity error; end if; last_clk := ext_out.control(1); wait for CLK_PERIOD; end loop; wait; end process verify_clk; verify_out_signals: process variable curr_parity : std_logic; begin wait for CLK_PERIOD / 2; for x in 0 to SIMULATION_CYCLE_COUNT loop check_data_out(expected_out); check_parity(expected_out); wait for CLK_PERIOD; end loop; wait; end process verify_out_signals; verify_signals : process variable nsv: boolean; begin expected_out <= "00000000"; wait for 3 * CLK_PERIOD; wait for CLK_PERIOD / 3; expected_out <= "00000000"; check_next_state(IDLE); wait for CLK_PERIOD /4; check_next_state(TX_HEADER); wait for CLK_PERIOD * 3 / 4; expected_out <= get_cmd_bits(WRITE) & get_size_bits_sim(2); check_next_state(TX_BODY); wait for CLK_PERIOD; expected_out <= "00000001"; check_next_state(TX_BODY); wait for CLK_PERIOD; expected_out <= "00000010"; check_next_state(TX_ACK); wait for CLK_PERIOD; expected_out <= "00000000"; check_next_state(TX_ACK); wait for CLK_PERIOD; check_next_state(IDLE); wait for CLK_PERIOD * 6; expected_out <= "00000000"; check_next_state(IDLE); wait for CLK_PERIOD /4; check_next_state(TX_HEADER); wait for CLK_PERIOD * 3 / 4; expected_out <= get_cmd_bits(WRITE_ADD) & get_size_bits(2); check_next_state(ADDR1); wait for CLK_PERIOD; expected_out <= x"FA"; check_next_state(ADDR2); wait for CLK_PERIOD; expected_out <= x"A0"; check_next_state(ADDR3); wait for CLK_PERIOD; expected_out <= x"0F"; check_next_state(ADDR4); wait for CLK_PERIOD; expected_out <= x"FA"; check_next_state(TX_BODY); wait for CLK_PERIOD; expected_out <= "00000100"; check_next_state(TX_BODY); wait for CLK_PERIOD; expected_out <= "00001000"; check_next_state(TX_ACK); wait for CLK_PERIOD; expected_out <= "00000000"; check_next_state(TX_ACK); wait for CLK_PERIOD; expected_out <= "00000000"; check_next_state(IDLE); wait for CLK_PERIOD * 2; wait for CLK_PERIOD /4; check_next_state(RX_HEADER); wait for CLK_PERIOD * 3 / 4; expected_out <= get_cmd_bits(READ) & get_size_bits(2); check_next_state(RX_RESPONSE); wait for CLK_PERIOD; expected_out <= "00000000"; check_next_state(RX_RESPONSE); wait for CLK_PERIOD; wait for CLK_PERIOD / 4; check_next_state(RX_BODY_NO_OUT); wait for CLK_PERIOD * 3 /4; check_next_state(RX_BODY); wait for CLK_PERIOD; check_next_state(RX_BODY); wait for CLK_PERIOD; check_next_state(IDLE); wait for CLK_PERIOD * 5; wait for CLK_PERIOD /4; check_next_state(RX_HEADER); wait for CLK_PERIOD * 3 / 4; expected_out <= get_cmd_bits(READ_ADD) & get_size_bits(2); check_next_state(ADDR1); wait for CLK_PERIOD; expected_out <= x"FA"; check_next_state(ADDR2); wait for CLK_PERIOD; expected_out <= x"A0"; check_next_state(ADDR3); wait for CLK_PERIOD; expected_out <= x"0F"; check_next_state(ADDR4); wait for CLK_PERIOD; expected_out <= x"FA"; check_next_state(RX_RESPONSE); wait for CLK_PERIOD; expected_out <= "00000000"; check_next_state(RX_RESPONSE); wait for CLK_PERIOD; wait for CLK_PERIOD / 4; check_next_state(RX_BODY_NO_OUT); wait for CLK_PERIOD * 3 /4; check_next_state(RX_BODY); wait for CLK_PERIOD; check_next_state(RX_BODY); wait for CLK_PERIOD; check_next_state(IDLE); wait; end process verify_signals; command_stimulus: process begin cmd <= NO_OP; cmd_size <= 2; wait for 3*CLK_PERIOD; wait for CLK_PERIOD / 2; cmd <= WRITE; wait for CLK_PERIOD; cmd <= NO_OP; wait for CLK_PERIOD * 10; cmd <= WRITE_ADD; address <= x"FA0FA0FA"; wait for CLK_PERIOD; cmd <= NO_OP; address <= (others => '0'); wait for CLK_PERIOD * 10; cmd <= READ; wait for CLK_PERIOD; cmd <= NO_OP; wait for CLK_PERIOD * 10; cmd <= READ_ADD; address <= x"FA0FA0FA"; wait for CLK_PERIOD; cmd <= NO_OP; address <= (others => '0'); wait; end process command_stimulus; external_stimulus_signal: process(curr_word) begin ext_in.payload <= curr_word; ext_in.control(0) <= calc_parity(curr_word); end process external_stimulus_signal; external_stimulus: process begin rst <= '0'; wait for CLK_PERIOD / 1000; rst <= '1'; curr_word <= "00000000"; wait for 999 * CLK_PERIOD / 1000; wait for 2 * CLK_PERIOD; rst <= '0'; wait for CLK_PERIOD / 2; wait for 4* CLK_PERIOD; curr_word <= "00001001"; wait for CLK_PERIOD; curr_word <= "00000000"; wait for CLK_PERIOD * 14; curr_word <= "00101001"; wait for CLK_PERIOD; curr_word <= "00000000"; wait for CLK_PERIOD*5; curr_word <= "01000001"; wait for CLK_PERIOD; curr_word <= "10000000"; wait for CLK_PERIOD; curr_word <= "01000000"; wait for CLK_PERIOD; curr_word <= "00000000"; wait for CLK_PERIOD*12; curr_word <= "01100001"; wait for CLK_PERIOD; curr_word <= "00100000"; wait for CLK_PERIOD; curr_word <= "00010000"; wait for CLK_PERIOD; curr_word <= "00000000"; wait; end process external_stimulus; internal_stimulus: process begin int_out.is_full_in <= '0'; int_out.write_enable_out <= '0'; wait for 3 * CLK_PERIOD; -- stimulus goes here int_out.write_enable_out <= '1'; int_out.payload <= "00000001"; wait until rising_edge(clk) and int_in.is_full_out = '0'; wait until falling_edge(clk); int_out.payload <= "00000010"; wait until rising_edge(clk) and int_in.is_full_out = '0'; wait until falling_edge(clk); int_out.payload <= "00000100"; wait until rising_edge(clk) and int_in.is_full_out = '0'; wait until falling_edge(clk); int_out.payload <= "00001000"; wait until rising_edge(clk) and int_in.is_full_out = '0'; wait until falling_edge(clk); int_out.payload <= "00010000"; wait until int_in.is_full_out = '0'; wait for CLK_PERIOD/2; wait until rising_edge(clk); wait until rising_edge(clk); int_out.payload <= "00100000"; wait until int_in.is_full_out = '0'; wait for CLK_PERIOD/2; wait until rising_edge(clk); wait until rising_edge(clk); --- ??? Why all these rising_edge checks? wait; end process internal_stimulus; end architecture tb ;