aboutsummaryrefslogtreecommitdiffstats
path: root/fpga
diff options
context:
space:
mode:
authorWade Fife <wade.fife@ettus.com>2020-04-12 17:13:22 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-08-04 15:40:08 -0500
commitb862eda69cf41c7044a1805324f2fcfef5b0ba3d (patch)
tree7ad6cb34cc9b3925d37a75d9b7416057d8e11497 /fpga
parentda3af4e6e86809038872a61696f3d1bac2e8583c (diff)
downloaduhd-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.v222
-rw-r--r--fpga/usrp3/lib/rfnoc/core/chdr_to_axis_data.v110
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