From: Thomas Gessler Date: Fri, 4 Sep 2020 14:22:06 +0000 (+0200) Subject: hub_test: Add TRB parser X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=92f82c661957c7ef43653329398ed2a819face70;p=cri.git hub_test: Add TRB parser --- diff --git a/hub_test/constrs/debug.xdc b/hub_test/constrs/debug.xdc index 5eea18e..fe30e4d 100644 --- a/hub_test/constrs/debug.xdc +++ b/hub_test/constrs/debug.xdc @@ -32,6 +32,26 @@ create_debug_port u_ila_0 probe set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] set_property port_width 72 [get_debug_ports u_ila_0/probe5] connect_debug_port u_ila_0/probe5 [get_nets [list {hub_data_seqnmbr[0]} {hub_data_seqnmbr[1]} {hub_data_seqnmbr[2]} {hub_data_seqnmbr[3]} {hub_data_seqnmbr[4]} {hub_data_seqnmbr[5]} {hub_data_seqnmbr[6]} {hub_data_seqnmbr[7]} {hub_data_seqnmbr[8]} {hub_data_seqnmbr[9]} {hub_data_seqnmbr[10]} {hub_data_seqnmbr[11]} {hub_data_seqnmbr[12]} {hub_data_seqnmbr[13]} {hub_data_seqnmbr[14]} {hub_data_seqnmbr[15]} {hub_data_seqnmbr[16]} {hub_data_seqnmbr[17]} {hub_data_seqnmbr[18]} {hub_data_seqnmbr[19]} {hub_data_seqnmbr[20]} {hub_data_seqnmbr[21]} {hub_data_seqnmbr[22]} {hub_data_seqnmbr[23]} {hub_data_seqnmbr[24]} {hub_data_seqnmbr[25]} {hub_data_seqnmbr[26]} {hub_data_seqnmbr[27]} {hub_data_seqnmbr[28]} {hub_data_seqnmbr[29]} {hub_data_seqnmbr[30]} {hub_data_seqnmbr[31]} {hub_data_seqnmbr[32]} {hub_data_seqnmbr[33]} {hub_data_seqnmbr[34]} {hub_data_seqnmbr[35]} {hub_data_seqnmbr[36]} {hub_data_seqnmbr[37]} {hub_data_seqnmbr[38]} {hub_data_seqnmbr[39]} {hub_data_seqnmbr[40]} {hub_data_seqnmbr[41]} {hub_data_seqnmbr[42]} {hub_data_seqnmbr[43]} {hub_data_seqnmbr[44]} {hub_data_seqnmbr[45]} {hub_data_seqnmbr[46]} {hub_data_seqnmbr[47]} {hub_data_seqnmbr[48]} {hub_data_seqnmbr[49]} {hub_data_seqnmbr[50]} {hub_data_seqnmbr[51]} {hub_data_seqnmbr[52]} {hub_data_seqnmbr[53]} {hub_data_seqnmbr[54]} {hub_data_seqnmbr[55]} {hub_data_seqnmbr[56]} {hub_data_seqnmbr[57]} {hub_data_seqnmbr[58]} {hub_data_seqnmbr[59]} {hub_data_seqnmbr[60]} {hub_data_seqnmbr[61]} {hub_data_seqnmbr[62]} {hub_data_seqnmbr[63]} {hub_data_seqnmbr[64]} {hub_data_seqnmbr[65]} {hub_data_seqnmbr[66]} {hub_data_seqnmbr[67]} {hub_data_seqnmbr[68]} {hub_data_seqnmbr[69]} {hub_data_seqnmbr[70]} {hub_data_seqnmbr[71]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] +set_property port_width 288 [get_debug_ports u_ila_0/probe6] +connect_debug_port u_ila_0/probe6 [get_nets [list {trb_data_tdata[0]} {trb_data_tdata[1]} {trb_data_tdata[2]} {trb_data_tdata[3]} {trb_data_tdata[4]} {trb_data_tdata[5]} {trb_data_tdata[6]} {trb_data_tdata[7]} {trb_data_tdata[8]} {trb_data_tdata[9]} {trb_data_tdata[10]} {trb_data_tdata[11]} {trb_data_tdata[12]} {trb_data_tdata[13]} {trb_data_tdata[14]} {trb_data_tdata[15]} {trb_data_tdata[16]} {trb_data_tdata[17]} {trb_data_tdata[18]} {trb_data_tdata[19]} {trb_data_tdata[20]} {trb_data_tdata[21]} {trb_data_tdata[22]} {trb_data_tdata[23]} {trb_data_tdata[24]} {trb_data_tdata[25]} {trb_data_tdata[26]} {trb_data_tdata[27]} {trb_data_tdata[28]} {trb_data_tdata[29]} {trb_data_tdata[30]} {trb_data_tdata[31]} {trb_data_tdata[32]} {trb_data_tdata[33]} {trb_data_tdata[34]} {trb_data_tdata[35]} {trb_data_tdata[36]} {trb_data_tdata[37]} {trb_data_tdata[38]} {trb_data_tdata[39]} {trb_data_tdata[40]} {trb_data_tdata[41]} {trb_data_tdata[42]} {trb_data_tdata[43]} {trb_data_tdata[44]} {trb_data_tdata[45]} {trb_data_tdata[46]} {trb_data_tdata[47]} {trb_data_tdata[48]} {trb_data_tdata[49]} {trb_data_tdata[50]} {trb_data_tdata[51]} {trb_data_tdata[52]} {trb_data_tdata[53]} {trb_data_tdata[54]} {trb_data_tdata[55]} {trb_data_tdata[56]} {trb_data_tdata[57]} {trb_data_tdata[58]} {trb_data_tdata[59]} {trb_data_tdata[60]} {trb_data_tdata[61]} {trb_data_tdata[62]} {trb_data_tdata[63]} {trb_data_tdata[64]} {trb_data_tdata[65]} {trb_data_tdata[66]} {trb_data_tdata[67]} {trb_data_tdata[68]} {trb_data_tdata[69]} {trb_data_tdata[70]} {trb_data_tdata[71]} {trb_data_tdata[72]} {trb_data_tdata[73]} {trb_data_tdata[74]} {trb_data_tdata[75]} {trb_data_tdata[76]} {trb_data_tdata[77]} {trb_data_tdata[78]} {trb_data_tdata[79]} {trb_data_tdata[80]} {trb_data_tdata[81]} {trb_data_tdata[82]} {trb_data_tdata[83]} {trb_data_tdata[84]} {trb_data_tdata[85]} {trb_data_tdata[86]} {trb_data_tdata[87]} {trb_data_tdata[88]} {trb_data_tdata[89]} {trb_data_tdata[90]} {trb_data_tdata[91]} {trb_data_tdata[92]} {trb_data_tdata[93]} {trb_data_tdata[94]} {trb_data_tdata[95]} {trb_data_tdata[96]} {trb_data_tdata[97]} {trb_data_tdata[98]} {trb_data_tdata[99]} {trb_data_tdata[100]} {trb_data_tdata[101]} {trb_data_tdata[102]} {trb_data_tdata[103]} {trb_data_tdata[104]} {trb_data_tdata[105]} {trb_data_tdata[106]} {trb_data_tdata[107]} {trb_data_tdata[108]} {trb_data_tdata[109]} {trb_data_tdata[110]} {trb_data_tdata[111]} {trb_data_tdata[112]} {trb_data_tdata[113]} {trb_data_tdata[114]} {trb_data_tdata[115]} {trb_data_tdata[116]} {trb_data_tdata[117]} {trb_data_tdata[118]} {trb_data_tdata[119]} {trb_data_tdata[120]} {trb_data_tdata[121]} {trb_data_tdata[122]} {trb_data_tdata[123]} {trb_data_tdata[124]} {trb_data_tdata[125]} {trb_data_tdata[126]} {trb_data_tdata[127]} {trb_data_tdata[128]} {trb_data_tdata[129]} {trb_data_tdata[130]} {trb_data_tdata[131]} {trb_data_tdata[132]} {trb_data_tdata[133]} {trb_data_tdata[134]} {trb_data_tdata[135]} {trb_data_tdata[136]} {trb_data_tdata[137]} {trb_data_tdata[138]} {trb_data_tdata[139]} {trb_data_tdata[140]} {trb_data_tdata[141]} {trb_data_tdata[142]} {trb_data_tdata[143]} {trb_data_tdata[144]} {trb_data_tdata[145]} {trb_data_tdata[146]} {trb_data_tdata[147]} {trb_data_tdata[148]} {trb_data_tdata[149]} {trb_data_tdata[150]} {trb_data_tdata[151]} {trb_data_tdata[152]} {trb_data_tdata[153]} {trb_data_tdata[154]} {trb_data_tdata[155]} {trb_data_tdata[156]} {trb_data_tdata[157]} {trb_data_tdata[158]} {trb_data_tdata[159]} {trb_data_tdata[160]} {trb_data_tdata[161]} {trb_data_tdata[162]} {trb_data_tdata[163]} {trb_data_tdata[164]} {trb_data_tdata[165]} {trb_data_tdata[166]} {trb_data_tdata[167]} {trb_data_tdata[168]} {trb_data_tdata[169]} {trb_data_tdata[170]} {trb_data_tdata[171]} {trb_data_tdata[172]} {trb_data_tdata[173]} {trb_data_tdata[174]} {trb_data_tdata[175]} {trb_data_tdata[176]} {trb_data_tdata[177]} {trb_data_tdata[178]} {trb_data_tdata[179]} {trb_data_tdata[180]} {trb_data_tdata[181]} {trb_data_tdata[182]} {trb_data_tdata[183]} {trb_data_tdata[184]} {trb_data_tdata[185]} {trb_data_tdata[186]} {trb_data_tdata[187]} {trb_data_tdata[188]} {trb_data_tdata[189]} {trb_data_tdata[190]} {trb_data_tdata[191]} {trb_data_tdata[192]} {trb_data_tdata[193]} {trb_data_tdata[194]} {trb_data_tdata[195]} {trb_data_tdata[196]} {trb_data_tdata[197]} {trb_data_tdata[198]} {trb_data_tdata[199]} {trb_data_tdata[200]} {trb_data_tdata[201]} {trb_data_tdata[202]} {trb_data_tdata[203]} {trb_data_tdata[204]} {trb_data_tdata[205]} {trb_data_tdata[206]} {trb_data_tdata[207]} {trb_data_tdata[208]} {trb_data_tdata[209]} {trb_data_tdata[210]} {trb_data_tdata[211]} {trb_data_tdata[212]} {trb_data_tdata[213]} {trb_data_tdata[214]} {trb_data_tdata[215]} {trb_data_tdata[216]} {trb_data_tdata[217]} {trb_data_tdata[218]} {trb_data_tdata[219]} {trb_data_tdata[220]} {trb_data_tdata[221]} {trb_data_tdata[222]} {trb_data_tdata[223]} {trb_data_tdata[224]} {trb_data_tdata[225]} {trb_data_tdata[226]} {trb_data_tdata[227]} {trb_data_tdata[228]} {trb_data_tdata[229]} {trb_data_tdata[230]} {trb_data_tdata[231]} {trb_data_tdata[232]} {trb_data_tdata[233]} {trb_data_tdata[234]} {trb_data_tdata[235]} {trb_data_tdata[236]} {trb_data_tdata[237]} {trb_data_tdata[238]} {trb_data_tdata[239]} {trb_data_tdata[240]} {trb_data_tdata[241]} {trb_data_tdata[242]} {trb_data_tdata[243]} {trb_data_tdata[244]} {trb_data_tdata[245]} {trb_data_tdata[246]} {trb_data_tdata[247]} {trb_data_tdata[248]} {trb_data_tdata[249]} {trb_data_tdata[250]} {trb_data_tdata[251]} {trb_data_tdata[252]} {trb_data_tdata[253]} {trb_data_tdata[254]} {trb_data_tdata[255]} {trb_data_tdata[256]} {trb_data_tdata[257]} {trb_data_tdata[258]} {trb_data_tdata[259]} {trb_data_tdata[260]} {trb_data_tdata[261]} {trb_data_tdata[262]} {trb_data_tdata[263]} {trb_data_tdata[264]} {trb_data_tdata[265]} {trb_data_tdata[266]} {trb_data_tdata[267]} {trb_data_tdata[268]} {trb_data_tdata[269]} {trb_data_tdata[270]} {trb_data_tdata[271]} {trb_data_tdata[272]} {trb_data_tdata[273]} {trb_data_tdata[274]} {trb_data_tdata[275]} {trb_data_tdata[276]} {trb_data_tdata[277]} {trb_data_tdata[278]} {trb_data_tdata[279]} {trb_data_tdata[280]} {trb_data_tdata[281]} {trb_data_tdata[282]} {trb_data_tdata[283]} {trb_data_tdata[284]} {trb_data_tdata[285]} {trb_data_tdata[286]} {trb_data_tdata[287]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] +set_property port_width 36 [get_debug_ports u_ila_0/probe7] +connect_debug_port u_ila_0/probe7 [get_nets [list {trb_data_tkeep[0]} {trb_data_tkeep[1]} {trb_data_tkeep[2]} {trb_data_tkeep[3]} {trb_data_tkeep[4]} {trb_data_tkeep[5]} {trb_data_tkeep[6]} {trb_data_tkeep[7]} {trb_data_tkeep[8]} {trb_data_tkeep[9]} {trb_data_tkeep[10]} {trb_data_tkeep[11]} {trb_data_tkeep[12]} {trb_data_tkeep[13]} {trb_data_tkeep[14]} {trb_data_tkeep[15]} {trb_data_tkeep[16]} {trb_data_tkeep[17]} {trb_data_tkeep[18]} {trb_data_tkeep[19]} {trb_data_tkeep[20]} {trb_data_tkeep[21]} {trb_data_tkeep[22]} {trb_data_tkeep[23]} {trb_data_tkeep[24]} {trb_data_tkeep[25]} {trb_data_tkeep[26]} {trb_data_tkeep[27]} {trb_data_tkeep[28]} {trb_data_tkeep[29]} {trb_data_tkeep[30]} {trb_data_tkeep[31]} {trb_data_tkeep[32]} {trb_data_tkeep[33]} {trb_data_tkeep[34]} {trb_data_tkeep[35]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] +set_property port_width 9 [get_debug_ports u_ila_0/probe8] +connect_debug_port u_ila_0/probe8 [get_nets [list {trb_data_tlast[0]} {trb_data_tlast[1]} {trb_data_tlast[2]} {trb_data_tlast[3]} {trb_data_tlast[4]} {trb_data_tlast[5]} {trb_data_tlast[6]} {trb_data_tlast[7]} {trb_data_tlast[8]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] +set_property port_width 9 [get_debug_ports u_ila_0/probe9] +connect_debug_port u_ila_0/probe9 [get_nets [list {trb_data_tready[0]} {trb_data_tready[1]} {trb_data_tready[2]} {trb_data_tready[3]} {trb_data_tready[4]} {trb_data_tready[5]} {trb_data_tready[6]} {trb_data_tready[7]} {trb_data_tready[8]}]] +create_debug_port u_ila_0 probe +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] +set_property port_width 9 [get_debug_ports u_ila_0/probe10] +connect_debug_port u_ila_0/probe10 [get_nets [list {trb_data_tvalid[0]} {trb_data_tvalid[1]} {trb_data_tvalid[2]} {trb_data_tvalid[3]} {trb_data_tvalid[4]} {trb_data_tvalid[5]} {trb_data_tvalid[6]} {trb_data_tvalid[7]} {trb_data_tvalid[8]}]] set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub] set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub] set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub] diff --git a/hub_test/hub_test.xpr b/hub_test/hub_test.xpr index 01bb521..a219765 100644 --- a/hub_test/hub_test.xpr +++ b/hub_test/hub_test.xpr @@ -271,6 +271,12 @@ + + + + + + diff --git a/hub_test/src/hub_test.vhd b/hub_test/src/hub_test.vhd index 48c12ea..2b4f355 100644 --- a/hub_test/src/hub_test.vhd +++ b/hub_test/src/hub_test.vhd @@ -146,6 +146,12 @@ architecture behavioral of hub_test is signal hub_data_seqnmbr : std_logic_vector(((INTERFACE_NUM - 1) * 8) - 1 downto 0); signal hub_data_length : std_logic_vector(((INTERFACE_NUM - 1) * c_DATA_WIDTH) - 1 downto 0); + signal trb_data_tvalid : std_logic_vector(INTERFACE_NUM - 2 downto 0); + signal trb_data_tready : std_logic_vector(INTERFACE_NUM - 2 downto 0) := (others => '1'); + signal trb_data_tdata : std_logic_vector((INTERFACE_NUM - 1) * 32 - 1 downto 0); + signal trb_data_tkeep : std_logic_vector((INTERFACE_NUM - 1) * 4 - 1 downto 0); + signal trb_data_tlast : std_logic_vector(INTERFACE_NUM - 2 downto 0); + attribute MARK_DEBUG : string; attribute KEEP : string; @@ -155,6 +161,11 @@ architecture behavioral of hub_test is attribute MARK_DEBUG of hub_data_address_sender : signal is "true"; attribute MARK_DEBUG of hub_data_seqnmbr : signal is "true"; attribute MARK_DEBUG of hub_data_length : signal is "true"; + attribute MARK_DEBUG of trb_data_tvalid : signal is "true"; + attribute MARK_DEBUG of trb_data_tready : signal is "true"; + attribute MARK_DEBUG of trb_data_tdata : signal is "true"; + attribute MARK_DEBUG of trb_data_tkeep : signal is "true"; + attribute MARK_DEBUG of trb_data_tlast : signal is "true"; attribute KEEP of hub_data_active : signal is "true"; attribute KEEP of hub_data_out : signal is "true"; @@ -162,6 +173,11 @@ architecture behavioral of hub_test is attribute KEEP of hub_data_address_sender : signal is "true"; attribute KEEP of hub_data_seqnmbr : signal is "true"; attribute KEEP of hub_data_length : signal is "true"; + attribute KEEP of trb_data_tvalid : signal is "true"; + attribute KEEP of trb_data_tready : signal is "true"; + attribute KEEP of trb_data_tdata : signal is "true"; + attribute KEEP of trb_data_tkeep : signal is "true"; + attribute KEEP of trb_data_tlast : signal is "true"; signal usrclk : std_logic; @@ -470,6 +486,28 @@ begin ); + generate_parsers: + for i in 0 to INTERFACE_NUM - 2 generate + begin + trb_parser_i : entity work.trb_parser + port map ( + CLK => sysclk_100, + RESET => reset, + DATA_ACTIVE => hub_data_active(i), + DATA_OUT => hub_data_out(32 * i + 31 downto 32 * i), + DATA_READY => hub_data_ready(i), + DATA_ADDRESS_SENDER => hub_data_address_sender(16 * i + 15 downto 16 * i), + DATA_SEQNMBR => hub_data_seqnmbr(8 * i + 7 downto 8 * i), + DATA_LENGTH => hub_data_length(16 * i + 15 downto 16 * i), + M_AXIS_TVALID => trb_data_tvalid(i), + M_AXIS_TREADY => trb_data_tready(i), + M_AXIS_TDATA => trb_data_tdata(32 * i + 31 downto 32 * i), + M_AXIS_TKEEP => trb_data_tkeep(4 * i + 3 downto 4 * i), + M_AXIS_TLAST => trb_data_tlast(i) + ); + end generate generate_parsers; + + gen_media_record : for i in 0 to INTERFACE_NUM - 1 generate begin med_data_in(i * 16 + 15 downto i * 16) <= med2int_i(i).data; diff --git a/hub_test/src/trb_parser.vhd b/hub_test/src/trb_parser.vhd new file mode 100644 index 0000000..8289557 --- /dev/null +++ b/hub_test/src/trb_parser.vhd @@ -0,0 +1,580 @@ +------------------------------------------------------------------------------- +--! @file +--! @brief TRB-data parser +--! +--! Receives TRB data from a hub data interface (DATA_* ports) and parses the +--! content. Outputs only valid TRB data to a 4-byte AXI-Stream interface. +--! Discards the complete input packet in case of any format error or buffer +--! overflow. +--! +--! Prepends a 32-bit word to every output packet: +--! +--! [31:24]: reserved +--! [23:0]: MBS trigger-number +--! +--! Assumptions about DATA_* ports: +--! - DATA_ACTIVE goes high for a new input packet and remains high until the +--! packet is finished. +--! - DATA_ACTIVE goes low for at least one clock cycle between packets. +--! - DATA_READY signifies that the word on DATA_OUT is valid. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library xpm; +use xpm.vcomponents.all; + +entity trb_parser is + port ( + CLK : in std_logic; + RESET : in std_logic; + + DATA_ACTIVE : in std_logic; + DATA_OUT : in std_logic_vector(31 downto 0); + DATA_READY : in std_logic; + DATA_ADDRESS_SENDER : in std_logic_vector(15 downto 0); + DATA_SEQNMBR : in std_logic_vector(7 downto 0); + DATA_LENGTH : in std_logic_vector(15 downto 0); + + M_AXIS_TVALID : out std_logic; + M_AXIS_TREADY : in std_logic; + M_AXIS_TDATA : out std_logic_vector(31 downto 0); + M_AXIS_TKEEP : out std_logic_vector(3 downto 0); + M_AXIS_TLAST : out std_logic + ); +end entity trb_parser; + +architecture behavioral of trb_parser is + type in_state is ( + in_reset, + discard_input_packet, + trg_type_inactive, + trg_type, + combiner_header, + subsub_header, + dirich_data, + cts_data, + trailer_0, + trailer_1, + aaaa_or_end_of_packet, + end_of_packet, + terminate_input + ); + + type out_state is ( + out_reset, + check_meta_fifo, + output_mbs_trg_num, + output_forward, + output_discard + ); + + signal in_state_cur : in_state := in_reset; + signal in_state_next : in_state; + + signal out_state_cur : out_state := out_reset; + signal out_state_next : out_state; + + type ERR_CODE is ( + ERR_INIT_DATA_LOST, -- 0 + ERR_READY_NOT_ACTIVE, -- 1 + ERR_META_FIFO_FULL, -- 2 + ERR_DATA_FIFO_FULL, -- 3 + ERR_UNEXPECTED_EOP, -- 4 + ERR_DATA_FIFO_AFULL, -- 5 + ERR_COMBINER_SIZE, -- 6 + ERR_TRAILER, -- 7 + ERR_META_FIFO_FATAL, -- 8 + ERR_DATA_FIFO_FATAL, -- 9 + ERR_PADDING, -- A + ERR_TRAILING_DATA -- B + ); + + signal err_mask : std_logic_vector(ERR_CODE'pos(ERR_CODE'high) downto 0); + + signal data_fifo_almost_full : std_logic; + signal data_fifo_dout : std_logic_vector(32 downto 0); + signal data_fifo_empty : std_logic; + signal data_fifo_full : std_logic; + signal data_fifo_rd_rst_busy : std_logic; + signal data_fifo_wr_rst_busy : std_logic; + signal data_fifo_din : std_logic_vector(32 downto 0); + signal data_fifo_rd_en : std_logic; + signal data_fifo_wr_en : std_logic; + + signal meta_fifo_dout : std_logic_vector(24 downto 0); + signal meta_fifo_empty : std_logic; + signal meta_fifo_full : std_logic; + signal meta_fifo_rd_rst_busy : std_logic; + signal meta_fifo_wr_rst_busy : std_logic; + signal meta_fifo_din : std_logic_vector(24 downto 0); + signal meta_fifo_rd_en : std_logic; + signal meta_fifo_wr_en : std_logic; + + signal comb_rem_words : unsigned(15 downto 0) := x"0000"; + signal comb_rem_words_next : unsigned(15 downto 0); + signal subsub_rem_words : unsigned(15 downto 0) := x"0000"; + signal subsub_rem_words_next : unsigned(15 downto 0); + signal mbs_trg_num : std_logic_vector(23 downto 0) := x"000000"; + signal mbs_trg_num_next : std_logic_vector(23 downto 0); + signal comb_addr : std_logic_vector(15 downto 0) := x"0000"; + signal comb_addr_next : std_logic_vector(15 downto 0); + + signal fifo_resets_busy : std_logic; +begin + data_fifo : xpm_fifo_sync + generic map ( + DOUT_RESET_VALUE => "0", + ECC_MODE => "no_ecc", + FIFO_MEMORY_TYPE => "auto", + FIFO_READ_LATENCY => 0, + FIFO_WRITE_DEPTH => 16384, -- 16 to 4194304 (power of 2) + FULL_RESET_VALUE => 0, + PROG_EMPTY_THRESH => 10, + PROG_FULL_THRESH => 10, + RD_DATA_COUNT_WIDTH => 1, + READ_DATA_WIDTH => 33, + READ_MODE => "fwft", + SIM_ASSERT_CHK => 0, + USE_ADV_FEATURES => "0008", -- almost_full + WAKEUP_TIME => 0, + WRITE_DATA_WIDTH => 33, + WR_DATA_COUNT_WIDTH => 1 + ) + port map ( + almost_empty => open, + almost_full => data_fifo_almost_full, + data_valid => open, + dbiterr => open, + dout => data_fifo_dout, + empty => data_fifo_empty, + full => data_fifo_full, + overflow => open, + prog_empty => open, + prog_full => open, + rd_data_count => open, + rd_rst_busy => data_fifo_rd_rst_busy, + sbiterr => open, + underflow => open, + wr_ack => open, + wr_data_count => open, + wr_rst_busy => data_fifo_wr_rst_busy, + din => data_fifo_din, + injectdbiterr => '0', + injectsbiterr => '0', + rd_en => data_fifo_rd_en, + rst => RESET, + sleep => '0', + wr_clk => CLK, + wr_en => data_fifo_wr_en + ); + + meta_fifo : xpm_fifo_sync + generic map ( + DOUT_RESET_VALUE => "0", + ECC_MODE => "no_ecc", + FIFO_MEMORY_TYPE => "auto", + FIFO_READ_LATENCY => 0, + FIFO_WRITE_DEPTH => 16, -- 16 to 4194304 (power of 2) + FULL_RESET_VALUE => 0, + PROG_EMPTY_THRESH => 10, + PROG_FULL_THRESH => 10, + RD_DATA_COUNT_WIDTH => 1, + READ_DATA_WIDTH => 25, + READ_MODE => "fwft", + SIM_ASSERT_CHK => 0, + USE_ADV_FEATURES => "0000", + WAKEUP_TIME => 0, + WRITE_DATA_WIDTH => 25, + WR_DATA_COUNT_WIDTH => 1 + ) + port map ( + almost_empty => open, + almost_full => open, + data_valid => open, + dbiterr => open, + dout => meta_fifo_dout, + empty => meta_fifo_empty, + full => meta_fifo_full, + overflow => open, + prog_empty => open, + prog_full => open, + rd_data_count => open, + rd_rst_busy => meta_fifo_rd_rst_busy, + sbiterr => open, + underflow => open, + wr_ack => open, + wr_data_count => open, + wr_rst_busy => meta_fifo_wr_rst_busy, + din => meta_fifo_din, + injectdbiterr => '0', + injectsbiterr => '0', + rd_en => meta_fifo_rd_en, + rst => RESET, + sleep => '0', + wr_clk => CLK, + wr_en => meta_fifo_wr_en + ); + + fifo_resets_busy <= data_fifo_rd_rst_busy or data_fifo_wr_rst_busy + or meta_fifo_rd_rst_busy or meta_fifo_wr_rst_busy; + + in_sm_sync: + process (CLK) is + begin + if rising_edge(CLK) then + if RESET = '1' then + in_state_cur <= in_reset; + comb_rem_words <= x"0000"; + subsub_rem_words <= x"0000"; + mbs_trg_num <= x"000000"; + comb_addr <= x"0000"; + else + in_state_cur <= in_state_next; + comb_rem_words <= comb_rem_words_next; + subsub_rem_words <= subsub_rem_words_next; + mbs_trg_num <= mbs_trg_num_next; + comb_addr <= comb_addr_next; + end if; + end if; + end process in_sm_sync; + + in_sm_comb: + process ( + in_state_cur, + comb_rem_words, + subsub_rem_words, + mbs_trg_num, + comb_addr, + DATA_ACTIVE, + DATA_OUT, + DATA_READY, + fifo_resets_busy, + meta_fifo_full, + data_fifo_full, + data_fifo_almost_full + ) is + begin + in_state_next <= in_state_cur; + + comb_rem_words_next <= comb_rem_words; + subsub_rem_words_next <= subsub_rem_words; + mbs_trg_num_next <= mbs_trg_num; + comb_addr_next <= comb_addr; + + err_mask <= (others => '0'); + err_mask(ERR_CODE'pos(ERR_READY_NOT_ACTIVE)) <= DATA_READY + and not DATA_ACTIVE; + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_FATAL)) <= data_fifo_full + and data_fifo_wr_en; + err_mask(ERR_CODE'pos(ERR_META_FIFO_FATAL)) <= meta_fifo_full + and meta_fifo_wr_en; + + data_fifo_din(31 downto 0) <= DATA_OUT; + data_fifo_din(32) <= '0'; + data_fifo_wr_en <= '0'; + + meta_fifo_din(23 downto 0) <= mbs_trg_num; + meta_fifo_din(24) <= '0'; + meta_fifo_wr_en <= '0'; + + case in_state_cur is + when in_reset => + if fifo_resets_busy = '0' then + in_state_next <= discard_input_packet; + if DATA_ACTIVE = '0' then + in_state_next <= trg_type_inactive; + else + err_mask(ERR_CODE'pos(ERR_INIT_DATA_LOST)) <= '1'; + in_state_next <= discard_input_packet; + end if; + end if; + when discard_input_packet => + if DATA_ACTIVE = '0' then + in_state_next <= trg_type_inactive; + end if; + when trg_type_inactive => + if DATA_ACTIVE = '1' then + if meta_fifo_full = '1' then + err_mask(ERR_CODE'pos(ERR_META_FIFO_FULL)) <= '1'; + end if; + if data_fifo_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_FULL)) <= '1'; + end if; + if meta_fifo_full = '1' or data_fifo_full = '1' then + -- Before accepting a new packet, we ensure that at least + -- one word can be written to both FIFOs. This condition is + -- kept up until the packet ends and the last data word and + -- meta word are written. + in_state_next <= discard_input_packet; + elsif DATA_READY = '1' then + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + in_state_next <= combiner_header; + end if; + else + in_state_next <= trg_type; + end if; + end if; + when trg_type => + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + in_state_next <= combiner_header; + end if; + end if; + when combiner_header => + comb_rem_words_next <= unsigned(DATA_OUT(31 downto 16)); + comb_addr_next <= DATA_OUT(15 downto 0); + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + in_state_next <= subsub_header; + end if; + end if; + when subsub_header => + subsub_rem_words_next <= unsigned(DATA_OUT(31 downto 16)); + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + comb_rem_words_next <= comb_rem_words - 1; + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + if DATA_OUT(15 downto 0) = comb_addr then + in_state_next <= cts_data; + else + in_state_next <= dirich_data; + end if; + end if; + end if; + when dirich_data => + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + comb_rem_words_next <= comb_rem_words - 1; + subsub_rem_words_next <= subsub_rem_words - 1; + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + if subsub_rem_words = 1 then + in_state_next <= subsub_header; + end if; + end if; + end if; + when cts_data => + mbs_trg_num_next <= DATA_OUT(23 downto 0); + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + comb_rem_words_next <= comb_rem_words - 1; + subsub_rem_words_next <= subsub_rem_words - 1; + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + if subsub_rem_words = 1 then + if comb_rem_words = 1 then + in_state_next <= trailer_0; + else + err_mask(ERR_CODE'pos(ERR_COMBINER_SIZE)) <= '1'; + in_state_next <= terminate_input; + end if; + end if; + end if; + end if; + when trailer_0 => + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + if DATA_OUT = x"00015555" then + in_state_next <= trailer_1; + else + err_mask(ERR_CODE'pos(ERR_TRAILER)) <= '1'; + in_state_next <= terminate_input; + end if; + end if; + end if; + when trailer_1 => + if DATA_ACTIVE = '0' then + err_mask(ERR_CODE'pos(ERR_UNEXPECTED_EOP)) <= '1'; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + in_state_next <= trg_type_inactive; + elsif DATA_READY = '1' then + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + in_state_next <= aaaa_or_end_of_packet; + end if; + end if; + when aaaa_or_end_of_packet => + if DATA_ACTIVE = '0' then + in_state_next <= trg_type_inactive; + data_fifo_din(31 downto 0) <= x"600D_DA7A"; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_din(24) <= '1'; + meta_fifo_wr_en <= '1'; + elsif DATA_READY = '1' then + if data_fifo_almost_full = '1' then + err_mask(ERR_CODE'pos(ERR_DATA_FIFO_AFULL)) <= '1'; + in_state_next <= terminate_input; + else + data_fifo_wr_en <= '1'; + if DATA_OUT = x"AAAAAAAA" then + in_state_next <= end_of_packet; + else + err_mask(ERR_CODE'pos(ERR_PADDING)) <= '1'; + in_state_next <= terminate_input; + end if; + end if; + end if; + when end_of_packet => + if DATA_ACTIVE = '0' then + in_state_next <= trg_type_inactive; + data_fifo_din(31 downto 0) <= x"600D_DA7A"; + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_din(24) <= '1'; + meta_fifo_wr_en <= '1'; + elsif DATA_READY = '1' then + err_mask(ERR_CODE'pos(ERR_TRAILING_DATA)) <= '1'; + in_state_next <= terminate_input; + end if; + when terminate_input => + data_fifo_din(32) <= '1'; + data_fifo_wr_en <= '1'; + meta_fifo_wr_en <= '1'; + if DATA_ACTIVE = '1' then + in_state_next <= discard_input_packet; + else + in_state_next <= trg_type_inactive; + end if; + end case; + end process in_sm_comb; + + + out_sm_sync: + process (CLK) is + begin + if rising_edge(CLK) then + if RESET = '1' then + out_state_cur <= out_reset; + else + out_state_cur <= out_state_next; + end if; + end if; + end process out_sm_sync; + + out_sm_comb: + process ( + out_state_cur, + fifo_resets_busy, + meta_fifo_empty, + meta_fifo_dout, + data_fifo_empty, + data_fifo_dout, + M_AXIS_TREADY + ) is + begin + out_state_next <= out_state_cur; + + M_AXIS_TVALID <= '0'; + M_AXIS_TLAST <= data_fifo_dout(32); + M_AXIS_TDATA <= data_fifo_dout(31 downto 0); + M_AXIS_TKEEP <= "1111"; + + meta_fifo_rd_en <= '0'; + data_fifo_rd_en <= '0'; + + case out_state_cur is + when out_reset => + if fifo_resets_busy = '0' then + out_state_next <= check_meta_fifo; + end if; + when check_meta_fifo => + if meta_fifo_empty = '0' then + if meta_fifo_dout(24) = '1' then + out_state_next <= output_mbs_trg_num; + else + meta_fifo_rd_en <= '1'; + out_state_next <= output_discard; + end if; + end if; + when output_mbs_trg_num => + M_AXIS_TVALID <= '1'; + M_AXIS_TLAST <= '0'; + M_AXIS_TDATA(31 downto 24) <= x"00"; + M_AXIS_TDATA(23 downto 0) <= meta_fifo_dout(23 downto 0); + if M_AXIS_TREADY = '1' then + meta_fifo_rd_en <= '1'; + out_state_next <= output_forward; + end if; + when output_forward => + M_AXIS_TVALID <= not data_fifo_empty; + data_fifo_rd_en <= M_AXIS_TREADY; + if M_AXIS_TREADY = '1' and data_fifo_empty = '0' + and data_fifo_dout(32) = '1' + then + out_state_next <= check_meta_fifo; + end if; + when output_discard => + data_fifo_rd_en <= '1'; + if data_fifo_empty = '0' and data_fifo_dout(32) = '1' then + out_state_next <= check_meta_fifo; + end if; + end case; + end process out_sm_comb; +end architecture behavioral;