1// 2// Copyright 2018-2019 Ettus Research, A National Instruments Company 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// 6// Module: context_handler_sync 7// Description: 8// 9// Parameters: 10// - CHDR_W: Width of the input CHDR bus in bits 11// 12// Signals: 13// 14 15module context_handler_sync #( 16 parameter CHDR_W = 256, 17 parameter ITEM_W = 32, 18 parameter NIPC = 2 19)( 20 // Clock and reset 21 input wire clk, 22 input wire rst, 23 // Context stream in (AXI-Stream) 24 input wire [CHDR_W-1:0] s_axis_context_tdata, 25 input wire [3:0] s_axis_context_tuser, 26 input wire s_axis_context_tlast, 27 input wire s_axis_context_tvalid, 28 output wire s_axis_context_tready, 29 // Context stream out (AXI-Stream) 30 output wire [CHDR_W-1:0] m_axis_context_tdata, 31 output wire [3:0] m_axis_context_tuser, 32 output wire m_axis_context_tlast, 33 output wire m_axis_context_tvalid, 34 input wire m_axis_context_tready, 35 // Input payload stream monitor 36 input wire [NIPC-1:0] in_payload_tkeep, 37 input wire in_payload_tlast, 38 input wire in_payload_tvalid, 39 input wire in_payload_tready, 40 // Output payload stream monitor 41 input wire [NIPC-1:0] out_payload_tkeep, 42 input wire out_payload_tlast, 43 input wire out_payload_tvalid, 44 input wire out_payload_tready, 45 // Status 46 output reg length_err_stb, 47 output reg seq_err_stb 48); 49 50 `include "../core/rfnoc_chdr_utils.vh" 51 52 // Thermometer to binary decoder 53 // 4'b0000 => 3'd0 54 // 4'b0001 => 3'd1 55 // 4'b0011 => 3'd2 56 // 4'b0111 => 3'd3 57 // 4'b1111 => 3'd4 58 function [$clog2(NIPC):0] thermo2bin(input [NIPC-1:0] thermo); 59 reg [NIPC:0] onehot; 60 integer i; 61 begin 62 onehot = thermo + 1; 63 thermo2bin = 0; 64 for (i = 0; i <= NIPC; i=i+1) 65 if (onehot[i]) 66 thermo2bin = thermo2bin | i; 67 end 68 endfunction 69 70 axi_fifo #(.WIDTH(CHDR_W+4+1), .SIZE(1)) ctxt_pipe_i ( 71 .clk(clk), .reset(rst), .clear(1'b0), 72 .i_tdata({s_axis_context_tlast, s_axis_context_tuser, s_axis_context_tdata}), 73 .i_tvalid(s_axis_context_tvalid), .i_tready(s_axis_context_tready), 74 .o_tdata({m_axis_context_tlast, m_axis_context_tuser, m_axis_context_tdata}), 75 .o_tvalid(m_axis_context_tvalid), .o_tready(m_axis_context_tready), 76 .space(), .occupied() 77 ); 78 79 wire is_ctxt_hdr = s_axis_context_tvalid && s_axis_context_tready && 80 (s_axis_context_tuser == CONTEXT_FIELD_HDR || 81 s_axis_context_tuser == CONTEXT_FIELD_HDR_TS); 82 83 reg [15:0] exp_pkt_len = 16'd0; 84 reg [15:0] exp_seq_num = 16'd0; 85 reg check_seq_num = 1'b0; 86 always @(posedge clk) begin 87 if (rst) begin 88 exp_pkt_len <= 16'd0; 89 check_seq_num <= 1'b0; 90 end else if (is_ctxt_hdr) begin 91 check_seq_num <= 1'b1; 92 exp_pkt_len <= chdr_get_length(s_axis_context_tdata[63:0]); 93 exp_seq_num <= chdr_get_seq_num(s_axis_context_tdata[63:0]) + 16'd1; 94 end 95 seq_err_stb <= is_ctxt_hdr && check_seq_num && 96 (exp_seq_num != chdr_get_seq_num(s_axis_context_tdata[63:0])); 97 end 98 99 reg [15:0] pyld_pkt_len = 16'd0; 100 always @(posedge clk) begin 101 if (rst) begin 102 pyld_pkt_len <= 16'd0; 103 end else if (in_payload_tvalid && in_payload_tready) begin 104 pyld_pkt_len <= in_payload_tlast ? 16'd0 : (pyld_pkt_len + ((ITEM_W*NIPC)/8)); 105 end 106 length_err_stb <= in_payload_tvalid && in_payload_tready && in_payload_tlast && 107 (pyld_pkt_len + (thermo2bin(in_payload_tkeep)*(ITEM_W/8)) != exp_pkt_len); 108 end 109 110endmodule // context_handler_sync 111