-
Notifications
You must be signed in to change notification settings - Fork 7
/
dec_lite_rx.v
134 lines (113 loc) · 4.52 KB
/
dec_lite_rx.v
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Copyright (c) 2023, Julia Desmazes. All rights reserved.
*
* This work is licensed under the Creative Commons Attribution-NonCommercial
* 4.0 International License.
*
* This code is provided "as is" without any express or implied warranties. */
/* PCS decode block, use on rx path.
* Received block data may be invalid if it is
* deemed malformed.
*/
module dec_lite_rx #(
parameter IS_40G = 0,
parameter HEAD_W = 2,
parameter DATA_W = 64,
parameter KEEP_W = DATA_W/8,
parameter LANE0_CNT_N = IS_40G ? 1 : 2,
parameter BLOCK_TYPE_W = 8
)(
input [HEAD_W-1:0] head_i,
input [DATA_W-1:0] data_i,
// lite dec interface, not x(l)gmii interface
output ctrl_v_o,
output idle_v_o,
output [LANE0_CNT_N-1:0] start_v_o,
output term_v_o,
output err_v_o,
output ord_v_o,
output [DATA_W-1:0] data_o, // x(l)gmii data
output [KEEP_W-1:0] keep_o
);
/* verilator lint_off UNUSEDPARAM*/
localparam [BLOCK_TYPE_W-1:0]
BLOCK_TYPE_CTRL = 8'h1e, // C7 C6 C5 C4 C3 C2 C1 C0 BT
BLOCK_TYPE_OS_4 = 8'h2d, // D7 D6 D5 O4 C3 C2 C1 C0 BT
BLOCK_TYPE_START_4 = 8'h33, // D7 D6 D5 C3 C2 C1 C0 BT
BLOCK_TYPE_OS_START = 8'h66, // D7 D6 D5 O0 D3 D2 D1 BT
BLOCK_TYPE_OS_04 = 8'h55, // D7 D6 D5 O4 O0 D3 D2 D1 BT
BLOCK_TYPE_START_0 = 8'h78, // D7 D6 D5 D4 D3 D2 D1 BT
BLOCK_TYPE_OS_0 = 8'h4b, // C7 C6 C5 C4 O0 D3 D2 D1 BT
BLOCK_TYPE_TERM_0 = 8'h87, // C7 C6 C5 C4 C3 C2 C1 BT
BLOCK_TYPE_TERM_1 = 8'h99, // C7 C6 C5 C4 C3 C2 D0 BT
BLOCK_TYPE_TERM_2 = 8'haa, // C7 C6 C5 C4 C3 D1 D0 BT
BLOCK_TYPE_TERM_3 = 8'hb4, // C7 C6 C5 C4 D2 D1 D0 BT
BLOCK_TYPE_TERM_4 = 8'hcc, // C7 C6 C5 D3 D2 D1 D0 BT
BLOCK_TYPE_TERM_5 = 8'hd2, // C7 C6 D4 D3 D2 D1 D0 BT
BLOCK_TYPE_TERM_6 = 8'he1, // C7 D5 D4 D3 D2 D1 D0 BT
BLOCK_TYPE_TERM_7 = 8'hff; // D6 D5 D4 D3 D2 D1 D0 BT
localparam SYNC_HEAD_CTRL = 2'b10;
localparam SYNC_HEAD_DATA = 2'b01;
/* verilator lint_on UNUSEDPARAM*/
// recieved block data is invalid, it is malformed.
// follows rules outlined in 49.2.4.6
logic block_nv;
// head
logic head_v; // head is wellformed
assign head_v = head_i[0] ^ head_i[1];
// look for matching control code
logic [BLOCK_TYPE_W-1:0] block_type;
logic block_type_none;
logic idle_lite;
logic ord_lite; // ordered set
logic [KEEP_W-1:0] term_lite;
logic [LANE0_CNT_N-1:0] start_lite;
logic idle_v;
logic err_v;
logic ord_v; // ordered set
logic [KEEP_W-1:0] term_v;
logic [LANE0_CNT_N-1:0] start_v;
assign block_type = data_i[BLOCK_TYPE_W-1:0];
assign idle_lite = block_type == BLOCK_TYPE_CTRL;
assign ord_lite = 1'b0; // TODO : add support for order set codes
assign term_lite[0] = block_type == BLOCK_TYPE_TERM_0;
assign term_lite[1] = block_type == BLOCK_TYPE_TERM_1;
assign term_lite[2] = block_type == BLOCK_TYPE_TERM_2;
assign term_lite[3] = block_type == BLOCK_TYPE_TERM_3;
assign term_lite[4] = block_type == BLOCK_TYPE_TERM_4;
assign term_lite[5] = block_type == BLOCK_TYPE_TERM_5;
assign term_lite[6] = block_type == BLOCK_TYPE_TERM_6;
assign term_lite[7] = block_type == BLOCK_TYPE_TERM_7;
assign start_lite[0] = block_type == BLOCK_TYPE_START_0;
generate
if ( !IS_40G ) begin : gen_is_10g
assign start_lite[1] = block_type == BLOCK_TYPE_START_4;
end
endgenerate
// no valid control code was dound
assign block_type_none = ~( idle_lite | ord_lite | |term_lite | |start_lite );
// mask control code if the block is invalid
assign err_v = block_nv;
assign idle_v = idle_lite & ~block_nv;
assign ord_v = ord_lite & ~block_nv;
assign term_v = term_lite & {KEEP_W{~block_nv}};
assign start_v = start_lite & {LANE0_CNT_N{~block_nv}};
// keep signal value
// this signal exists only in our implementation, as such it doesn't follow 802.3
// as we will not be using start_4 our keep signal doesn't show a correct mask for
// that case ( 8'b1110_0000 ).
// keep signal is only valid for term
assign keep_o = term_lite - {{KEEP_W-1{1'b0}}, 1'b1};
// check if block is valid
assign block_nv = ~head_v | ( head_v & head_i[1] & block_type_none);
// output
// check if we have ctrl, or reception error
assign ctrl_v_o = head_i[1] | block_nv;
assign idle_v_o = idle_v;
assign err_v_o = err_v;
assign ord_v_o = ord_v;
assign term_v_o = |term_v;
assign start_v_o = start_v;
assign data_o = data_i;
`ifdef FORMAL
`endif
endmodule