diff options
author | Wade Fife <wade.fife@ettus.com> | 2020-04-12 17:13:22 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-08-04 15:40:08 -0500 |
commit | b862eda69cf41c7044a1805324f2fcfef5b0ba3d (patch) | |
tree | 7ad6cb34cc9b3925d37a75d9b7416057d8e11497 /fpga | |
parent | da3af4e6e86809038872a61696f3d1bac2e8583c (diff) | |
download | uhd-b862eda69cf41c7044a1805324f2fcfef5b0ba3d.tar.gz uhd-b862eda69cf41c7044a1805324f2fcfef5b0ba3d.tar.bz2 uhd-b862eda69cf41c7044a1805324f2fcfef5b0ba3d.zip |
fpga: rfnoc: Add support for CHDR_W < ITEM_W*NIPC
This change fixes the case where CHDR_W < ITEM_W*NIPC.
It also adds a state machine to stall the input to the pyld_fifo to
ensure that the pkt_info_fifo will not overflow. Previously in some
cases it allowed the same word to be inserted into the pyld_fifo
multiple times.
Diffstat (limited to 'fpga')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v | 222 | ||||
-rw-r--r-- | fpga/usrp3/lib/rfnoc/core/chdr_to_axis_data.v | 110 |
2 files changed, 195 insertions, 137 deletions
diff --git a/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v b/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v index 2ff5a1ee7..50a4b7615 100644 --- a/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v +++ b/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v @@ -218,9 +218,13 @@ module axis_data_to_chdr #( endgenerate - //--------------------------------------------------------------------------- - // Data Width Converter (ITEM_W*NIPC => CHDR_W) + // Data Width Conversion and Input FIFOs + //--------------------------------------------------------------------------- + // + // Convert the data width and cross the data into the CHDR clock domain, as + // needed. Buffer the data and packet info. + // //--------------------------------------------------------------------------- wire [CHDR_W-1:0] in_pyld_tdata; @@ -229,15 +233,63 @@ module axis_data_to_chdr #( wire in_pyld_tready; wire width_conv_tready; - assign width_conv_tready = in_pyld_tready & in_pkt_info_tready; + wire [CHDR_W-1:0] out_pyld_tdata; + wire out_pyld_tlast; + wire out_pyld_tvalid; + reg out_pyld_tready; + + wire out_pkt_info_tvalid; + reg out_pkt_info_tready; + wire out_eob, out_eov, out_has_time; + wire [63:0] out_timestamp; + wire [15:0] out_length; + + reg gating = 0; generate + if (SYNC_CLKS) begin : gen_sync_info_fifo + axi_fifo #( + .WIDTH (3 + 64 + 16), + .SIZE (INFO_FIFO_SIZE) + ) pkt_info_fifo ( + .clk (axis_chdr_clk), + .reset (axis_chdr_rst), + .clear (1'b0), + .i_tdata ({packet_eob, packet_eov, packet_has_time, packet_timestamp, packet_length}), + .i_tvalid (in_pkt_info_tvalid), + .i_tready (in_pkt_info_tready), + .o_tdata ({out_eob, out_eov, out_has_time, out_timestamp, out_length}), + .o_tvalid (out_pkt_info_tvalid), + .o_tready (out_pkt_info_tready), + .space (), + .occupied () + ); + end else begin : gen_async_info_fifo + axi_fifo_2clk #( + .WIDTH (3 + 64 + 16), + .SIZE (INFO_FIFO_SIZE) + ) pkt_info_fifo ( + .reset (axis_data_rst), + .i_aclk (axis_data_clk), + .i_tdata ({packet_eob, packet_eov, packet_has_time, packet_timestamp, packet_length}), + .i_tvalid (in_pkt_info_tvalid), + .i_tready (in_pkt_info_tready), + .o_aclk (axis_chdr_clk), + .o_tdata ({out_eob, out_eov, out_has_time, out_timestamp, out_length}), + .o_tvalid (out_pkt_info_tvalid), + .o_tready (out_pkt_info_tready) + ); + end + if (NIPC != CHDR_W/ITEM_W) begin : gen_axis_width_conv + // Do the width conversion and clock crossing in the axis_width_conv + // module to ensure that the resize happens on the correct side of the + // clock crossing. axis_width_conv #( .WORD_W (ITEM_W), .IN_WORDS (NIPC), .OUT_WORDS (CHDR_W/ITEM_W), - .SYNC_CLKS (1), + .SYNC_CLKS (SYNC_CLKS), .PIPELINE ("IN") ) payload_width_conv_i ( .s_axis_aclk (axis_data_clk), @@ -247,108 +299,98 @@ module axis_data_to_chdr #( .s_axis_tlast (s_axis_tlast), .s_axis_tvalid (s_axis_tvalid), .s_axis_tready (s_axis_tready), - .m_axis_aclk (axis_data_clk), - .m_axis_rst (axis_data_rst), + .m_axis_aclk (axis_chdr_clk), + .m_axis_rst (axis_chdr_rst), .m_axis_tdata (in_pyld_tdata), .m_axis_tkeep (), .m_axis_tlast (in_pyld_tlast), .m_axis_tvalid (in_pyld_tvalid), - .m_axis_tready (width_conv_tready) + .m_axis_tready (in_pyld_tready & ~gating) + ); + + axi_fifo #( + .WIDTH (CHDR_W+1), + .SIZE (PAYLOAD_FIFO_SIZE) + ) pyld_fifo ( + .clk (axis_chdr_clk), + .reset (axis_chdr_rst), + .clear (1'b0), + .i_tdata ({in_pyld_tlast, in_pyld_tdata}), + .i_tvalid (in_pyld_tvalid & ~gating), + .i_tready (in_pyld_tready), + .o_tdata ({out_pyld_tlast, out_pyld_tdata}), + .o_tvalid (out_pyld_tvalid), + .o_tready (out_pyld_tready), + .space (), + .occupied () ); end else begin : no_gen_axis_width_conv + // No width conversion needed assign in_pyld_tdata = s_axis_tdata; assign in_pyld_tlast = s_axis_tlast; assign in_pyld_tvalid = s_axis_tvalid; - assign s_axis_tready = width_conv_tready; + assign s_axis_tready = in_pyld_tready & ~gating; + + if (SYNC_CLKS) begin : gen_sync_pyld_fifo + axi_fifo #( + .WIDTH (CHDR_W+1), + .SIZE (PAYLOAD_FIFO_SIZE) + ) pyld_fifo ( + .clk (axis_chdr_clk), + .reset (axis_chdr_rst), + .clear (1'b0), + .i_tdata ({in_pyld_tlast, in_pyld_tdata}), + .i_tvalid (in_pyld_tvalid & ~gating), + .i_tready (in_pyld_tready), + .o_tdata ({out_pyld_tlast, out_pyld_tdata}), + .o_tvalid (out_pyld_tvalid), + .o_tready (out_pyld_tready), + .space (), + .occupied () + ); + end else begin : gen_async_pyld_fifo + axi_fifo_2clk #( + .WIDTH (CHDR_W + 1), + .SIZE (PAYLOAD_FIFO_SIZE) + ) pyld_fifo ( + .reset (axis_data_rst), + .i_aclk (axis_data_clk), + .i_tdata ({in_pyld_tlast, in_pyld_tdata}), + .i_tvalid (in_pyld_tvalid & ~gating), + .i_tready (in_pyld_tready), + .o_aclk (axis_chdr_clk), + .o_tdata ({out_pyld_tlast, out_pyld_tdata}), + .o_tvalid (out_pyld_tvalid), + .o_tready (out_pyld_tready) + ); + end end endgenerate - //--------------------------------------------------------------------------- - // Input FIFOs - //--------------------------------------------------------------------------- - // - // Buffer the data, packet info, metadata, and cross it into the CHDR clock - // domain, if needed. The payload FIFO is sized to match the MTU so that an - // entire packet can be buffered while the length is calculated. - // - //--------------------------------------------------------------------------- - wire [CHDR_W-1:0] out_pyld_tdata; - wire out_pyld_tlast; - wire out_pyld_tvalid; - reg out_pyld_tready; - wire out_pkt_info_tvalid; - reg out_pkt_info_tready; - wire out_eob, out_eov, out_has_time; - wire [63:0] out_timestamp; - wire [15:0] out_length; - generate if (SYNC_CLKS) begin : gen_sync_fifo - axi_fifo #( - .WIDTH (CHDR_W+1), - .SIZE (PAYLOAD_FIFO_SIZE) - ) pyld_fifo ( - .clk (axis_chdr_clk), - .reset (axis_chdr_rst), - .clear (1'b0), - .i_tdata ({in_pyld_tlast, in_pyld_tdata}), - .i_tvalid (in_pyld_tvalid), - .i_tready (in_pyld_tready), - .o_tdata ({out_pyld_tlast, out_pyld_tdata}), - .o_tvalid (out_pyld_tvalid), - .o_tready (out_pyld_tready), - .space (), - .occupied () - ); - axi_fifo #( - .WIDTH (3 + 64 + 16), - .SIZE (INFO_FIFO_SIZE) - ) pkt_info_fifo ( - .clk (axis_chdr_clk), - .reset (axis_chdr_rst), - .clear (1'b0), - .i_tdata ({packet_eob, packet_eov, packet_has_time,packet_timestamp, packet_length}), - .i_tvalid (in_pkt_info_tvalid), - .i_tready (in_pkt_info_tready), - .o_tdata ({out_eob, out_eov, out_has_time, out_timestamp, out_length}), - .o_tvalid (out_pkt_info_tvalid), - .o_tready (out_pkt_info_tready), - .space (), - .occupied () - ); - - end else begin : gen_async_fifo - axi_fifo_2clk #( - .WIDTH (CHDR_W + 1), - .SIZE (PAYLOAD_FIFO_SIZE) - ) pyld_fifo ( - .reset (axis_data_rst), - .i_aclk (axis_data_clk), - .i_tdata ({in_pyld_tlast, in_pyld_tdata}), - .i_tvalid (in_pyld_tvalid), - .i_tready (in_pyld_tready), - .o_aclk (axis_chdr_clk), - .o_tdata ({out_pyld_tlast, out_pyld_tdata}), - .o_tvalid (out_pyld_tvalid), - .o_tready (out_pyld_tready) - ); - axi_fifo_2clk #( - .WIDTH (3 + 64 + 16), - .SIZE (INFO_FIFO_SIZE) - ) pkt_info_fifo ( - .reset (axis_data_rst), - .i_aclk (axis_data_clk), - .i_tdata ({packet_eob, packet_eov, packet_has_time,packet_timestamp, packet_length}), - .i_tvalid (in_pkt_info_tvalid), - .i_tready (in_pkt_info_tready), - .o_aclk (axis_chdr_clk), - .o_tdata ({out_eob, out_eov, out_has_time, out_timestamp, out_length}), - .o_tvalid (out_pkt_info_tvalid), - .o_tready (out_pkt_info_tready) - ); - end endgenerate + + + + // This state machine prevents data from transferring when the pkt_info_fifo + // is stalled. This ensures that we don't overflow the pkt_info_fifo. + always @(posedge axis_chdr_clk) begin + if (axis_chdr_rst) begin + gating <= 0; + end else begin + if (gating) begin + if (in_pkt_info_tready) gating <= 0; + end else begin + // If we're not asserting tvalid, or we're completing a transfer this + // cycle, then it is safe to gate tvalid on the next cycle. + if (!in_pkt_info_tready && (!in_pyld_tvalid || (in_pyld_tvalid && in_pyld_tready))) begin + gating <= 1; + end + end + end + end //--------------------------------------------------------------------------- diff --git a/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_data.v b/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_data.v index a00a9952c..cb0a29845 100644 --- a/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_data.v +++ b/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_data.v @@ -282,7 +282,7 @@ module chdr_to_axis_data #( end // --------------------------------------------------- - // Payload and mdata FIFOs + // Payload and Sideband Data FIFOs // --------------------------------------------------- wire [CHDR_W-1:0] out_pyld_tdata; wire [CHDR_KEEP_W-1:0] out_pyld_tkeep; @@ -296,54 +296,48 @@ module chdr_to_axis_data #( wire conv_pyld_tlast, conv_pyld_tvalid, conv_pyld_tready; - generate if (SYNC_CLKS) begin : gen_sync_fifo - axi_fifo #(.WIDTH(INFO_W), .SIZE(INFO_FIFO_SIZE)) info_fifo_i ( - .clk(axis_data_clk), .reset(axis_data_rst), .clear(1'b0), - .i_tdata(in_info_tdata), - .i_tvalid(in_info_tvalid), .i_tready(in_info_tready), - .o_tdata(out_info_tdata), - .o_tvalid(out_info_tvalid), .o_tready(out_info_tready), - .space(), .occupied() - ); - axi_fifo #(.WIDTH(CHDR_W+CHDR_KEEP_W+1), .SIZE(PYLD_FIFO_SIZE)) pyld_fifo_i ( - .clk(axis_data_clk), .reset(axis_data_rst), .clear(1'b0), - .i_tdata({in_pyld_tlast, in_pyld_tkeep, in_pyld_tdata}), - .i_tvalid(in_pyld_tvalid), .i_tready(in_pyld_tready), - .o_tdata({out_pyld_tlast, out_pyld_tkeep, out_pyld_tdata}), - .o_tvalid(out_pyld_tvalid), .o_tready(out_pyld_tready), - .space(), .occupied() - ); - end else begin : gen_async_fifo - axi_fifo_2clk #(.WIDTH(INFO_W), .SIZE(INFO_FIFO_SIZE)) info_fifo_i ( - .reset(axis_chdr_rst), - .i_aclk(axis_chdr_clk), - .i_tdata(in_info_tdata), - .i_tvalid(in_info_tvalid), .i_tready(in_info_tready), - .o_aclk(axis_data_clk), - .o_tdata(out_info_tdata), - .o_tvalid(out_info_tvalid), .o_tready(out_info_tready) - ); - axi_fifo_2clk #(.WIDTH(CHDR_W+CHDR_KEEP_W+1), .SIZE(PYLD_FIFO_SIZE)) pyld_fifo_i ( - .reset(axis_chdr_rst), - .i_aclk(axis_chdr_clk), - .i_tdata({in_pyld_tlast, in_pyld_tkeep, in_pyld_tdata}), - .i_tvalid(in_pyld_tvalid), .i_tready(in_pyld_tready), - .o_aclk(axis_data_clk), - .o_tdata({out_pyld_tlast, out_pyld_tkeep, out_pyld_tdata}), - .o_tvalid(out_pyld_tvalid), .o_tready(out_pyld_tready) - ); - end endgenerate - - // --------------------------------------------------- - // Data Width Converter: CHDR_W => ITEM_W*NIPC - // --------------------------------------------------- generate + // Metadata FIFOs + if (SYNC_CLKS) begin : gen_sync_info_fifo + axi_fifo #(.WIDTH(INFO_W), .SIZE(INFO_FIFO_SIZE)) info_fifo_i ( + .clk(axis_data_clk), .reset(axis_data_rst), .clear(1'b0), + .i_tdata(in_info_tdata), + .i_tvalid(in_info_tvalid), .i_tready(in_info_tready), + .o_tdata(out_info_tdata), + .o_tvalid(out_info_tvalid), .o_tready(out_info_tready), + .space(), .occupied() + ); + end else begin : gen_async_info_fifo + axi_fifo_2clk #(.WIDTH(INFO_W), .SIZE(INFO_FIFO_SIZE)) info_fifo_i ( + .reset(axis_chdr_rst), + .i_aclk(axis_chdr_clk), + .i_tdata(in_info_tdata), + .i_tvalid(in_info_tvalid), .i_tready(in_info_tready), + .o_aclk(axis_data_clk), + .o_tdata(out_info_tdata), + .o_tvalid(out_info_tvalid), .o_tready(out_info_tready) + ); + end + + // Payload FIFOs if (CHDR_W != ITEM_W*NIPC) begin : gen_axis_width_conv + axi_fifo #(.WIDTH(CHDR_W+CHDR_KEEP_W+1), .SIZE(PYLD_FIFO_SIZE)) pyld_fifo_i ( + .clk(axis_chdr_clk), .reset(axis_chdr_rst), .clear(1'b0), + .i_tdata({in_pyld_tlast, in_pyld_tkeep, in_pyld_tdata}), + .i_tvalid(in_pyld_tvalid), .i_tready(in_pyld_tready), + .o_tdata({out_pyld_tlast, out_pyld_tkeep, out_pyld_tdata}), + .o_tvalid(out_pyld_tvalid), .o_tready(out_pyld_tready), + .space(), .occupied() + ); + + // Do the width conversion and clock crossing in the axis_width_conv + // module to ensure that the resize happens on the correct side of the + // clock crossing. axis_width_conv #( .WORD_W(ITEM_W), .IN_WORDS(CHDR_W/ITEM_W), .OUT_WORDS(NIPC), - .SYNC_CLKS(1), .PIPELINE("NONE") + .SYNC_CLKS(SYNC_CLKS), .PIPELINE("NONE") ) payload_width_conv_i ( - .s_axis_aclk(axis_data_clk), .s_axis_rst(axis_data_rst), + .s_axis_aclk(axis_chdr_clk), .s_axis_rst(axis_chdr_rst), .s_axis_tdata(out_pyld_tdata), .s_axis_tkeep(out_pyld_tkeep), .s_axis_tlast(out_pyld_tlast), .s_axis_tvalid(out_pyld_tvalid), .s_axis_tready(out_pyld_tready), @@ -353,6 +347,28 @@ module chdr_to_axis_data #( .m_axis_tready(conv_pyld_tready) ); end else begin : no_gen_axis_width_conv + if (SYNC_CLKS) begin : gen_sync_pyld_fifo + axi_fifo #(.WIDTH(CHDR_W+CHDR_KEEP_W+1), .SIZE(PYLD_FIFO_SIZE)) pyld_fifo_i ( + .clk(axis_chdr_clk), .reset(axis_chdr_rst), .clear(1'b0), + .i_tdata({in_pyld_tlast, in_pyld_tkeep, in_pyld_tdata}), + .i_tvalid(in_pyld_tvalid), .i_tready(in_pyld_tready), + .o_tdata({out_pyld_tlast, out_pyld_tkeep, out_pyld_tdata}), + .o_tvalid(out_pyld_tvalid), .o_tready(out_pyld_tready), + .space(), .occupied() + ); + end else begin : gen_async_pyld_fifo + axi_fifo_2clk #(.WIDTH(CHDR_W+CHDR_KEEP_W+1), .SIZE(PYLD_FIFO_SIZE)) pyld_fifo_i ( + .reset(axis_chdr_rst), + .i_aclk(axis_chdr_clk), + .i_tdata({in_pyld_tlast, in_pyld_tkeep, in_pyld_tdata}), + .i_tvalid(in_pyld_tvalid), .i_tready(in_pyld_tready), + .o_aclk(axis_data_clk), + .o_tdata({out_pyld_tlast, out_pyld_tkeep, out_pyld_tdata}), + .o_tvalid(out_pyld_tvalid), .o_tready(out_pyld_tready) + ); + end + + // No width conversion needed assign conv_pyld_tdata = out_pyld_tdata; assign conv_pyld_tkeep = out_pyld_tkeep; assign conv_pyld_tlast = out_pyld_tlast; @@ -372,9 +388,9 @@ module chdr_to_axis_data #( assign flush_tdata = { out_info_tdata, conv_pyld_tkeep, conv_pyld_tdata }; assign flush_tlast = conv_pyld_tlast; - assign flush_tvalid = conv_pyld_tvalid && out_info_tvalid; - assign conv_pyld_tready = flush_tready && out_info_tvalid; - assign out_info_tready = conv_pyld_tready && conv_pyld_tlast && conv_pyld_tvalid; + assign flush_tvalid = conv_pyld_tvalid && out_info_tvalid; + assign conv_pyld_tready = flush_tready && out_info_tvalid; + assign out_info_tready = conv_pyld_tready && conv_pyld_tlast && conv_pyld_tvalid; // --------------------------------------------------- // Flushing Logic |