1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
|