diff --git a/vunit/vhdl/verification_components/src/axi_stream_master.vhd b/vunit/vhdl/verification_components/src/axi_stream_master.vhd index dc47c2cd5..1c5148c88 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_master.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_master.vhd @@ -16,28 +16,33 @@ use work.sync_pkg.all; entity axi_stream_master is generic ( - master : axi_stream_master_t; + master : axi_stream_master_t; drive_invalid : boolean := true; drive_invalid_val : std_logic := 'X'; drive_invalid_val_user : std_logic := '0' ); port ( - aclk : in std_logic; - tvalid : out std_logic := '0'; - tready : in std_logic := '1'; - tdata : out std_logic_vector(data_length(master)-1 downto 0) := (others => '0'); - tlast : out std_logic := '0'; - tkeep : out std_logic_vector(data_length(master)/8-1 downto 0) := (others => '0'); - tstrb : out std_logic_vector(data_length(master)/8-1 downto 0) := (others => '0'); - tid : out std_logic_vector(id_length(master)-1 downto 0) := (others => '0'); - tdest : out std_logic_vector(dest_length(master)-1 downto 0) := (others => '0'); - tuser : out std_logic_vector(user_length(master)-1 downto 0) := (others => '0') + aclk : in std_logic; + areset_n : in std_logic := '1'; + tvalid : out std_logic := '0'; + tready : in std_logic := '1'; + tdata : out std_logic_vector(data_length(master)-1 downto 0) := (others => '0'); + tlast : out std_logic := '0'; + tkeep : out std_logic_vector(data_length(master)/8-1 downto 0) := (others => '0'); + tstrb : out std_logic_vector(data_length(master)/8-1 downto 0) := (others => '0'); + tid : out std_logic_vector(id_length(master)-1 downto 0) := (others => '0'); + tdest : out std_logic_vector(dest_length(master)-1 downto 0) := (others => '0'); + tuser : out std_logic_vector(user_length(master)-1 downto 0) := (others => '0') ); end entity; architecture a of axi_stream_master is - constant message_queue : queue_t := new_queue; + + signal notify_bus_process_done : std_logic := '0'; + constant message_queue : queue_t := new_queue; + begin + main : process variable request_msg : msg_t; variable msg_type : msg_type_t; @@ -50,7 +55,7 @@ begin elsif msg_type = wait_for_time_msg then push(message_queue, request_msg); elsif msg_type = wait_until_idle_msg then - wait until tvalid = '0' and is_empty(message_queue) and rising_edge(aclk); + wait on notify_bus_process_done until is_empty(message_queue); handle_wait_until_idle(net, msg_type, request_msg); else unexpected_msg_type(msg_type); @@ -60,6 +65,7 @@ begin bus_process : process variable msg : msg_t; variable msg_type : msg_type_t; + variable reset_cycles : positive := 1; begin if drive_invalid then tdata <= (others => drive_invalid_val); @@ -71,49 +77,56 @@ begin end if; -- Wait for messages to arrive on the queue, posted by the process above - wait until rising_edge(aclk) and not is_empty(message_queue); - - while not is_empty(message_queue) loop - - msg := pop(message_queue); - msg_type := message_type(msg); - - if msg_type = wait_for_time_msg then - handle_sync_message(net, msg_type, msg); - -- Re-align with the clock when a wait for time message was handled, because this breaks edge alignment. - wait until rising_edge(aclk); - elsif msg_type = stream_push_msg or msg_type = push_axi_stream_msg then - tvalid <= '1'; - tdata <= pop_std_ulogic_vector(msg); - if msg_type = push_axi_stream_msg then - tlast <= pop_std_ulogic(msg); - tkeep <= pop_std_ulogic_vector(msg); - tstrb <= pop_std_ulogic_vector(msg); - tid <= pop_std_ulogic_vector(msg); - tdest <= pop_std_ulogic_vector(msg); - tuser <= pop_std_ulogic_vector(msg); - else - if pop_boolean(msg) then - tlast <= '1'; + wait until rising_edge(aclk) and (not is_empty(message_queue) or areset_n = '0'); + + if (areset_n = '0') then + tvalid <= '0'; + else + while not is_empty(message_queue) loop + msg := pop(message_queue); + msg_type := message_type(msg); + + if msg_type = wait_for_time_msg then + handle_sync_message(net, msg_type, msg); + -- Re-align with the clock when a wait for time message was handled, because this breaks edge alignment. + wait until rising_edge(aclk); + + elsif msg_type = stream_push_msg or msg_type = push_axi_stream_msg then + tvalid <= '1'; + tdata <= pop_std_ulogic_vector(msg); + if msg_type = push_axi_stream_msg then + tlast <= pop_std_ulogic(msg); + tkeep <= pop_std_ulogic_vector(msg); + tstrb <= pop_std_ulogic_vector(msg); + tid <= pop_std_ulogic_vector(msg); + tdest <= pop_std_ulogic_vector(msg); + tuser <= pop_std_ulogic_vector(msg); else - tlast <= '0'; + if pop_boolean(msg) then + tlast <= '1'; + else + tlast <= '0'; + end if; + tkeep <= (others => '1'); + tstrb <= (others => '1'); + tid <= (others => '0'); + tdest <= (others => '0'); + tuser <= (others => '0'); end if; - tkeep <= (others => '1'); - tstrb <= (others => '1'); - tid <= (others => '0'); - tdest <= (others => '0'); - tuser <= (others => '0'); + wait until ((tvalid and tready) = '1' or areset_n = '0') and rising_edge(aclk); + tvalid <= '0'; + tlast <= '0'; + else + unexpected_msg_type(msg_type); end if; - wait until (tvalid and tready) = '1' and rising_edge(aclk); - tvalid <= '0'; - tlast <= '0'; - else - unexpected_msg_type(msg_type); - end if; - delete(msg); - end loop; + delete(msg); + end loop; + notify_bus_process_done <= '1'; + wait until notify_bus_process_done = '1'; + notify_bus_process_done <= '0'; + end if; end process; axi_stream_monitor_generate : if master.p_monitor /= null_axi_stream_monitor generate @@ -141,7 +154,7 @@ begin protocol_checker => master.p_protocol_checker) port map ( aclk => aclk, - areset_n => open, + areset_n => areset_n, tvalid => tvalid, tready => tready, tdata => tdata, diff --git a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd index 091f7f9a6..4aa747320 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd @@ -17,16 +17,17 @@ entity axi_stream_slave is generic ( slave : axi_stream_slave_t); port ( - aclk : in std_logic; - tvalid : in std_logic; - tready : out std_logic := '0'; - tdata : in std_logic_vector(data_length(slave)-1 downto 0); - tlast : in std_logic := '1'; - tkeep : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); - tstrb : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); - tid : in std_logic_vector(id_length(slave)-1 downto 0) := (others => '0'); - tdest : in std_logic_vector(dest_length(slave)-1 downto 0) := (others => '0'); - tuser : in std_logic_vector(user_length(slave)-1 downto 0) := (others => '0') + aclk : in std_logic; + areset_n : in std_logic := '1'; + tvalid : in std_logic; + tready : out std_logic := '0'; + tdata : in std_logic_vector(data_length(slave)-1 downto 0); + tlast : in std_logic := '1'; + tkeep : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); + tstrb : in std_logic_vector(data_length(slave)/8-1 downto 0) := (others => '0'); + tid : in std_logic_vector(id_length(slave)-1 downto 0) := (others => '0'); + tdest : in std_logic_vector(dest_length(slave)-1 downto 0) := (others => '0'); + tuser : in std_logic_vector(user_length(slave)-1 downto 0) := (others => '0') ); end entity; @@ -98,7 +99,7 @@ begin protocol_checker => slave.p_protocol_checker) port map ( aclk => aclk, - areset_n => open, + areset_n => areset_n, tvalid => tvalid, tready => tready, tdata => tdata, diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd index fdabd2749..6b0ffa92c 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd @@ -134,6 +134,13 @@ begin ); check_true(axi_stream_transaction.tlast, result("for axi_stream_transaction.tlast")); end loop; + elsif run("test reset") then + wait until rising_edge(aclk); + areset_n <= '0'; + wait until rising_edge(aclk); + check_equal(tvalid, '0', result("for valid low check while in reset")); + areset_n <= '1'; + wait until rising_edge(aclk); elsif run("test single push and pop with tlast") then push_stream(net, master_stream, x"88", true); @@ -307,16 +314,17 @@ begin generic map( master => master_axi_stream) port map( - aclk => aclk, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tuser => tuser, - tdest => tdest); + aclk => aclk, + areset_n => areset_n, + tvalid => tvalid, + tready => tready, + tdata => tdata, + tlast => tlast, + tkeep => tkeep, + tstrb => tstrb, + tid => tid, + tuser => tuser, + tdest => tdest); not_valid <= not tvalid; @@ -337,16 +345,17 @@ begin generic map( slave => slave_axi_stream) port map( - aclk => aclk, - tvalid => tvalid, - tready => tready, - tdata => tdata, - tlast => tlast, - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tuser => tuser, - tdest => tdest); + aclk => aclk, + areset_n => areset_n, + tvalid => tvalid, + tready => tready, + tdata => tdata, + tlast => tlast, + tkeep => tkeep, + tstrb => tstrb, + tid => tid, + tuser => tuser, + tdest => tdest); axi_stream_monitor_inst : entity work.axi_stream_monitor generic map(