aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v')
-rw-r--r--fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v110
1 files changed, 110 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v b/fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v
new file mode 100644
index 000000000..c7f899ee9
--- /dev/null
+++ b/fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v
@@ -0,0 +1,110 @@
+//
+// Copyright 2018-2019 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: context_handler_sync
+// Description:
+//
+// Parameters:
+// - CHDR_W: Width of the input CHDR bus in bits
+//
+// Signals:
+//
+
+module context_handler_sync #(
+ parameter CHDR_W = 256,
+ parameter ITEM_W = 32,
+ parameter NIPC = 2
+)(
+ // Clock and reset
+ input wire clk,
+ input wire rst,
+ // Context stream in (AXI-Stream)
+ input wire [CHDR_W-1:0] s_axis_context_tdata,
+ input wire [3:0] s_axis_context_tuser,
+ input wire s_axis_context_tlast,
+ input wire s_axis_context_tvalid,
+ output wire s_axis_context_tready,
+ // Context stream out (AXI-Stream)
+ output wire [CHDR_W-1:0] m_axis_context_tdata,
+ output wire [3:0] m_axis_context_tuser,
+ output wire m_axis_context_tlast,
+ output wire m_axis_context_tvalid,
+ input wire m_axis_context_tready,
+ // Input payload stream monitor
+ input wire [NIPC-1:0] in_payload_tkeep,
+ input wire in_payload_tlast,
+ input wire in_payload_tvalid,
+ input wire in_payload_tready,
+ // Output payload stream monitor
+ input wire [NIPC-1:0] out_payload_tkeep,
+ input wire out_payload_tlast,
+ input wire out_payload_tvalid,
+ input wire out_payload_tready,
+ // Status
+ output reg length_err_stb,
+ output reg seq_err_stb
+);
+
+ `include "../core/rfnoc_chdr_utils.vh"
+
+ // Thermometer to binary decoder
+ // 4'b0000 => 3'd0
+ // 4'b0001 => 3'd1
+ // 4'b0011 => 3'd2
+ // 4'b0111 => 3'd3
+ // 4'b1111 => 3'd4
+ function [$clog2(NIPC):0] thermo2bin(input [NIPC-1:0] thermo);
+ reg [NIPC:0] onehot;
+ integer i;
+ begin
+ onehot = thermo + 1;
+ thermo2bin = 0;
+ for (i = 0; i <= NIPC; i=i+1)
+ if (onehot[i])
+ thermo2bin = thermo2bin | i;
+ end
+ endfunction
+
+ axi_fifo #(.WIDTH(CHDR_W+4+1), .SIZE(1)) ctxt_pipe_i (
+ .clk(clk), .reset(rst), .clear(1'b0),
+ .i_tdata({s_axis_context_tlast, s_axis_context_tuser, s_axis_context_tdata}),
+ .i_tvalid(s_axis_context_tvalid), .i_tready(s_axis_context_tready),
+ .o_tdata({m_axis_context_tlast, m_axis_context_tuser, m_axis_context_tdata}),
+ .o_tvalid(m_axis_context_tvalid), .o_tready(m_axis_context_tready),
+ .space(), .occupied()
+ );
+
+ wire is_ctxt_hdr = s_axis_context_tvalid && s_axis_context_tready &&
+ (s_axis_context_tuser == CONTEXT_FIELD_HDR ||
+ s_axis_context_tuser == CONTEXT_FIELD_HDR_TS);
+
+ reg [15:0] exp_pkt_len = 16'd0;
+ reg [15:0] exp_seq_num = 16'd0;
+ reg check_seq_num = 1'b0;
+ always @(posedge clk) begin
+ if (rst) begin
+ exp_pkt_len <= 16'd0;
+ check_seq_num <= 1'b0;
+ end else if (is_ctxt_hdr) begin
+ check_seq_num <= 1'b1;
+ exp_pkt_len <= chdr_get_length(s_axis_context_tdata[63:0]);
+ exp_seq_num <= chdr_get_seq_num(s_axis_context_tdata[63:0]) + 16'd1;
+ end
+ seq_err_stb <= is_ctxt_hdr && check_seq_num &&
+ (exp_seq_num != chdr_get_seq_num(s_axis_context_tdata[63:0]));
+ end
+
+ reg [15:0] pyld_pkt_len = 16'd0;
+ always @(posedge clk) begin
+ if (rst) begin
+ pyld_pkt_len <= 16'd0;
+ end else if (in_payload_tvalid && in_payload_tready) begin
+ pyld_pkt_len <= in_payload_tlast ? 16'd0 : (pyld_pkt_len + ((ITEM_W*NIPC)/8));
+ end
+ length_err_stb <= in_payload_tvalid && in_payload_tready && in_payload_tlast &&
+ (pyld_pkt_len + (thermo2bin(in_payload_tkeep)*(ITEM_W/8)) != exp_pkt_len);
+ end
+
+endmodule // context_handler_sync