-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathpcs_tx.v
161 lines (145 loc) · 2.84 KB
/
pcs_tx.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// SPDX-License-Identifier: AGPL-3.0-Only OR CERN-OHL-S-2.0
/*
* Copyright (C) 2022 Sean Anderson <[email protected]>
*/
`include "common.vh"
`include "pcs.vh"
`timescale 1ns/1ns
/* Transmit process */
module pcs_tx (
/* MII */
input clk,
input ce,
input enable,
input [3:0] data,
input err,
/* PMA */
output bits,
input link_status,
/* Internal */
output reg tx
);
localparam IDLE = 0;
localparam START_J = 1;
localparam START_K = 2;
localparam ERROR_J = 3;
localparam ERROR_K = 4;
localparam ERROR = 5;
localparam DATA = 6;
localparam END_T = 7;
localparam END_R = 8;
reg [3:0] last_data;
reg tx_next;
reg [4:0] code, code_next;
reg [3:0] state, state_next;
initial tx = 0;
initial code = `CODE_I;
initial state = IDLE;
always @(*) begin
case (last_data)
4'h0: code_next = `CODE_0;
4'h1: code_next = `CODE_1;
4'h2: code_next = `CODE_2;
4'h3: code_next = `CODE_3;
4'h4: code_next = `CODE_4;
4'h5: code_next = `CODE_5;
4'h6: code_next = `CODE_6;
4'h7: code_next = `CODE_7;
4'h8: code_next = `CODE_8;
4'h9: code_next = `CODE_9;
4'hA: code_next = `CODE_A;
4'hB: code_next = `CODE_B;
4'hC: code_next = `CODE_C;
4'hD: code_next = `CODE_D;
4'hE: code_next = `CODE_E;
4'hF: code_next = `CODE_F;
endcase
tx_next = tx;
if (enable) begin
if (err)
state_next = ERROR;
else
state_next = DATA;
end else begin
state_next = END_T;
end
case (state)
IDLE: begin
tx_next = 0;
code_next = `CODE_I;
state_next = IDLE;
if (enable) begin
tx_next = 1;
if (err)
state_next = ERROR_J;
else
state_next = START_J;
end
end
START_J: begin
code_next = `CODE_J;
if (err)
state_next = ERROR_K;
else
state_next = START_K;
end
START_K: begin
code_next = `CODE_K;
end
ERROR_J: begin
code_next = `CODE_J;
state_next = ERROR_K;
end
ERROR_K: begin
code_next = `CODE_K;
state_next = ERROR;
end
ERROR: begin
code_next = `CODE_H;
end
DATA: ;
END_T: begin
tx_next = 0;
code_next = `CODE_T;
state_next = END_R;
end
END_R: begin
code_next = `CODE_R;
state_next = IDLE;
end
endcase
if (!link_status) begin
tx_next = 0;
code_next = `CODE_I;
state_next = IDLE;
end
end
always @(posedge clk) begin
if (ce) begin
last_data <= data;
tx <= tx_next;
code <= code_next;
state <= state_next;
end else begin
code <= code << 1;
end
end
`ifndef SYNTHESIS
reg [255:0] state_text;
always @(*) begin
case (state)
IDLE: state_text = "IDLE";
START_J: state_text = "START_J";
START_K: state_text = "START_K";
ERROR_J: state_text = "ERROR_J";
ERROR_K: state_text = "ERROR_K";
ERROR: state_text = "ERROR";
DATA: state_text = "DATA";
END_T: state_text = "END_T";
END_R: state_text = "END_R";
endcase
end
`endif
/* Transmit bits process */
assign bits = code[4];
endmodule