From: Manuel Penschuck Date: Thu, 7 Aug 2014 17:33:32 +0000 (+0200) Subject: CBMNet: data_stop-related timing problem in combination with slow fifo required addit... X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=24341ec41592c1565379dfc3439683e840fcd7df;p=trb3.git CBMNet: data_stop-related timing problem in combination with slow fifo required additional output-buffer - now implemented. New simulation includes two lp_top's for an end-to-end coverage of the readout path. Simulation look promising --- diff --git a/cbmnet/code/cbmnet_interface_pkg.vhd b/cbmnet/code/cbmnet_interface_pkg.vhd index 7f9bced..6809235 100644 --- a/cbmnet/code/cbmnet_interface_pkg.vhd +++ b/cbmnet/code/cbmnet_interface_pkg.vhd @@ -304,61 +304,6 @@ package cbmnet_interface_pkg is ctrl_rec_stop : out std_logic ); end component; - - component CBMNET_READOUT_TX_FSM is - port ( - CLK_IN : in std_logic; - RESET_IN : in std_logic; - - -- fifo - FIFO_DATA_IN : in std_logic_vector(15 downto 0); - FIFO_DEQUEUE_OUT : out std_logic; - FIFO_PACKET_COMPLETE_IN : in std_logic; - FIFO_PACKET_COMPLETE_ACK_OUT : out std_logic; - - -- cbmnet - CBMNET_STOP_IN : in std_logic; - CBMNET_START_OUT : out std_logic; - CBMNET_END_OUT : out std_logic; - CBMNET_DATA_OUT : out std_logic_vector(15 downto 0); - - -- debug - DEBUG_OUT : out std_logic_vector(31 downto 0) - ); - end component; - - component CBMNET_READOUT_FIFO is - generic ( - ADDR_WIDTH : positive := 10; - WATERMARK : positive := 2 - ); - - port ( - -- write port - WCLK_IN : in std_logic; -- not faster than rclk_in - WRESET_IN : in std_logic; - - WADDR_STORE_IN : in std_logic; - WADDR_RESTORE_IN : in std_logic; - - WDATA_IN : in std_logic_vector(17 downto 0); - WENQUEUE_IN : in std_logic; - WPACKET_COMPLETE_IN : in std_logic; - - WALMOST_FULL_OUT : out std_logic; - WFULL_OUT : out std_logic; - - -- read port - RCLK_IN : in std_logic; - RRESET_IN : in std_logic; -- has to active at least two clocks AFTER (or while) write port was (is being) initialised - - RDATA_OUT : out std_logic_vector(17 downto 0); - RDEQUEUE_IN : in std_logic; - - RPACKET_COMPLETE_OUT : out std_logic; -- atleast one packet is completed in fifo - RPACKET_COMPLETE_ACK_IN : in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one) - ); - end component; component CBMNET_READOUT is port ( @@ -481,6 +426,103 @@ package cbmnet_interface_pkg is DEBUG_OUT : out std_logic_vector(31 downto 0) ); end component; + + component CBMNET_READOUT_FIFO is + generic ( + ADDR_WIDTH : positive := 10; + WATERMARK : positive := 2 + ); + + port ( + -- write port + WCLK_IN : in std_logic; -- not faster than rclk_in + WRESET_IN : in std_logic; + + WADDR_STORE_IN : in std_logic; + WADDR_RESTORE_IN : in std_logic; + + WDATA_IN : in std_logic_vector(17 downto 0); + WENQUEUE_IN : in std_logic; + WPACKET_COMPLETE_IN : in std_logic; + + WALMOST_FULL_OUT : out std_logic; + WFULL_OUT : out std_logic; + + -- read port + RCLK_IN : in std_logic; + RRESET_IN : in std_logic; -- has to active at least two clocks AFTER (or while) write port was (is being) initialised + + RDATA_OUT : out std_logic_vector(17 downto 0); + RDEQUEUE_IN : in std_logic; + + RPACKET_COMPLETE_OUT : out std_logic; -- atleast one packet is completed in fifo + RPACKET_COMPLETE_ACK_IN : in std_logic; -- mark one event as dealt with (effectively decrease number of completed packets by one) + + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); + end component; + + component CBMNET_READOUT_FRAME_PACKER is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + + -- fifo + FIFO_DATA_IN : in std_logic_vector(15 downto 0); + FIFO_DEQUEUE_OUT : out std_logic; + FIFO_PACKET_COMPLETE_IN : in std_logic; + FIFO_PACKET_COMPLETE_ACK_OUT : out std_logic; + + -- cbmnet + CBMNET_STOP_IN : in std_logic; + CBMNET_START_OUT : out std_logic; + CBMNET_END_OUT : out std_logic; + CBMNET_DATA_OUT : out std_logic_vector(15 downto 0); + + -- debug + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); + end component; + + component CBMNET_READOUT_OBUF is + port( + CLK_IN : std_logic; + RESET_IN : std_logic; + + -- packer + PACKER_STOP_OUT : out std_logic; + PACKER_START_IN : in std_logic; + PACKER_END_IN : in std_logic; + PACKER_DATA_IN : in std_logic_vector(15 downto 0); + + -- cbmnet + CBMNET_STOP_IN : in std_logic; + CBMNET_START_OUT : out std_logic; + CBMNET_END_OUT : out std_logic; + CBMNET_DATA_OUT : out std_logic_vector(15 downto 0); + + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); + end component; + + component cbmnet_readout_tx_fifo is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + EMPTY_IN : in std_logic; -- identical to reset_in + + DATA_IN : in std_logic_vector(15 downto 0); + DATA_OUT : out std_logic_vector(15 downto 0); + + ENQUEUE_IN : in std_logic; + DEQUEUE_IN : in std_logic; + + LAST_OUT : out std_logic; + + FILLED_IN : in std_logic; + FILLED_OUT : out std_logic + ); + end component; end package cbmnet_interface_pkg; package body cbmnet_interface_pkg is diff --git a/cbmnet/code/cbmnet_readout.vhd b/cbmnet/code/cbmnet_readout.vhd index 3dc3250..1a113e7 100644 --- a/cbmnet/code/cbmnet_readout.vhd +++ b/cbmnet/code/cbmnet_readout.vhd @@ -60,6 +60,9 @@ entity CBMNET_READOUT is end entity; architecture cbmnet_readout_arch of CBMNET_READOUT is + signal reset_combined_i : std_logic; + signal reset_combined_125_i : std_logic; + -- signals of readout chain (DECODER -> PACKER -> FIFO -> TX) signal fifo_rdata_i : std_logic_vector(17 downto 0); signal fifo_rdequeue_i : std_logic; @@ -72,6 +75,7 @@ architecture cbmnet_readout_arch of CBMNET_READOUT is signal fifo_wenqueue_i : std_logic; signal fifo_wpacket_complete_i : std_logic; signal fifo_wfull_i : std_logic; + signal debug_fifo_i : std_logic_vector(31 downto 0); signal dec_evt_info_i : std_logic_vector(31 downto 0); signal dec_length_i : std_logic_vector(15 downto 0); @@ -88,9 +92,11 @@ architecture cbmnet_readout_arch of CBMNET_READOUT is signal pack_source_i : std_logic_vector(15 downto 0); -- cbm strobe buffers - signal cbmnet_data2send_start_i : std_logic; - signal cbmnet_data2send_end_i : std_logic; - signal cbmnet_data2send_data_i : std_logic_vector(15 downto 0); + signal frame_packer_start_i : std_logic; + signal frame_packer_end_i : std_logic; + signal frame_packer_data_i : std_logic_vector(15 downto 0); + signal obuf_stop_i : std_logic; + signal cbmnet_link_active_in_buf_i : std_logic; -- stats and monitoring @@ -137,6 +143,25 @@ begin HUB_CTS_READOUT_FINISHED_OUT <= GBE_CTS_READOUT_FINISHED_IN; HUB_CTS_STATUS_BITS_OUT <= GBE_CTS_STATUS_BITS_IN; + proc_reset: process is + variable counter_v : integer range 0 to 15 := 0; + begin + wait until rising_edge(CBMNET_CLK_IN); + + if RESET_IN='1' or CBMNET_RESET_IN='1' or CBMNET_LINK_ACTIVE_IN='0' then + counter_v := 0; + elsif counter_v /= 15 then + counter_v := counter_v + 1; + end if; + + reset_combined_125_i <= '1'; + if counter_v = 15 then + reset_combined_125_i <= '0'; + end if; + end process; + reset_combined_i <= reset_combined_125_i when rising_edge(CLK_IN); + + THE_DECODER: CBMNET_READOUT_TRBNET_DECODER port map ( -- TrbNet @@ -163,13 +188,13 @@ begin DEBUG_OUT => debug_decorder_i -- out std_logic_vector(31 downto 0); ); - dec_reset_i <= RESET_IN or dec_issue_reset_i; + dec_reset_i <= reset_combined_i or dec_issue_reset_i; THE_PACKER: CBMNET_READOUT_EVENT_PACKER port map ( -- TrbNet CLK_IN => CLK_IN, -- in std_logic; - RESET_IN => RESET_IN, -- in std_logic; + RESET_IN => reset_combined_i, -- in std_logic; -- connect to hub HUB_CTS_NUMBER_IN => HUB_CTS_NUMBER_IN, -- in std_logic_vector (15 downto 0); @@ -206,11 +231,11 @@ begin THE_READOUT_FIFO: CBMNET_READOUT_FIFO generic map ( ADDR_WIDTH => 12, -- 8kb .. - WATERMARK => 2 + WATERMARK => 8 ) port map ( -- write port WCLK_IN => CLK_IN, -- in std_logic; -- not faster than rclk_in - WRESET_IN => RESET_IN, -- in std_logic; + WRESET_IN => reset_combined_i, -- in std_logic; WADDR_STORE_IN => fifo_waddr_store_i, -- in std_logic; WADDR_RESTORE_IN => fifo_waddr_restore_i, -- in std_logic; @@ -219,24 +244,26 @@ begin WENQUEUE_IN => fifo_wenqueue_i, -- in std_logic; WPACKET_COMPLETE_IN => fifo_wpacket_complete_i, -- in std_logic; - WALMOST_FULL_OUT => open, -- out std_logic; - WFULL_OUT => fifo_wfull_i, -- out std_logic; + WALMOST_FULL_OUT => fifo_wfull_i, -- out std_logic; + WFULL_OUT => open, -- out std_logic; -- read port RCLK_IN => CBMNET_CLK_IN, -- in std_logic; - RRESET_IN => CBMNET_RESET_IN, -- in std_logic; -- has to active at least two clocks AFTER (or while) write port was (is being) initialised + RRESET_IN => reset_combined_125_i, -- in std_logic; -- has to active at least two clocks AFTER (or while) write port was (is being) initialised RDATA_OUT => fifo_rdata_i, -- out std_logic_vector(17 downto 0); RDEQUEUE_IN => fifo_rdequeue_i, -- in std_logic; RPACKET_COMPLETE_OUT => fifo_rpacket_complete_i, -- out std_logic; -- atleast one packet is completed in fifo - RPACKET_COMPLETE_ACK_IN => fifo_rpacket_complete_ack_i -- in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one) + RPACKET_COMPLETE_ACK_IN => fifo_rpacket_complete_ack_i, -- in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one) + + DEBUG_OUT => debug_fifo_i ); - THE_TX_FSM: CBMNET_READOUT_TX_FSM + THE_FRAME_PACKER: CBMNET_READOUT_FRAME_PACKER port map ( CLK_IN => CBMNET_CLK_IN, -- in std_logic; - RESET_IN => CBMNET_RESET_IN, -- in std_logic; + RESET_IN => reset_combined_i, -- in std_logic; -- fifo FIFO_DATA_IN => fifo_rdata_i(15 downto 0), -- in std_logic_vector(15 downto 0); @@ -245,17 +272,33 @@ begin FIFO_PACKET_COMPLETE_ACK_OUT => fifo_rpacket_complete_ack_i, -- out std_logic; -- cbmnet - CBMNET_STOP_IN => CBMNET_DATA2SEND_STOP_IN, -- in std_logic; - CBMNET_START_OUT => cbmnet_data2send_start_i, -- out std_logic; - CBMNET_END_OUT => cbmnet_data2send_end_i, -- out std_logic; - CBMNET_DATA_OUT => cbmnet_data2send_data_i, -- out std_logic_vector(15 downto 0) + CBMNET_STOP_IN => obuf_stop_i, -- in std_logic; + CBMNET_START_OUT => frame_packer_start_i, -- out std_logic; + CBMNET_END_OUT => frame_packer_end_i, -- out std_logic; + CBMNET_DATA_OUT => frame_packer_data_i, -- out std_logic_vector(15 downto 0) DEBUG_OUT => debug_tx_fsm_i ); - CBMNET_DATA2SEND_DATA_OUT <= cbmnet_data2send_data_i; - CBMNET_DATA2SEND_START_OUT <= cbmnet_data2send_start_i; - CBMNET_DATA2SEND_END_OUT <= cbmnet_data2send_end_i; + THE_OBUF: CBMNET_READOUT_OBUF + port map ( + CLK_IN => CBMNET_CLK_IN, -- std_logic; + RESET_IN => reset_combined_125_i, -- std_logic; + + -- packer + PACKER_STOP_OUT => obuf_stop_i, -- out std_logic; + PACKER_START_IN => frame_packer_start_i, -- in std_logic; + PACKER_END_IN => frame_packer_end_i, -- in std_logic; + PACKER_DATA_IN => frame_packer_data_i, -- in std_logic_vector(15 downto 0); + + -- cbmnet + CBMNET_STOP_IN => CBMNET_DATA2SEND_STOP_IN, -- in std_logic; + CBMNET_START_OUT => CBMNET_DATA2SEND_START_OUT, -- out std_logic; + CBMNET_END_OUT => CBMNET_DATA2SEND_END_OUT, -- out std_logic; + CBMNET_DATA_OUT => CBMNET_DATA2SEND_DATA_OUT, -- out std_logic_vector(15 downto 0); + + DEBUG_OUT => open -- out std_logic_vector(31 downto 0) + ); ---------------------------------------- -- Slow control and monitoring @@ -270,7 +313,7 @@ begin cbm_stat_connections_i <= cbm_stat_connections_i + 1; end if; - if cbmnet_data2send_end_i = '1' and last_end_v = '0' then + if frame_packer_end_i = '1' and last_end_v = '0' then cbm_stat_num_packets_i <= cbm_stat_num_packets_i + 1; end if; @@ -283,7 +326,7 @@ begin end if; last_link_active_v := CBMNET_LINK_ACTIVE_IN; - last_end_v := cbmnet_data2send_end_i; + last_end_v := frame_packer_end_i; end process; -- and cross over to TrbNet clock domain @@ -323,25 +366,27 @@ begin -- read case addr is - when 16#0# => regio_data_status_i(0) <= cfg_enabled_i; - when 16#1# => regio_data_status_i(16 downto 0) <= cfg_source_override_i & cfg_source_i; + when 16#00# => regio_data_status_i(0) <= cfg_enabled_i; + when 16#01# => regio_data_status_i(16 downto 0) <= cfg_source_override_i & cfg_source_i; - when 16#2# => regio_data_status_i <= std_logic_vector(stat_connections_i); - when 16#3# => regio_data_status_i <= std_logic_vector(stat_clks_dead_i); - when 16#4# => regio_data_status_i <= std_logic_vector(stat_num_send_completed_i); - when 16#5# => regio_data_status_i <= std_logic_vector(stat_num_packets_i); - when 16#6# => regio_data_status_i <= std_logic_vector(stat_num_recv_completed_i); - when 16#7# => regio_data_status_i <= std_logic_vector(stat_link_inactive_i); - when 16#8# => regio_data_status_i <= std_logic_vector(stat_num_packets_aborted_i); + when 16#02# => regio_data_status_i <= std_logic_vector(stat_connections_i); + when 16#03# => regio_data_status_i <= std_logic_vector(stat_clks_dead_i); + when 16#04# => regio_data_status_i <= std_logic_vector(stat_num_send_completed_i); + when 16#05# => regio_data_status_i <= std_logic_vector(stat_num_packets_i); + when 16#06# => regio_data_status_i <= std_logic_vector(stat_num_recv_completed_i); + when 16#07# => regio_data_status_i <= std_logic_vector(stat_link_inactive_i); + when 16#08# => regio_data_status_i <= std_logic_vector(stat_num_packets_aborted_i); -- debug only ports - when 16#9# => regio_data_status_i <= debug_decorder_i; - when 16#a# => regio_data_status_i <= debug_packer_i; - when 16#b# => regio_data_status_i <= debug_tx_fsm_i; - when 16#c# => regio_data_status_i(1 downto 0) <= fifo_wfull_i & fifo_rpacket_complete_i; - when 16#d# => regio_data_status_i <= HUB_CTS_INFORMATION_IN & HUB_CTS_CODE_IN & HUB_CTS_NUMBER_IN; - when 16#e# => regio_data_status_i <= dec_evt_info_i; - when 16#f# => regio_data_status_i <= dec_source_i & dec_length_i; + when 16#09# => regio_data_status_i <= debug_decorder_i; + when 16#0a# => regio_data_status_i <= debug_packer_i; + when 16#0b# => regio_data_status_i <= debug_tx_fsm_i; + when 16#0c# => regio_data_status_i(1 downto 0) <= fifo_wfull_i & fifo_rpacket_complete_i; + when 16#0d# => regio_data_status_i <= HUB_CTS_INFORMATION_IN & HUB_CTS_CODE_IN & HUB_CTS_NUMBER_IN; + when 16#0e# => regio_data_status_i <= dec_evt_info_i; + when 16#0f# => regio_data_status_i <= dec_source_i & dec_length_i; + + when 16#10# => regio_data_status_i <= debug_fifo_i; when others => regio_unkown_address_i <= REGIO_READ_ENABLE_IN; end case; diff --git a/cbmnet/code/cbmnet_readout_fifo.vhd b/cbmnet/code/cbmnet_readout_fifo.vhd index 5c9701f..381d8a5 100644 --- a/cbmnet/code/cbmnet_readout_fifo.vhd +++ b/cbmnet/code/cbmnet_readout_fifo.vhd @@ -6,7 +6,7 @@ library ieee; entity CBMNET_READOUT_FIFO is generic ( ADDR_WIDTH : positive := 10; - WATERMARK : positive := 2 + WATERMARK : positive := 4 ); port ( @@ -32,7 +32,9 @@ entity CBMNET_READOUT_FIFO is RDEQUEUE_IN : in std_logic; RPACKET_COMPLETE_OUT : out std_logic; -- atleast one packet is completed in fifo - RPACKET_COMPLETE_ACK_IN : in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one) + RPACKET_COMPLETE_ACK_IN : in std_logic; -- mark one event as dealt with (effectively decrease number of completed packets by one) + + DEBUG_OUT : out std_logic_vector(31 downto 0) ); end CBMNET_READOUT_FIFO; @@ -52,11 +54,13 @@ begin variable last_full_v : std_logic := '1'; begin wait until rising_edge(WCLK_IN); - if (wfull_i = '0' or last_full_v = '0') and WENQUEUE_IN = '1' then + if (wfull_i = '0' ) and WENQUEUE_IN = '1' then mem_i(to_integer(waddr_i)) <= WDATA_IN; end if; - last_full_v := wfull_i; + if WENQUEUE_IN='1' then + last_full_v := wfull_i; + end if; end process; -- Read Port @@ -82,9 +86,11 @@ begin delta_v := delta_v + TO_UNSIGNED(1, delta_v'length); end if; - rpacket_counter_i <= rpacket_counter_i + delta_v - TO_UNSIGNED(1, 1); + if rpacket_counter_i /= 0 or delta_v /= 0 then + rpacket_counter_i <= rpacket_counter_i + delta_v - TO_UNSIGNED(1, 1); + end if; - if rpacket_counter_i /= 0 or delta_v = 2 then + if (rpacket_counter_i /= 0 or delta_v = 2) then RPACKET_COMPLETE_OUT <= '1'; end if; end if; @@ -107,7 +113,7 @@ begin raddr_i <= next_addr_v; end process; - RDATA_OUT <= mem_i(to_integer(raddr_i)); + RDATA_OUT <= mem_i(to_integer(raddr_i)) when rising_edge(RCLK_IN); -- Write Port wread_pointer_i <= raddr_i when rising_edge(WCLK_IN); @@ -116,10 +122,14 @@ begin wait until rising_edge(WCLK_IN); if WADDR_RESTORE_IN = '1' then waddr_i <= waddr_stored_i; - elsif wfull_i = '0' and WENQUEUE_IN = '1' then + elsif WENQUEUE_IN = '1' and wfull_i = '0' then waddr_i <= waddr_i + 1; end if; end process; + +-- synopsys translate_off + assert not(WENQUEUE_IN='1' and wfull_i='1' and rising_edge(WCLK_IN)) report "Enqueued into full fifo" severity warning; +-- synopsys translate_on WPROC_STORE_ADDR: process is begin @@ -157,4 +167,12 @@ begin WALMOST_FULL_OUT <= walmost_full_i; WFULL_OUT <= wfull_i; + + WPROC_DEBUG: process is + begin + wait until rising_edge(WCLK_IN); + DEBUG_OUT <= (others => '0'); + DEBUG_OUT(wwords_remaining_i'range) <= STD_LOGIC_VECTOR(wwords_remaining_i); + DEBUG_OUT(16+rpacket_counter_i'high downto 16) <= STD_LOGIC_VECTOR(rpacket_counter_i); + end process; end architecture; \ No newline at end of file diff --git a/cbmnet/code/cbmnet_readout_frame_packer.vhd b/cbmnet/code/cbmnet_readout_frame_packer.vhd new file mode 100644 index 0000000..5301781 --- /dev/null +++ b/cbmnet/code/cbmnet_readout_frame_packer.vhd @@ -0,0 +1,233 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + + +entity CBMNET_READOUT_FRAME_PACKER is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + + -- fifo + FIFO_DATA_IN : in std_logic_vector(15 downto 0); + FIFO_DEQUEUE_OUT : out std_logic; + FIFO_PACKET_COMPLETE_IN : in std_logic; + FIFO_PACKET_COMPLETE_ACK_OUT : out std_logic; + + -- cbmnet + CBMNET_STOP_IN : in std_logic; + CBMNET_START_OUT : out std_logic; + CBMNET_END_OUT : out std_logic; + CBMNET_DATA_OUT : out std_logic_vector(15 downto 0); + + -- debug + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); +end entity; + +architecture cbmnet_readout_frame_packer_arch of CBMNET_READOUT_FRAME_PACKER is + type FSM_STATES_T is ( + IDLE, + SETUP_TRANSACTION, SETUP_TRANSACTION_WAIT, SETUP_TRANSACTION_FETCH_LENGTH_H, SETUP_TRANSACTION_FETCH_LENGTH_L, + FIRST_FRAME_SEND_HDR, FIRST_FRAME_SEND_LENGTH_H, + BEGIN_FRAME_WAIT, BEGIN_FRAME, BEGIN_FRAME_PRE_WAIT0, BEGIN_FRAME_PRE_WAIT1, BEGIN_FRAME_PRE_WAIT2, SEND_HDR, + SEND_PAYLOAD, SEND_STOP_WORD, + COMPLETE_TRANSACTION, COMPLETE_TRANSACTION_WAIT + ); + + type FSM_STATES_ENC_T is array(FSM_STATES_T) of std_logic_vector(3 downto 0); + constant fsm_state_enc_c : FSM_STATES_ENC_T := ( + IDLE => x"0", + SETUP_TRANSACTION => x"1", SETUP_TRANSACTION_WAIT => x"2", SETUP_TRANSACTION_FETCH_LENGTH_H => x"3", SETUP_TRANSACTION_FETCH_LENGTH_L => x"4", + FIRST_FRAME_SEND_HDR => x"5", FIRST_FRAME_SEND_LENGTH_H => x"6", + BEGIN_FRAME => x"7", SEND_HDR => x"8", BEGIN_FRAME_WAIT => x"c", BEGIN_FRAME_PRE_WAIT0 => x"d", BEGIN_FRAME_PRE_WAIT1 => x"d", BEGIN_FRAME_PRE_WAIT2 => x"d", + SEND_PAYLOAD => x"9", SEND_STOP_WORD => x"a", + COMPLETE_TRANSACTION => x"b", COMPLETE_TRANSACTION_WAIT => x"b" + ); + + signal fsm_i : FSM_STATES_T; + + signal transaction_number_i : unsigned(15 downto 0); + signal frame_number_i : unsigned( 6 downto 0); -- frame in current transaction + + signal remaining_words_in_transaction_i : unsigned(15 downto 0); + signal remaining_words_in_frame_i : unsigned(15 downto 0); + signal remaining_words_to_dequeue_i : unsigned(15 downto 0); + + signal dequeue_i : std_logic; + + signal buf_length_h_i : std_logic_vector(15 downto 0); + +begin + + PROC_TX_CNTL: process is + variable dequeue_forced_v : std_logic; + variable dequeue_if_allowed_v : std_logic; + begin + wait until rising_edge(CLK_IN); + + CBMNET_START_OUT <= '0'; + CBMNET_END_OUT <= '0'; + CBMNET_DATA_OUT <= FIFO_DATA_IN; + + dequeue_if_allowed_v := '0'; + dequeue_forced_v := '0'; + + FIFO_PACKET_COMPLETE_ACK_OUT <= '0'; + + if RESET_IN = '1' then + fsm_i <= IDLE; + transaction_number_i <= (others => '0'); + + else + case(fsm_i) is + when IDLE => + if FIFO_PACKET_COMPLETE_IN='1' then + fsm_i <= SETUP_TRANSACTION; + end if; + + when SETUP_TRANSACTION => + frame_number_i <= (others => '0'); + transaction_number_i <= transaction_number_i + 1; + dequeue_forced_v := '1'; + fsm_i <= SETUP_TRANSACTION_WAIT; + + when SETUP_TRANSACTION_WAIT => + fsm_i <= SETUP_TRANSACTION_FETCH_LENGTH_H; + + when SETUP_TRANSACTION_FETCH_LENGTH_H => + buf_length_h_i <= FIFO_DATA_IN; + assert(FIFO_DATA_IN = x"0000"); + fsm_i <= SETUP_TRANSACTION_FETCH_LENGTH_L; + + when SETUP_TRANSACTION_FETCH_LENGTH_L => + remaining_words_in_transaction_i <= (others =>'0'); + remaining_words_in_transaction_i(14 downto 0) <= UNSIGNED(FIFO_DATA_IN(15 downto 1)); + remaining_words_to_dequeue_i <= (others =>'0'); + remaining_words_to_dequeue_i(14 downto 0) <= UNSIGNED(FIFO_DATA_IN(15 downto 1)) - TO_UNSIGNED(1, 15); + assert(to_integer(UNSIGNED(FIFO_DATA_IN)) >= 24) report "TrbNet packet too short. Expect minimal length of 24 bytes."; + assert(to_integer(UNSIGNED(FIFO_DATA_IN)) < 4096) report "TrbNet packet too long. This module should support sending of transactions with upto 32kb data, but only 4kb transactions have been specified and tested"; + fsm_i <= FIRST_FRAME_SEND_HDR; + + when FIRST_FRAME_SEND_HDR => + CBMNET_DATA_OUT <= (others => '0'); + remaining_words_in_frame_i <= TO_UNSIGNED(31, 16); + if remaining_words_in_transaction_i <= 31 then + CBMNET_DATA_OUT(15) <= '1'; -- stop + remaining_words_in_frame_i <= remaining_words_in_transaction_i; + end if; + CBMNET_DATA_OUT(14) <= '1'; -- start + CBMNET_DATA_OUT(11 downto 0) <= STD_LOGIC_VECTOR(transaction_number_i(11 downto 0)); + + if CBMNET_STOP_IN='0' then + dequeue_if_allowed_v := '1'; + CBMNET_START_OUT <= '1'; + fsm_i <= FIRST_FRAME_SEND_LENGTH_H; + end if; + + when FIRST_FRAME_SEND_LENGTH_H => + CBMNET_DATA_OUT <= buf_length_h_i; + dequeue_if_allowed_v := '1'; + remaining_words_in_frame_i <= remaining_words_in_frame_i - 1; + remaining_words_in_transaction_i <= remaining_words_in_transaction_i - 1; + fsm_i <= SEND_PAYLOAD; + + + when BEGIN_FRAME_PRE_WAIT0 => + fsm_i <= BEGIN_FRAME_PRE_WAIT1; + when BEGIN_FRAME_PRE_WAIT1 => + fsm_i <= BEGIN_FRAME_PRE_WAIT2; + when BEGIN_FRAME_PRE_WAIT2 => + fsm_i <= BEGIN_FRAME; + + when BEGIN_FRAME => + if CBMNET_STOP_IN='0' then + dequeue_if_allowed_v := '1'; + fsm_i <= SEND_HDR; + frame_number_i <= frame_number_i + 1; + end if; + + when BEGIN_FRAME_WAIT => + dequeue_if_allowed_v := '1'; + fsm_i <= SEND_HDR; + + when SEND_HDR => + CBMNET_DATA_OUT <= (others => '0'); + remaining_words_in_frame_i <= TO_UNSIGNED(31, 16); + + if remaining_words_in_transaction_i <= 31 then + CBMNET_DATA_OUT(15) <= '1'; -- stop + CBMNET_DATA_OUT(11 downto 0) <= STD_LOGIC_VECTOR(transaction_number_i(11 downto 0)); + + if remaining_words_in_transaction_i <= 3 then + remaining_words_in_frame_i <= TO_UNSIGNED(3, 16); + else + remaining_words_in_frame_i <= remaining_words_in_transaction_i; + end if; + + else + CBMNET_DATA_OUT(11 downto 7) <= STD_LOGIC_VECTOR(transaction_number_i(4 downto 0)); + CBMNET_DATA_OUT(6 downto 0) <= STD_LOGIC_VECTOR(frame_number_i(6 downto 0)); + end if; + + dequeue_if_allowed_v := '1'; + CBMNET_START_OUT <= '1'; + fsm_i <= SEND_PAYLOAD; + + when SEND_PAYLOAD => + if remaining_words_in_transaction_i = 0 then + CBMNET_DATA_OUT <= x"aaaa"; + else + remaining_words_in_transaction_i <= remaining_words_in_transaction_i - 1; + end if; + + remaining_words_in_frame_i <= remaining_words_in_frame_i - 1; + if remaining_words_in_frame_i > 3 then + dequeue_if_allowed_v := '1'; + end if; + + if remaining_words_in_frame_i = 2 then + fsm_i <= SEND_STOP_WORD; + end if; + + when SEND_STOP_WORD => + if remaining_words_in_transaction_i = 0 then + CBMNET_DATA_OUT <= x"aaaa"; + else + remaining_words_in_transaction_i <= remaining_words_in_transaction_i - 1; + end if; + remaining_words_in_frame_i <= remaining_words_in_frame_i - 1; + dequeue_if_allowed_v := '1'; + + CBMNET_END_OUT <= '1'; + if remaining_words_in_transaction_i = 1 or remaining_words_in_transaction_i = 0 then + fsm_i <= COMPLETE_TRANSACTION; + FIFO_PACKET_COMPLETE_ACK_OUT <= '1'; + else + fsm_i <= BEGIN_FRAME_PRE_WAIT0; + end if; + + + when COMPLETE_TRANSACTION => + assert(remaining_words_to_dequeue_i = 0) report "Fifo was not properly emptied"; + fsm_i <= COMPLETE_TRANSACTION_WAIT; + + when COMPLETE_TRANSACTION_WAIT => + fsm_i <= IDLE; + + + end case; + + dequeue_i <= dequeue_forced_v; + if dequeue_if_allowed_v = '1' and remaining_words_to_dequeue_i > 0 then + dequeue_i <= '1'; + remaining_words_to_dequeue_i <= remaining_words_to_dequeue_i - 1; + end if; + end if; + end process; + + FIFO_DEQUEUE_OUT <= dequeue_i; + DEBUG_OUT(31 downto 4) <= (others => '0'); + DEBUG_OUT(3 downto 0) <= fsm_state_enc_c(fsm_i); +end architecture; + diff --git a/cbmnet/code/cbmnet_readout_obuf.vhd b/cbmnet/code/cbmnet_readout_obuf.vhd new file mode 100644 index 0000000..134216d --- /dev/null +++ b/cbmnet/code/cbmnet_readout_obuf.vhd @@ -0,0 +1,190 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + use work.cbmnet_interface_pkg.all; + +-- this small output buffer is necessary, as the CBMNet interface directly switches to streaming +-- mode once it accepted a start flag. thus the latency between the main buffer over the frame packer to lp_top +-- is to large to corretly implement the stop - flag. +entity CBMNET_READOUT_OBUF is + port( + CLK_IN : std_logic; + RESET_IN : std_logic; + + -- packer + PACKER_STOP_OUT : out std_logic; + PACKER_START_IN : in std_logic; + PACKER_END_IN : in std_logic; + PACKER_DATA_IN : in std_logic_vector(15 downto 0); + + -- cbmnet + CBMNET_STOP_IN : in std_logic; + CBMNET_START_OUT : out std_logic; + CBMNET_END_OUT : out std_logic; + CBMNET_DATA_OUT : out std_logic_vector(15 downto 0); + + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); +end entity; + +architecture cbmnet_readout_obuf_arch of CBMNET_READOUT_OBUF is + signal read_fifo_i, read_fifo_next_i, write_fifo_i : integer range 0 to 1 := 0; + + signal fifo_empty_i : std_logic_vector(1 downto 0); + signal fifo_enqueue_i : std_logic_vector(1 downto 0); + signal fifo_dequeue_i : std_logic_vector(1 downto 0); + signal fifo_last_i : std_logic_vector(1 downto 0); + signal fifo_set_filled_i : std_logic_vector(1 downto 0); + signal fifo_get_filled_i : std_logic_vector(1 downto 0); + + signal fifo_read_data_i : std_logic_vector(31 downto 0); + signal fifo_write_data_i : std_logic_vector(15 downto 0); + + signal fifo_deq_i : std_logic; + + type WFSM_T is (OBTAIN_FREE_BUFFER, WAIT_FOR_START, WAIT_FOR_END, COMPLETE); + signal wfsm_i : WFSM_T; + + type RFSM_T is (OBTAIN_FULL_BUFFER, WAIT_WHILE_STOP, COPY, COMPLETE); + signal rfsm_i, rfsm_next_i : RFSM_T; +begin + WPROC: process is + begin + wait until rising_edge(CLK_IN); + + fifo_enqueue_i <= "00"; + fifo_set_filled_i <= "00"; + PACKER_STOP_OUT <= '0'; + + if RESET_IN='1' then + wfsm_i <= OBTAIN_FREE_BUFFER; + + else + case (wfsm_i) is + when OBTAIN_FREE_BUFFER => + if fifo_get_filled_i(0) = '0' then + write_fifo_i <= 0; + wfsm_i <= WAIT_FOR_START; + elsif fifo_get_filled_i(1) = '0' then + write_fifo_i <= 1; + wfsm_i <= WAIT_FOR_START; + else + PACKER_STOP_OUT <= '1'; + end if; + + when WAIT_FOR_START => + if PACKER_START_IN='1' then + fifo_enqueue_i(write_fifo_i) <= '1'; + wfsm_i <= WAIT_FOR_END; + end if; + + + when WAIT_FOR_END => + fifo_enqueue_i(write_fifo_i) <= '1'; + if PACKER_END_IN='1' then + fifo_set_filled_i(write_fifo_i) <= '1'; + wfsm_i <= COMPLETE; + end if; + + when COMPLETE => + PACKER_STOP_OUT <= '1'; + wfsm_i <= OBTAIN_FREE_BUFFER; + + end case; + end if; + end process; + + RSYNC: process is + begin + wait until rising_edge(CLK_IN); + + if RESET_IN='1' then + rfsm_i <= OBTAIN_FULL_BUFFER; + else + rfsm_i <= rfsm_next_i; + end if; + read_fifo_i <= read_fifo_next_i; + end process; + + RASYNC: process(rfsm_i, fifo_get_filled_i, fifo_last_i, CBMNET_STOP_IN) is + begin + CBMNET_START_OUT <= '0'; + CBMNET_END_OUT <= '0'; + + fifo_deq_i <= '0'; + rfsm_next_i <= rfsm_i; + read_fifo_next_i <= read_fifo_i; + fifo_empty_i <= "00"; + + case(rfsm_i) is + when OBTAIN_FULL_BUFFER => + if fifo_get_filled_i(0) = '1' then + read_fifo_next_i <= 0; + rfsm_next_i <= WAIT_WHILE_STOP; + elsif fifo_get_filled_i(1) = '1' then + read_fifo_next_i <= 1; + rfsm_next_i <= WAIT_WHILE_STOP; + end if; + + when WAIT_WHILE_STOP => + CBMNET_START_OUT <= '1'; + if CBMNET_STOP_IN='0' then + fifo_deq_i <= '1'; + rfsm_next_i <= COPY; + end if; + + when COPY => + fifo_deq_i <= '1'; + if fifo_last_i(read_fifo_i)='1' then + CBMNET_END_OUT <= '1'; + rfsm_next_i <= COMPLETE; + end if; + + when others => + fifo_empty_i(read_fifo_i) <= '1'; + rfsm_next_i <= OBTAIN_FULL_BUFFER; + end case; + end process; + + -- fifo multiplexer + fifo_dequeue_i <= "0" & fifo_deq_i when read_fifo_i=0 else fifo_deq_i&"0"; + CBMNET_DATA_OUT <= fifo_read_data_i(read_fifo_i*16 + 15 downto read_fifo_i*16); + + THE_FIFO_0: CBMNET_READOUT_TX_FIFO + port map ( + CLK_IN => CLK_IN, -- in std_logic; + RESET_IN => RESET_IN, -- in std_logic; + EMPTY_IN => fifo_empty_i(0), -- in std_logic; -- identical to reset_in + + DATA_IN => fifo_write_data_i, -- in std_logic_vector(15 downto 0); + DATA_OUT => fifo_read_data_i(0*16 + 15 downto 0*16), -- out std_logic_vector(15 downto 0); + + ENQUEUE_IN => fifo_enqueue_i(0), -- in std_logic; + DEQUEUE_IN => fifo_dequeue_i(0), -- in std_logic; + + LAST_OUT => fifo_last_i(0), -- out std_logic; + + FILLED_IN => fifo_set_filled_i(0), -- in std_logic; + FILLED_OUT => fifo_get_filled_i(0) -- out std_logic; + ); + + THE_FIFO_1: CBMNET_READOUT_TX_FIFO + port map ( + CLK_IN => CLK_IN, -- in std_logic; + RESET_IN => RESET_IN, -- in std_logic; + EMPTY_IN => fifo_empty_i(1), -- in std_logic; -- identical to reset_in + + DATA_IN => fifo_write_data_i, -- in std_logic_vector(15 downto 0); + DATA_OUT => fifo_read_data_i(1*16 + 15 downto 1*16), -- out std_logic_vector(15 downto 0); + + ENQUEUE_IN => fifo_enqueue_i(1), -- in std_logic; + DEQUEUE_IN => fifo_dequeue_i(1), -- in std_logic; + + LAST_OUT => fifo_last_i(1), -- out std_logic; + + FILLED_IN => fifo_set_filled_i(1), -- in std_logic; + FILLED_OUT => fifo_get_filled_i(1) -- out std_logic; + ); + + fifo_write_data_i <= PACKER_DATA_IN when rising_edge(CLK_IN); +end architecture; \ No newline at end of file diff --git a/cbmnet/code/cbmnet_readout_trbnet_decoder.vhd b/cbmnet/code/cbmnet_readout_trbnet_decoder.vhd index 4a7ad1f..cf24f06 100644 --- a/cbmnet/code/cbmnet_readout_trbnet_decoder.vhd +++ b/cbmnet/code/cbmnet_readout_trbnet_decoder.vhd @@ -38,22 +38,6 @@ entity CBMNET_READOUT_TRBNET_DECODER is end entity; architecture cbmnet_readout_trbnet_decoder_arch of CBMNET_READOUT_TRBNET_DECODER is --- component lattice_ecp3_fifo_16x16_dualport is --- port ( --- Data: in std_logic_vector(15 downto 0); --- WrClock: in std_logic; --- RdClock: in std_logic; --- WrEn: in std_logic; --- RdEn: in std_logic; --- Reset: in std_logic; --- RPReset: in std_logic; --- Q: out std_logic_vector(15 downto 0); --- Empty: out std_logic; --- Full: out std_logic; --- AlmostFull: out std_logic --- ); --- end component; --- constant FIFO_LENGTH_C : integer := 4; type FIFO_MEM_T is array(0 to 2**FIFO_LENGTH_C-1) of std_logic_vector(15 downto 0); signal fifo_mem_i : FIFO_MEM_T; @@ -133,6 +117,9 @@ begin word_counter_set_i <= '1'; if read_word_i = '1' then dec_length_i <= data_i(13 downto 0) & "00"; +-- synopsys translate_off + assert data_i(13 downto 0) & "00" /= x"0000" report "TrbNet packet must not be of length 0" severity warning; +-- synopsys translate_on fsm_i <= RECV_EVT_SOURCE; end if; diff --git a/cbmnet/code/cbmnet_readout_tx_fifo.vhd b/cbmnet/code/cbmnet_readout_tx_fifo.vhd new file mode 100644 index 0000000..420316a --- /dev/null +++ b/cbmnet/code/cbmnet_readout_tx_fifo.vhd @@ -0,0 +1,63 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity cbmnet_readout_tx_fifo is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + EMPTY_IN : in std_logic; -- identical to reset_in + + + DATA_IN : in std_logic_vector(15 downto 0); + DATA_OUT : out std_logic_vector(15 downto 0); + + ENQUEUE_IN : in std_logic; + DEQUEUE_IN : in std_logic; + + LAST_OUT : out std_logic; + + FILLED_IN : in std_logic; + FILLED_OUT : out std_logic + ); +end entity; + +architecture RTL of cbmnet_readout_tx_fifo is + type MEM_T is array(0 to 31) of std_logic_vector(15 downto 0); + signal mem_i : MEM_T; + + signal raddr_i, waddr_i : unsigned(5 downto 0); + signal filled_i : std_logic; +begin + + WPROC: process is + begin + wait until rising_edge(CLK_IN); + + if RESET_IN='1' or EMPTY_IN='1' then + waddr_i <= (others => '0'); + elsif ENQUEUE_IN='1' then + mem_i(to_integer(waddr_i(4 downto 0))) <= DATA_IN; + if waddr_i /= "100000" then + waddr_i <= waddr_i + 1; + end if; + end if; + end process; + + RPROC: process is + begin + wait until rising_edge(CLK_IN); + + if RESET_IN='1' or EMPTY_IN='1' then + raddr_i <= (others => '0'); + elsif DEQUEUE_IN='1' then + raddr_i <= raddr_i + 1; + end if; + end process; + + LAST_OUT <= '1' when raddr_i+1 >= waddr_i else '0'; + DATA_OUT <= mem_i(to_integer(raddr_i(4 downto 0))); + + filled_i <= not(RESET_IN or EMPTY_IN) and (filled_i or FILLED_IN) when rising_edge(CLK_IN); + FILLED_OUT <= filled_i; +end architecture; \ No newline at end of file diff --git a/cbmnet/code/cbmnet_readout_tx_fsm.vhd b/cbmnet/code/cbmnet_readout_tx_fsm.vhd deleted file mode 100644 index 3f51b73..0000000 --- a/cbmnet/code/cbmnet_readout_tx_fsm.vhd +++ /dev/null @@ -1,186 +0,0 @@ -library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - - -entity CBMNET_READOUT_TX_FSM is - port ( - CLK_IN : in std_logic; - RESET_IN : in std_logic; - - -- fifo - FIFO_DATA_IN : in std_logic_vector(15 downto 0); - FIFO_DEQUEUE_OUT : out std_logic; - FIFO_PACKET_COMPLETE_IN : in std_logic; - FIFO_PACKET_COMPLETE_ACK_OUT : out std_logic; - - -- cbmnet - CBMNET_STOP_IN : in std_logic; - CBMNET_START_OUT : out std_logic; - CBMNET_END_OUT : out std_logic; - CBMNET_DATA_OUT : out std_logic_vector(15 downto 0); - - -- debug - DEBUG_OUT : out std_logic_vector(31 downto 0) - ); -end entity; - -architecture cbmnet_readout_tx_fsm_arch of CBMNET_READOUT_TX_FSM is - constant PAYLOAD_PER_PACKET_C : integer := 62; -- bytes - - - type FSM_STATES_T is (WAIT_FOR_COMPL_PACKET, SETUP_TRANSACTION, SETUP_TRANSACTION_RECV_LENGTH, SETUP_SEND_START_HEADER, SEND_START_LENGTH_HIGH, SEND_START_LENGTH_LOW, SEND_HEADER, SEND_PAYLOAD, SEND_PACKET_GAP, FINISH_TRANSACTION, FINISH_WAIT1, FINISH_WAIT2); - signal fsm_i : FSM_STATES_T; - signal fsm_state_i : unsigned(3 downto 0); - - signal trans_num_i : unsigned(5 downto 0); - - signal buffer_bytes_length_high_i : std_logic_vector(15 downto 0) := x"0000"; - signal trans_bytes_length_i : unsigned(15 downto 0) := x"0000"; - signal trans_bytes_send_i : unsigned(15 downto 0); - - signal pack_num_i : unsigned(5 downto 0); - signal pack_payload_words_i : unsigned(4 downto 0); - - signal pack_start_i, pack_stop_i : std_logic; - - signal trans_complete_i : std_logic; - - - -begin - assert(buffer_bytes_length_high_i = x"0000"); - - PROC_TX_CNTL: process is - begin - wait until rising_edge(CLK_IN); - - CBMNET_START_OUT <= '0'; - CBMNET_END_OUT <= '0'; - CBMNET_DATA_OUT <= FIFO_DATA_IN; - - FIFO_DEQUEUE_OUT <= '0'; - FIFO_PACKET_COMPLETE_ACK_OUT <= '0'; - - if RESET_IN = '1' then - fsm_i <= WAIT_FOR_COMPL_PACKET; - trans_num_i <= (others => '0'); - fsm_state_i <= x"0"; - - else - case(fsm_i) is - when WAIT_FOR_COMPL_PACKET => - fsm_state_i <= x"1"; - if FIFO_PACKET_COMPLETE_IN = '1' then - fsm_i <= SETUP_TRANSACTION; - FIFO_DEQUEUE_OUT <= '1'; - end if; - - when SETUP_TRANSACTION => - fsm_state_i <= x"2"; - trans_bytes_send_i <= (others => '0'); - pack_num_i <= (others => '0'); - pack_start_i <= '1'; - buffer_bytes_length_high_i <= FIFO_DATA_IN; - fsm_i <= SETUP_TRANSACTION_RECV_LENGTH; - - when SETUP_TRANSACTION_RECV_LENGTH => - fsm_state_i <= x"7"; - trans_bytes_send_i <= (others => '0'); - trans_bytes_length_i <= UNSIGNED(FIFO_DATA_IN); - fsm_i <= SETUP_SEND_START_HEADER; - - when SETUP_SEND_START_HEADER => - fsm_state_i <= x"8"; - trans_bytes_send_i <= (others => '0'); - pack_payload_words_i <= (others => '0'); - CBMNET_DATA_OUT <= (others => '0'); - CBMNET_DATA_OUT( 5 downto 0) <= STD_LOGIC_VECTOR(pack_num_i); - CBMNET_DATA_OUT(11 downto 6) <= STD_LOGIC_VECTOR(trans_num_i); - CBMNET_DATA_OUT(14) <= '1'; - CBMNET_DATA_OUT(15) <= pack_stop_i; - - if CBMNET_STOP_IN = '0' then - CBMNET_START_OUT <= '1'; - fsm_i <= SEND_START_LENGTH_HIGH; - end if; - - when SEND_START_LENGTH_HIGH => - fsm_state_i <= x"9"; - pack_payload_words_i <= (others => '0'); - trans_bytes_send_i <= TO_UNSIGNED(4, 16); -- +2 so trans_complete computation becomes easier - pack_payload_words_i <= TO_UNSIGNED(1, 5); - CBMNET_DATA_OUT <= buffer_bytes_length_high_i; - fsm_i <= SEND_PAYLOAD; - FIFO_DEQUEUE_OUT <= '1'; - - when SEND_START_LENGTH_LOW => - fsm_state_i <= x"a"; - CBMNET_DATA_OUT <= STD_LOGIC_VECTOR(trans_bytes_length_i); - fsm_i <= SEND_PAYLOAD; - - when SEND_HEADER => - fsm_state_i <= x"3"; - CBMNET_DATA_OUT <= (others => '0'); - CBMNET_DATA_OUT( 5 downto 0) <= STD_LOGIC_VECTOR(pack_num_i); - CBMNET_DATA_OUT(11 downto 6) <= STD_LOGIC_VECTOR(trans_num_i); - CBMNET_DATA_OUT(14) <= '0'; - CBMNET_DATA_OUT(15) <= pack_stop_i; - - pack_payload_words_i <= (others => '0'); - - if CBMNET_STOP_IN = '0' then - CBMNET_START_OUT <= '1'; - FIFO_DEQUEUE_OUT <= '1'; - fsm_i <= SEND_PAYLOAD; - end if; - - when SEND_PAYLOAD => - fsm_state_i <= x"4"; - if pack_payload_words_i = 30 or trans_complete_i = '1' then - CBMNET_END_OUT <= '1'; - pack_num_i <= pack_num_i + 1; - - if trans_complete_i = '1' then - fsm_i <= FINISH_TRANSACTION; - else - fsm_i <= SEND_PACKET_GAP; - end if; - - else - FIFO_DEQUEUE_OUT <= '1'; - end if; - - pack_start_i <= '0'; - pack_payload_words_i <= pack_payload_words_i + 1; - trans_bytes_send_i <= trans_bytes_send_i + 2; - - - when SEND_PACKET_GAP => - fsm_state_i <= x"5"; - fsm_i <= SEND_HEADER; - - when FINISH_TRANSACTION => - fsm_state_i <= x"6"; - FIFO_PACKET_COMPLETE_ACK_OUT <= '1'; - trans_num_i <= trans_num_i + 1; - fsm_i <= FINISH_WAIT1; - - when FINISH_WAIT1 => - fsm_state_i <= x"6"; - fsm_i <= FINISH_WAIT2; - - when FINISH_WAIT2 => - fsm_state_i <= x"6"; - fsm_i <= WAIT_FOR_COMPL_PACKET; - - end case; - end if; - end process; - - pack_stop_i <= '1' when trans_bytes_length_i - trans_bytes_send_i < PAYLOAD_PER_PACKET_C else '0'; - trans_complete_i <= '1' when trans_bytes_length_i = trans_bytes_send_i else '0'; - - DEBUG_OUT(3 downto 0) <= STD_LOGIC_VECTOR(fsm_state_i); -end architecture; - diff --git a/cbmnet/code/tb_cbmnet_logger.vhd b/cbmnet/code/tb_cbmnet_logger.vhd index d1b2a16..8ef9233 100644 --- a/cbmnet/code/tb_cbmnet_logger.vhd +++ b/cbmnet/code/tb_cbmnet_logger.vhd @@ -33,7 +33,7 @@ begin variable frame_line_v : line; begin wait until rising_edge(CLK_IN); - + if RESET_IN = '0' and LINK_ACTIVE_IN = '1' then case (fsm_i) is when IDLE => @@ -50,7 +50,7 @@ begin write(frame_line_v, " " & hstr(DATA2SEND_IN)); word_count_i <= word_count_i + 1; - if DATA2SEND_STOP_IN = '1' then + if DATA2SEND_END_IN = '1' then writeline(l_file, frame_line_v); --println ("DATA(" & str(word_count_i*2) & ") :" & frame_str_i); fsm_i <= IDLE; @@ -63,4 +63,6 @@ begin end if; end process; + assert word_count_i <= 32 report "CBMNet frame must not be longer than 64 bytes" severity warning; + end architecture; \ No newline at end of file diff --git a/cbmnet/code/tb_cbmnet_readout.vhd b/cbmnet/code/tb_cbmnet_readout.vhd index fd39dd5..be4f476 100644 --- a/cbmnet/code/tb_cbmnet_readout.vhd +++ b/cbmnet/code/tb_cbmnet_readout.vhd @@ -79,9 +79,6 @@ begin HUB_CTS_READOUT_TYPE_IN <= x"e"; GBE_CTS_STATUS_BITS_IN <= x"12345678"; -00:00:00:70:00:03:00:62:00:00:00:64:00:02:00:11:00:00:f3:c0:00:09:45:f7: -00:12:f3:c0:20:06:f3:53:cf:0f:3c:7c:00:00:00:61:cf:0f:3c:7c:05:06:ac:6e:cf:0f:3c:7c:00:00:00:00:00:00:00:00:00:00:00:00:cf:0f:3c:7c:00:00:00:61:cf:0f:3c:7c:05:06:ac:6e:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00: -00:01:55:55:00:00:00:01: wait until rising_edge(CLK_IN); wait until rising_edge(CLK_IN); wait until rising_edge(CLK_IN); diff --git a/cbmnet/code/tb_cbmnet_readout2.vhd b/cbmnet/code/tb_cbmnet_readout2.vhd index a96e90a..6374253 100644 --- a/cbmnet/code/tb_cbmnet_readout2.vhd +++ b/cbmnet/code/tb_cbmnet_readout2.vhd @@ -1,8 +1,9 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; + use ieee.math_real.all; use work.cbmnet_interface_pkg.all; - + entity tb_cbmnet_readout2 is end tb_cbmnet_readout2; @@ -79,7 +80,7 @@ architecture TB of tb_cbmnet_readout2 is signal send_wait_threshold_i : unsigned(31 downto 0) := x"0000_0010"; signal event_id : unsigned(15 downto 0) := x"0000"; - signal send_length_i : unsigned(15 downto 0) := x"0010"; + signal send_length_i : unsigned(15 downto 0) := x"0100"; signal send_counter_i : unsigned(15 downto 0); signal send_enabled_i : std_logic := '0'; @@ -88,17 +89,25 @@ architecture TB of tb_cbmnet_readout2 is type TRB_FSM_T is (IDLE, START_READOUT, START_READOUT_WAIT, FEE_BUSY, SEND_EINF_H, SEND_EINF_L, SEND_LENGTH, SEND_SOURCE, SEND_SOURCE_WAIT, SEND_PAYLOAD_H, SEND_PAYLOAD_L, COMPL_WAIT, COMPL_NOT_BUSY_WAIT, EVT_WAIT); signal trb_fsm_i : TRB_FSM_T; + + -- FEEs + signal fee_cbm_data_from_link_i, flib_cbm_data2link_i, flib_cbm_data_from_link_i, fee_cbm_data2link_i : std_logic_vector(17 downto 0); + signal flib_cbm_serdes_ready_i, fee_cbm_serdes_ready_i, flib_cbm_link_active_i, fee_cbm_link_active_i : std_logic; + signal cbm_reset_n_i1, cbm_reset_n_i2 : std_logic; + signal flib_data_rec_i : std_logic_vector(15 downto 0); + signal flib_data_rec_start_i, flib_data_rec_end_i, flib_data_rec_stop_i : std_logic := '0'; + begin REGIO_ADDR_IN <= (others => '0'); REGIO_DATA_IN <= x"0000_0001"; REGIO_WRITE_ENABLE_IN <= '1'; CLK_IN <= not CLK_IN after 5 ns; - RESET_IN <= '1', '0' after 30 ns; + RESET_IN <= '1', '0' after 20 ns; CBMNET_CLK_IN <= not CBMNET_CLK_IN after 4 ns; - CBMNET_RESET_IN <= '1', '0' after 20 ns; - CBMNET_LINK_ACTIVE_IN <= '1'; + CBMNET_RESET_IN <= '1', '0' after 40 ns; +-- CBMNET_LINK_ACTIVE_IN <= '0', '1' after 50 us; gbe_fee_read_in <= '1'; gbe_cts_status_bits_in <= x"beafc0de"; @@ -107,6 +116,12 @@ begin process is variable wait_cnt_v : integer range 0 to 15 := 0; + + variable seed1, seed2: positive; -- seed values for random generator + variable rand: real; -- random real-number value in range 0 to 1.0 + variable int_rand: integer; -- random integer value in range 0..4095 + + begin wait until rising_edge(CLK_IN); @@ -215,10 +230,16 @@ begin send_wait_counter_i <= send_wait_counter_i + 1; if send_wait_counter_i >= UNSIGNED(send_wait_threshold_i) then - send_length_i(9 downto 0) <= send_length_i(9 downto 0) + 1; - if send_length_i = x"0000" then - send_length_i <= x"0001"; - end if; + --send_length_i(8 downto 0) <= send_length_i(8 downto 0) + 1; + --if send_length_i = x"01ff" then + -- send_length_i <= x"0001"; + --end if; + + uniform(seed1, seed2, rand); + int_rand := 4+integer(trunc(rand*500.0)); + --int_rand := 2; + send_length_i(9 downto 0) <= TO_UNSIGNED(int_rand, 10); + trb_fsm_i <= IDLE; end if; @@ -227,19 +248,22 @@ begin PROC_CBMNET: process is - variable wait_dur : integer range 0 to 10000 := 250; + variable wait_dur : integer range 0 to 10000 := 4; + variable seed1, seed2: positive; -- seed values for random generator + variable rand: real; -- random real-number value in range 0 to 1.0 + variable int_rand: integer; -- random integer value in range 0..4095 begin - CBMNET_DATA2SEND_STOP_IN <= '0'; - wait until falling_edge(CBMNET_DATA2SEND_END_OUT); - CBMNET_DATA2SEND_STOP_IN <= '1'; + flib_data_rec_stop_i <= '0'; wait until rising_edge(CBMNET_CLK_IN); - wait for wait_dur * 8 ns; - - if wait_dur = 10000 then - wait_dur := 0; - else - wait_dur := wait_dur + 1; - end if; + uniform(seed1, seed2, rand); + int_rand := 4+integer(trunc(rand*10000.0)); + wait for int_rand * 8 ns; + + flib_data_rec_stop_i <= '1'; + wait until rising_edge(CBMNET_CLK_IN); + uniform(seed1, seed2, rand); + int_rand := 4+integer(trunc(rand*256.0)); + wait for int_rand * 8 ns; end process; --GBE_FEE_READ_IN <= HUB_FEE_DATAREADY_IN; @@ -297,6 +321,200 @@ begin CBMNET_DATA2SEND_END_OUT => CBMNET_DATA2SEND_END_OUT, -- out std_logic; CBMNET_DATA2SEND_DATA_OUT =>CBMNET_DATA2SEND_DATA_OUT -- out std_logic_vector(15 downto 0) ); + CBMNET_LINK_ACTIVE_IN <= fee_cbm_link_active_i; + + + THE_FEE_ENDPOINT: lp_top + generic map ( + NUM_LANES => 1, + TX_SLAVE => 0 + ) + port map ( + -- Clk & Reset + clk => CBMNET_CLK_IN, + res_n => cbm_reset_n_i1, + + -- Phy + data_from_link => fee_cbm_data_from_link_i, + data2link => fee_cbm_data2link_i, + link_activeovr => '0', + link_readyovr => '0', + SERDES_ready => fee_cbm_serdes_ready_i, + + -- CBMNet Interface + link_active => fee_cbm_link_active_i, + ctrl2send_stop => open, + ctrl2send_start => '0', + ctrl2send_end => '0', + ctrl2send => x"0000", + + data2send_stop(0) => CBMNET_DATA2SEND_STOP_IN, + data2send_start(0) => CBMNET_DATA2SEND_START_OUT, + data2send_end(0) => CBMNET_DATA2SEND_END_OUT, + data2send => CBMNET_DATA2SEND_DATA_OUT, + + dlm2send_va => '0', + dlm2send => x"0", + + dlm_rec_type => open, + dlm_rec_va => open, + + data_rec => open, + data_rec_start => open, + data_rec_end => open, + data_rec_stop => "0", + + ctrl_rec => open, + ctrl_rec_start => open, + ctrl_rec_end => open, + ctrl_rec_stop => '0', + + -- diagnostics Lane0 + crc_error_cntr_flag_0 => open, -- out std_logic; + retrans_cntr_flag_0 => open, -- out std_logic; + retrans_error_cntr_flag_0 => open, -- out std_logic; + crc_error_cntr_0 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_0 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_0 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_0 => '0', -- in std_logic; + retrans_cntr_clr_0 => '0', -- in std_logic; + retrans_error_cntr_clr_0 => '0', -- in std_logic; + + -- diagnostics Lane1 + crc_error_cntr_flag_1 => open, -- out std_logic; + retrans_cntr_flag_1 => open, -- out std_logic; + retrans_error_cntr_flag_1 => open, -- out std_logic; + crc_error_cntr_1 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_1 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_1 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_1 => '0', -- in std_logic; + retrans_cntr_clr_1 => '0', -- in std_logic; + retrans_error_cntr_clr_1 => '0', -- in std_logic; + + -- diagnostics Lane2 + crc_error_cntr_flag_2 => open, -- out std_logic; + retrans_cntr_flag_2 => open, -- out std_logic; + retrans_error_cntr_flag_2 => open, -- out std_logic; + crc_error_cntr_2 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_2 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_2 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_2 => '0', -- in std_logic; + retrans_cntr_clr_2 => '0', -- in std_logic; + retrans_error_cntr_clr_2 => '0', -- in std_logic; + + -- diagnostics Lane3 + crc_error_cntr_flag_3 => open, -- out std_logic; + retrans_cntr_flag_3 => open, -- out std_logic; + retrans_error_cntr_flag_3 => open, -- out std_logic; + crc_error_cntr_3 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_3 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_3 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_3 => '0', -- in std_logic; + retrans_cntr_clr_3 => '0', -- in std_logic; + retrans_error_cntr_clr_3 => '0' -- in std_logic + ); + + fee_cbm_data_from_link_i <= flib_cbm_data2link_i when rising_edge(CBMNET_CLK_IN); + flib_cbm_data_from_link_i <= fee_cbm_data2link_i when rising_edge(CBMNET_CLK_IN); + + fee_cbm_serdes_ready_i <= '0', '1' after 100 ns; + flib_cbm_serdes_ready_i <= '0', '1' after 100 ns; + + cbm_reset_n_i2 <= not CBMNET_RESET_IN; + cbm_reset_n_i1 <= transport not CBMNET_RESET_IN after 40 ns; + + THE_FLIB_ENDPOINT: lp_top + generic map ( + NUM_LANES => 1, + TX_SLAVE => 0 + ) + port map ( + -- Clk & Reset + clk => CBMNET_CLK_IN, + res_n => cbm_reset_n_i2, + + -- Phy + data_from_link => flib_cbm_data_from_link_i, + data2link => flib_cbm_data2link_i, + link_activeovr => '0', + link_readyovr => '0', + SERDES_ready => flib_cbm_serdes_ready_i, + + -- CBMNet Interface + link_active => flib_cbm_link_active_i, + ctrl2send_stop => open, + ctrl2send_start => '0', + ctrl2send_end => '0', + ctrl2send => x"0000", + + data2send_stop => open, + data2send_start => "0", + data2send_end => "0", + data2send => x"0000", + + dlm2send_va => '0', + dlm2send => x"0", + + dlm_rec_type => open, + dlm_rec_va => open, + + data_rec => flib_data_rec_i, + data_rec_start(0) => flib_data_rec_start_i, + data_rec_end(0) => flib_data_rec_end_i, + data_rec_stop(0) => flib_data_rec_stop_i, + + ctrl_rec => open, + ctrl_rec_start => open, + ctrl_rec_end => open, + ctrl_rec_stop => '0', + + -- diagnostics Lane0 + crc_error_cntr_flag_0 => open, -- out std_logic; + retrans_cntr_flag_0 => open, -- out std_logic; + retrans_error_cntr_flag_0 => open, -- out std_logic; + crc_error_cntr_0 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_0 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_0 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_0 => '0', -- in std_logic; + retrans_cntr_clr_0 => '0', -- in std_logic; + retrans_error_cntr_clr_0 => '0', -- in std_logic; + + -- diagnostics Lane1 + crc_error_cntr_flag_1 => open, -- out std_logic; + retrans_cntr_flag_1 => open, -- out std_logic; + retrans_error_cntr_flag_1 => open, -- out std_logic; + crc_error_cntr_1 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_1 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_1 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_1 => '0', -- in std_logic; + retrans_cntr_clr_1 => '0', -- in std_logic; + retrans_error_cntr_clr_1 => '0', -- in std_logic; + + -- diagnostics Lane2 + crc_error_cntr_flag_2 => open, -- out std_logic; + retrans_cntr_flag_2 => open, -- out std_logic; + retrans_error_cntr_flag_2 => open, -- out std_logic; + crc_error_cntr_2 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_2 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_2 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_2 => '0', -- in std_logic; + retrans_cntr_clr_2 => '0', -- in std_logic; + retrans_error_cntr_clr_2 => '0', -- in std_logic; + + -- diagnostics Lane3 + crc_error_cntr_flag_3 => open, -- out std_logic; + retrans_cntr_flag_3 => open, -- out std_logic; + retrans_error_cntr_flag_3 => open, -- out std_logic; + crc_error_cntr_3 => open, -- out std_logic_vector(15 downto 0); + retrans_cntr_3 => open, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_3 => open, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_3 => '0', -- in std_logic; + retrans_cntr_clr_3 => '0', -- in std_logic; + retrans_error_cntr_clr_3 => '0' -- in std_logic + ); + + + THE_LOGGER : TB_CBMNET_LOGGER generic map (log_file => "frames2.txt") @@ -311,4 +529,17 @@ begin DATA2SEND_END_IN => CBMNET_DATA2SEND_END_OUT -- std_logic ); + THE_LOGGER_RECV : TB_CBMNET_LOGGER + generic map (log_file => "recv_frames2.txt") + port map ( + CLK_IN => CBMNET_CLK_IN, -- in std_logic; + RESET_IN => CBMNET_RESET_IN, -- in std_logic; + LINK_ACTIVE_IN => flib_cbm_link_active_i, -- in std_logic; + + DATA2SEND_IN => flib_data_rec_i, -- std_logic_vector(15 downto 0); + DATA2SEND_STOP_IN => '0', -- std_logic; + DATA2SEND_START_IN => flib_data_rec_start_i, -- std_logic; + DATA2SEND_END_IN => flib_data_rec_end_i -- std_logic + ); + end architecture; \ No newline at end of file diff --git a/cbmnet/test/check_frames.pl b/cbmnet/test/check_frames.pl index 3bf4223..3553f75 100755 --- a/cbmnet/test/check_frames.pl +++ b/cbmnet/test/check_frames.pl @@ -2,6 +2,7 @@ use warnings; use strict; use Data::Dumper; +use POSIX qw/ceil/; my @packet = (); @@ -9,6 +10,7 @@ my $success = 0; my $errors = 0; my $skipped = 0; my $line = 0; +my $matched = 0; my $ref = ""; @@ -26,7 +28,7 @@ sub fassert { } sub stats { - printf("Read: % 9d | Skipped: % 9d | Success: % 9d | Errors: % 9d\n", $line, $skipped, $success, $errors) + printf("Read: % 9d | Skipped: % 9d | Success: % 9d | Errors: % 9d | Unmatched: % 9d (%.1f %%)\n", $line, $skipped, $success, $errors, $line - $matched, 100* ($line - $matched) / $line ) } my $lastFrameNo = -1; @@ -40,43 +42,51 @@ while(my $frame = ) { $ref = $1; $frame =~ s/DATA\(.*\):\s+//; $frame =~ s/\s+$//; - my @frameData = map {$_} split(" ", $frame); - print Dumper @frameData; + my @frameData = map {hex} split(" ", $frame); - next unless fassert($#frameData > 0, "Frame must no be empty"); - next unless fassert($#frameData <= 32, "Frame must no be longer than 64 bytes. Got " . (2*$#frameData)); + next unless fassert($#frameData+1 >= 4, "Frame must no be shorter than 8 bytes. Got " . (2*$#frameData+2)); + next unless fassert($#frameData+1 <= 32, "Frame must no be longer than 64 bytes. Got " . (2*$#frameData+2)); my $hdr = shift @frameData; my $start = ($hdr & 0x4000) != 0; my $end = ($hdr & 0x8000) != 0; - my $frameNo = $hdr & 0x3f; - my $transNo = ($hdr >> 6) & 0x3f; + my $frameNo = $hdr & 0x7f; + my $transNo = ($hdr >> 7) & 0x1f; - print "$#frameData\n"; + if ($start or $end) { + $transNo = $hdr & 0xfff; + } + + #print "$#frameData\n"; next unless fassert($#frameData == 30 or $end, "Only last frame can be shorted than 64 bytes. Got " . (2*$#frameData+2)); if ($start) { - my $exp = ($lastTransNo+1) & 0x3f; + my $exp = ($lastTransNo+1) & 0xfff; fassert($lastTransNo == -1 or $exp == $transNo, "Expected sequential transaction numbers. Exp $exp. Got $transNo"); fassert(-1 == $#packet, "Unexpected start"); @packet = @frameData; $lastTransNo = $transNo; } else { + if ($#packet == -1) { $skipped++; } else { - next unless fassert($lastTransNo == $transNo, "TransNo mismatch"); + my $exp = (($#packet+1)/31) & 0x7f; + next unless fassert($end or $exp == $frameNo, "FrameNo mismatch. Exp $exp, Got: $frameNo " ); + next unless fassert(($lastTransNo & ($end ? 0xfff : 0x1f)) == $transNo, "TransNo mismatch. Exp $lastTransNo, Got: $transNo"); @packet = (@packet, @frameData); } } - + # print join(" ", map{sprintf("%04x", $_)} @packet) . "\n"; if ($end and $#packet > 0) { my $expectLength = ($packet[0] << 16) | $packet[1]; + + pop @packet while ((2*$#packet+2) > $expectLength and $packet[-1] == 0xaaaa); next unless fassert($expectLength == 2*$#packet+2, "Length mismatch. Packet says $expectLength. Got " . (2*$#packet+2)); my $payloadLength = ($expectLength - 16 - 8); @@ -85,28 +95,36 @@ while(my $frame = ) { my $payloadWords = $payloadLength / 4; my $fail=0; for(my $i = 0; $i < $payloadWords and !$fail; $i++) { - $fail=1 unless fassert($packet[$i*2 + 8] == $packet[8], "TrbTransactionNo mismatch"); - my $exp = ($payloadWords - $i) & 0xfff; - my $got = $packet[$i*2 + 8 + 1] & 0xfff; - $fail=1 unless fassert($fail or $exp == $got, "Payload-RunNo mismatch. Exp: $exp, Got: $got"); + $fail=1 unless fassert($fail or $packet[$i*2 + 8] == $packet[8], "TrbTransactionNo mismatch"); + unless($fail) { + my $exp = ($payloadWords - $i) & 0xfff; + my $got = $packet[$i*2 + 8 + 1] & 0xfff; + $fail=1 unless fassert($fail or $exp == $got, "Payload-RunNo mismatch. Exp: $exp, Got: $got"); + } } - next unless fassert(($packet[8] & 0xff00) == 0xbb00, "Expected 0xbb-- as first word of payload"); - - if ($lastInnerTransNo != -1) { - my $exp = ($lastInnerTransNo + 1) & 0xff; - my $got = $packet[8] & 0xff; - # print "Error at $line: Inner TransNo mismatch. Exp: $exp, Got $got\n" unless ($exp == $got); + unless($fail) { + next unless fassert($fail or ($packet[8] & 0xff00) == 0xbb00, "Expected 0xbb-- as first word of payload"); + + if ($lastInnerTransNo != -1) { + my $exp = ($lastInnerTransNo + 1) & 0xff; + my $got = $packet[8] & 0xff; + # print "Error at $line: Inner TransNo mismatch. Exp: $exp, Got $got\n" unless ($exp == $got); + } + + $lastInnerTransNo = $packet[8] & 0xff; + + $fail=1 unless fassert($fail or $packet[-1] == 0xc0de, "Trailer mismatch"); + $fail=1 unless fassert($fail or $packet[-2] == 0xbeaf, "Trailer mismatch"); + $fail=1 unless fassert($fail or $packet[-3] == 0x5555, "Trailer mismatch"); + $fail=1 unless fassert($fail or $packet[-4] == 0x0001, "Trailer mismatch"); + + unless ($fail) { + $success++; + $matched += ceil(($#packet+1)/31); + } + } - - $lastInnerTransNo = $packet[8] & 0xff; - - $fail=1 unless fassert($fail or $packet[-1] == 0xc0de, "Trailer mismatch"); - $fail=1 unless fassert($fail or $packet[-2] == 0xbeaf, "Trailer mismatch"); - $fail=1 unless fassert($fail or $packet[-3] == 0x5555, "Trailer mismatch"); - $fail=1 unless fassert($fail or $packet[-4] == 0x0001, "Trailer mismatch"); - - $success++ unless $fail; #print "Sucessfully read packet with $expectLength bytes\n" unless $fail; @packet = (); }