diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/utils/context_handler_sync.v | 110 |
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 |