-
Notifications
You must be signed in to change notification settings - Fork 8
/
phy_rx_module.v
186 lines (152 loc) · 4.6 KB
/
phy_rx_module.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
`timescale 1ns / 1ps
module phy_rx_module(
input clk_in,
input data_in,
output MII_RX_CLK,
output MII_RX_EN,
output [3:0] MII_RXD
);
reg mii_rx_clk_reg = 'd0;//2.5 mhz
reg [3:0] mii_rxd_reg = 'd0;//buffered MII_RXD value
reg mii_en_reg = 'd0;//buffered MII_RX_EN value
assign MII_RX_CLK = mii_rx_clk_reg;//2.5 MHz
assign MII_RXD = mii_rxd_reg;
assign MII_RX_EN = mii_en_reg;
reg [4:0] clk_cnt = 5'd0;//used for 2.5 MHz generation
reg [3:0] data = 4'd0;//shift register
reg [3:0] data_latch = 4'd0;//internal received data
reg [4:0] fifo_buf [0:3];
reg [1:0] index = 2'd0;
//fifo is used to keep delta time between edges
initial
begin
fifo_buf[0] = 'd0;
fifo_buf[1] = 'd0;
fifo_buf[2] = 'd0;
fifo_buf[3] = 'd0;
end
reg [4:0] delta_cnt = 5'd0;//time betveen EDGES
wire ext_stop;//ext stop is extending stop_signal (protection from TP_IDLE part)
wire stop_signal = ((delta_cnt > 'd13)? 1'd1: 1'd0) | ext_stop;//high the end of packet
pulse_extend local_pulse_extend(.clk_in(clk_in), .pulse_in(stop_signal), .pulse_out(ext_stop));
reg new_data = 'd0;//buffered signal for MII_RX_EN
//80 div 24 = 2.5 MHz
//clk generation
always@(posedge clk_in)
begin
if (clk_cnt > 'd30)
begin
clk_cnt = 'd0;
end
else clk_cnt = clk_cnt + 5'd1;//30+1=31, and (31) will be hold for a tick
if (clk_cnt < 'd16) mii_rx_clk_reg<= 'd1;//10 mhz
else mii_rx_clk_reg<= 'd0;
if (clk_cnt == 'd0)
begin
mii_rxd_reg<= data_latch;//synchronize data
mii_en_reg<= new_data;//synchronize enable
end
end
reg [3:0] shift_reg = 4'd0;
always @(posedge clk_in) shift_reg <= {shift_reg[2:0], data_in};
wire [1:0] window = shift_reg[3:2];
reg pos_edge = 1'd0;
reg neg_edge = 1'd0;
wire any_edge = pos_edge | neg_edge;
//edge detection part
always @(posedge clk_in)
begin
if (window == 2'b01) pos_edge <= 1'd1;
else if (window == 'b10) neg_edge<= 1'd1;
else
begin
pos_edge<= 1'd0;
neg_edge<= 1'd0;
end
end
//fifo - store delay between edges
always @(posedge clk_in)
begin
if (any_edge)
begin
for(index = 2'd3; index > 2'd0; index = index - 2'd1)
begin
fifo_buf[index] = fifo_buf[index - 'd1];
end
fifo_buf[0] = delta_cnt + 5'd1;
delta_cnt = 'd0;
end
else if (delta_cnt < 'd16) delta_cnt = delta_cnt + 'd1;
end
wire center = (((fifo_buf[0] == fifo_buf[2]) && (fifo_buf[1] == fifo_buf[3]) && (fifo_buf[0] > 0)) & any_edge)? 1'd1:1'd0;
reg [9:0] timeout2 = 'd40;//used to remove noise, NLP
wire capt_en = (timeout2 < 'd60)? 1'd1: 1'd0;//capture enabled
reg end_reset = 1'd0;//1 tick pulse at the end of the packet (used to reset pos_edge_cnt)
reg [9:0] timeout1 = 'd100;//clears at every signal pos edge
wire capt_en2 = (timeout1 < 'd99)? 1'd1: 1'd0;//capture enabled
always @(posedge clk_in)
begin
if (pos_edge)//first edge in packet is pos
timeout1<= 'd0;
else if (capt_en2) timeout1 <= timeout1 +10'd1;//overflow protection
end_reset <= (timeout1 == 'd90)? 1'd1: 1'd0;//value is buffered
end
reg [1:0] pos_edge_cnt = 'd0;//used for sync with right edge
always @(posedge clk_in)
begin
if (pos_edge && (!capt_en2))//first edge in packet is pos
pos_edge_cnt <= 'd0;
else if (any_edge) pos_edge_cnt <= pos_edge_cnt + 2'd1;
else if (end_reset) pos_edge_cnt <= 'd0;//additional reset at the end of pulse or packet
end
reg [3:0] symb_cnt = 4'd0;//bit time count (synchronized with signal edges)
always @(posedge clk_in)
begin
if (center && (!capt_en) && (pos_edge_cnt == 'd2))//if capture disabled
begin
timeout2 <= 'd0;//reset at the begin of the packet
end
else if (capt_en && any_edge) timeout2 <= 'd0;
else if (capt_en) timeout2 <= timeout2 + 10'd1;//overflow protection
if (center && (!capt_en)) symb_cnt <= 4'd0;
else if (symb_cnt < 4'd7) symb_cnt <= symb_cnt + 4'd1;
else if (symb_cnt > 4'd6) symb_cnt <= 4'd0;
end
reg [1:0] bit_cnt = 2'd0;//number of received bits
//captures data from "data_in"
wire capture = capt_en && (symb_cnt == 'd5);
always @(posedge clk_in)
begin
if (capture)
begin
data = {data_in,data[3:1]};
bit_cnt = bit_cnt + 2'd1;
if (bit_cnt == 2'd0)
begin
data_latch = data;
if (stop_signal == 1'd0)
new_data <= 1'd1;
else
new_data <= 1'd0;
end
end
else if (!capt_en) bit_cnt<= 2'd0;//reset at the end of the packet
end
endmodule
//find pos edge at "pulse_in" and create 30 ticks pulse at "pulse_out"
module pulse_extend(
input clk_in,
input pulse_in,
output pulse_out
);
reg [5:0] cnt = 6'd0;
reg [1:0] trig = 2'd0;
always@(posedge clk_in) trig <= {trig[0],pulse_in};
wire start_edge = (trig == 2'b01) ? 1'b1 : 1'b0;
assign pulse_out = (cnt < 'd30);
always @(posedge clk_in)
begin
if (start_edge) cnt<= 6'd0;
else if (pulse_out) cnt<= cnt+ 6'd1;
end
endmodule