1 |
10 |
antiquity |
//author :Renliang Gu
|
2 |
|
|
//Email: gurenliang@gmail.com
|
3 |
|
|
//note: if there are some errors, please feel free to contact me. Thank you very much!
|
4 |
|
|
|
5 |
|
|
//Next step, reduce the resource consumed
|
6 |
|
|
|
7 |
|
|
//version 0.5, defined many parameter to configure the IP core, making it easier to use.
|
8 |
|
|
//vertion 0.4, add the function for TxModule to get start in a configurable ff_clk time after
|
9 |
|
|
// RxModule receiving the first frame. To modify the delay time just to
|
10 |
|
|
// change the value of the macro-variable delay_cnt_config.
|
11 |
|
|
//version 0.3, changed the changes made by version 0.2 back
|
12 |
|
|
//version 0.2, set empty when ff_data_buf_index's less significant bits is 3'b111 or 3'b000
|
13 |
|
|
|
14 |
|
|
`include "common.v"
|
15 |
|
|
|
16 |
|
|
`define IDXlen 3 //2^IDXlen should be the number of cyclic queue
|
17 |
|
|
`define queue_len (1<<3) //define the length of the cyclic queue
|
18 |
|
|
|
19 |
|
|
`define rx_crc_offset (`data_offset+(`uframelen*`num_uframe/4)) //index of first bit of crc
|
20 |
|
|
`define rx_total_len (`rx_crc_offset + (4<<1))
|
21 |
|
|
`define rxdata_len (`uframelen*`num_uframe/4)
|
22 |
|
|
|
23 |
|
|
`define delay_cnt_config 8 //the initiation value for the delay_cnt
|
24 |
|
|
|
25 |
|
|
module RxModule(phy_rxd, phy_rxen, phy_rxclk, phy_rxer,
|
26 |
|
|
ff_clk, ff_data, ff_en,
|
27 |
|
|
|
28 |
|
|
`ifdef frameIDfromRx
|
29 |
|
|
frameid,
|
30 |
|
|
`endif
|
31 |
|
|
|
32 |
|
|
start,
|
33 |
|
|
test1, test2, test3, test4
|
34 |
|
|
);
|
35 |
|
|
input phy_rxen, phy_rxclk, phy_rxer; //MII interface
|
36 |
|
|
input [3:0] phy_rxd;
|
37 |
|
|
|
38 |
|
|
input ff_clk; //270.8333KHz
|
39 |
|
|
output ff_data, ff_en;
|
40 |
|
|
|
41 |
|
|
`ifdef frameIDfromRx
|
42 |
|
|
output[`frameidlen-1:0] frameid;
|
43 |
|
|
reg[`frameidlen-1:0] frameid;
|
44 |
|
|
`endif
|
45 |
|
|
|
46 |
|
|
output start; //to tell TxModule that buf in RxModule needs data
|
47 |
|
|
output test1, test2, test3, test4;
|
48 |
|
|
reg test1, test2;
|
49 |
|
|
|
50 |
|
|
parameter delay_cnt_len = (`delay_cnt_config < 2) ? 1 : (`delay_cnt_config < 4) ? 2 :
|
51 |
|
|
(`delay_cnt_config < 8) ? 3 : (`delay_cnt_config < 16) ? 4 :
|
52 |
|
|
(`delay_cnt_config < 32) ? 5 : (`delay_cnt_config < 64) ? 6 :
|
53 |
|
|
(`delay_cnt_config < 128) ? 7 : 8;
|
54 |
|
|
parameter nibble_idx_len = (`rx_total_len<= 2)? 1 : (`rx_total_len<= 4)? 2 :
|
55 |
|
|
(`rx_total_len<= 8)? 3 : (`rx_total_len<= 16)? 4 :
|
56 |
|
|
(`rx_total_len<= 32)? 5 : (`rx_total_len<= 64)? 6 :
|
57 |
|
|
(`rx_total_len<= 128)? 7 : (`rx_total_len<= 256)? 8 :
|
58 |
|
|
(`rx_total_len<= 512)? 9 : (`rx_total_len<=1024)? 10 :
|
59 |
|
|
(`rx_total_len<=2048)? 11 : 12;
|
60 |
|
|
parameter ff_idx_len = (`rxdata_len<= 2)? 1 : (`rxdata_len<= 4)? 2 :
|
61 |
|
|
(`rxdata_len<= 8)? 3 : (`rxdata_len<= 16)? 4 :
|
62 |
|
|
(`rxdata_len<= 32)? 5 : (`rxdata_len<= 64)? 6 :
|
63 |
|
|
(`rxdata_len<= 128)? 7 : (`rxdata_len<= 256)? 8 :
|
64 |
|
|
(`rxdata_len<= 512)? 9 : (`rxdata_len<=1024)?10 :
|
65 |
|
|
(`rxdata_len<=2048)?11 : 12;
|
66 |
|
|
parameter frameid_idx_len = ((`frameidlen>>2)<= 2)? 1 : ((`frameidlen>>2)<= 4)? 2 :
|
67 |
|
|
((`frameidlen>>2)<= 8)? 3 : ((`frameidlen>>2)<= 16)? 4 :
|
68 |
|
|
((`frameidlen>>2)<= 32)? 5 : ((`frameidlen>>2)<= 64)? 6 :
|
69 |
|
|
((`frameidlen>>2)<= 64)? 7 : 8;
|
70 |
|
|
parameter ff_cnt_len = (`uframelen < 2) ? 1 : (`uframelen < 4) ? 2 :
|
71 |
|
|
(`uframelen < 8) ? 3 : (`uframelen < 16) ? 4 :
|
72 |
|
|
(`uframelen < 32) ? 5 : (`uframelen < 64) ? 6 :
|
73 |
|
|
(`uframelen < 128) ? 7 : (`uframelen < 256) ? 8 :
|
74 |
|
|
(`uframelen < 512) ? 9 : (`uframelen < 1024) ? 10:
|
75 |
|
|
(`uframelen < 2048) ? 11: (`uframelen < 4096) ? 12:
|
76 |
|
|
(`uframelen < 8192) ? 13: 14;
|
77 |
|
|
|
78 |
|
|
reg ff_data;
|
79 |
|
|
reg ff_en;
|
80 |
|
|
|
81 |
|
|
reg[ff_cnt_len-1:0] ff_cnt;
|
82 |
|
|
reg[2:0] ff_d;
|
83 |
|
|
|
84 |
|
|
reg start=1'b0;
|
85 |
|
|
reg start_intra=1'b0;
|
86 |
|
|
reg[delay_cnt_len-1:0] delay_cnt;
|
87 |
|
|
|
88 |
|
|
reg[3:0] gap_cnt;
|
89 |
|
|
reg[1:0] gap_len_ctl;
|
90 |
|
|
reg[1:0] cycle;
|
91 |
|
|
|
92 |
|
|
reg[3:0] rxdata_buf [0:(`rxdata_len*`queue_len+1)]; //more ram for special usage
|
93 |
|
|
wire[ff_idx_len+`IDXlen-1:0] rxdata_buf_writer_address;
|
94 |
|
|
reg[ff_idx_len+`IDXlen-1:0] rxdata_buf_reader_address;
|
95 |
|
|
|
96 |
|
|
reg[`frameidlen-1:0] frameid_buf[0:(`queue_len-1)];
|
97 |
|
|
|
98 |
|
|
reg[nibble_idx_len-1:0] nibble_idx;
|
99 |
|
|
reg[ff_idx_len-1:0] ff_idx;
|
100 |
|
|
|
101 |
|
|
reg[`IDXlen-1:0] rxIDX, ffIDX;
|
102 |
|
|
|
103 |
|
|
reg bad_da;
|
104 |
|
|
reg queue_empty;
|
105 |
|
|
|
106 |
|
|
reg[2:0] rxState = 0;
|
107 |
|
|
parameter s_preamble = 0, s_address = 1, s_typelen = 2,
|
108 |
|
|
s_frameid = 3, s_data = 4, s_crc = 5;
|
109 |
|
|
reg[1:0] ff_state = 0;
|
110 |
|
|
parameter ffs_idle = 0, ffs_transfer = 1, ffs_gap = 2;
|
111 |
|
|
|
112 |
|
|
wire[47:0] mac_add;
|
113 |
|
|
wire[3:0] da[0:11];
|
114 |
|
|
assign mac_add = `MAC_ADD;
|
115 |
|
|
assign da[ 0] = mac_add[ 3: 0];
|
116 |
|
|
assign da[ 1] = mac_add[ 7: 4];
|
117 |
|
|
assign da[ 2] = mac_add[11: 8];
|
118 |
|
|
assign da[ 3] = mac_add[15:12];
|
119 |
|
|
assign da[ 4] = mac_add[19:16];
|
120 |
|
|
assign da[ 5] = mac_add[23:20];
|
121 |
|
|
assign da[ 6] = mac_add[27:24];
|
122 |
|
|
assign da[ 7] = mac_add[31:28];
|
123 |
|
|
assign da[ 8] = mac_add[35:32];
|
124 |
|
|
assign da[ 9] = mac_add[39:36];
|
125 |
|
|
assign da[10] = mac_add[43:40];
|
126 |
|
|
assign da[11] = mac_add[47:44];
|
127 |
|
|
|
128 |
|
|
assign test4 = start_intra;
|
129 |
|
|
assign test3 = start;
|
130 |
|
|
|
131 |
|
|
always@(posedge phy_rxclk)begin //control the increasing of nibble_idx;
|
132 |
|
|
if(phy_rxen & ~phy_rxer) //data is valid and no error
|
133 |
|
|
nibble_idx <= nibble_idx + 1;
|
134 |
|
|
else
|
135 |
|
|
nibble_idx <= 0;
|
136 |
|
|
end
|
137 |
|
|
|
138 |
|
|
always@(posedge phy_rxclk)begin
|
139 |
|
|
if(phy_rxen & ~phy_rxer)
|
140 |
|
|
case (rxState)
|
141 |
|
|
s_preamble:
|
142 |
|
|
if(nibble_idx == `da_offset-1) rxState <= s_address;
|
143 |
|
|
else rxState <= s_preamble;
|
144 |
|
|
|
145 |
|
|
s_address:
|
146 |
|
|
if(nibble_idx == `typelen_offset-1) rxState <= s_typelen;
|
147 |
|
|
else rxState <= s_address;
|
148 |
|
|
|
149 |
|
|
s_typelen:
|
150 |
|
|
if(nibble_idx == `frameid_offset-1) rxState <= s_frameid;
|
151 |
|
|
else rxState <= s_typelen;
|
152 |
|
|
|
153 |
|
|
s_frameid:
|
154 |
|
|
if(nibble_idx == `data_offset-1) rxState <= s_data;
|
155 |
|
|
else rxState <= s_frameid;
|
156 |
|
|
|
157 |
|
|
s_data:
|
158 |
|
|
if(nibble_idx == `rx_crc_offset-1) rxState <= s_crc;
|
159 |
|
|
else rxState <= s_data;
|
160 |
|
|
|
161 |
|
|
s_crc:
|
162 |
|
|
if(nibble_idx == `rx_total_len-1) rxState <= s_preamble;
|
163 |
|
|
else rxState <= s_crc;
|
164 |
|
|
|
165 |
|
|
default: rxState <= rxState;
|
166 |
|
|
endcase
|
167 |
|
|
else
|
168 |
|
|
rxState <= s_preamble;
|
169 |
|
|
end
|
170 |
|
|
|
171 |
|
|
assign rxdata_buf_writer_address = rxIDX*`rxdata_len + nibble_idx - `data_offset;
|
172 |
|
|
|
173 |
|
|
always@(posedge phy_rxclk)begin //receive data from Ethernet including the preamble, SFD and CRC
|
174 |
|
|
if(phy_rxen & ~phy_rxer) begin //data is valid and no error
|
175 |
|
|
case (rxState)
|
176 |
|
|
s_preamble: test1 <= ~test1;
|
177 |
|
|
s_address:
|
178 |
|
|
if((phy_rxd!=da[nibble_idx-`da_offset])&(nibble_idx < `sa_offset))
|
179 |
|
|
bad_da <= 1;
|
180 |
|
|
|
181 |
|
|
s_frameid: begin
|
182 |
|
|
if(nibble_idx==`frameid_offset) begin
|
183 |
|
|
rxIDX <= phy_rxd[2:0];
|
184 |
|
|
frameid_buf[phy_rxd[2:0]][(`frameidlen-1):(`frameidlen-4)] <= phy_rxd;
|
185 |
|
|
end else
|
186 |
|
|
frameid_buf[rxIDX] <= {phy_rxd, frameid_buf[rxIDX][(`frameidlen-1):4]};
|
187 |
|
|
end
|
188 |
|
|
|
189 |
|
|
s_data: begin
|
190 |
|
|
//test2 <= ~test2;
|
191 |
|
|
rxdata_buf[rxdata_buf_writer_address] <= phy_rxd;
|
192 |
|
|
end
|
193 |
|
|
endcase
|
194 |
|
|
end else if ((nibble_idx == `rx_total_len ) & (!bad_da)) begin
|
195 |
|
|
//one frame has been transfered over, the destinate address is right and then been put into the buffer
|
196 |
|
|
start_intra <= 1;
|
197 |
|
|
end else
|
198 |
|
|
bad_da <= 0;
|
199 |
|
|
end
|
200 |
|
|
|
201 |
|
|
always@(negedge ff_clk) begin
|
202 |
|
|
case(ff_state)
|
203 |
|
|
ffs_idle: begin //wait the first frame to come
|
204 |
|
|
gap_len_ctl <= 0;
|
205 |
|
|
if(start_intra) ff_state <= ffs_transfer;
|
206 |
|
|
else ff_state <= ffs_idle;
|
207 |
|
|
end
|
208 |
|
|
|
209 |
|
|
ffs_transfer: begin
|
210 |
|
|
if(ff_cnt == `uframelen-1)begin //every `uframelen bit need a gap
|
211 |
|
|
ff_state <= ffs_gap;
|
212 |
|
|
gap_len_ctl <= gap_len_ctl + 1;
|
213 |
|
|
end
|
214 |
|
|
else ff_state <= ffs_transfer;
|
215 |
|
|
end
|
216 |
|
|
ffs_gap: begin
|
217 |
|
|
if(((gap_len_ctl == 0)&(gap_cnt == 8)) | ((gap_len_ctl != 0)&(gap_cnt == 7)))
|
218 |
|
|
ff_state <=ffs_transfer;
|
219 |
|
|
else ff_state <= ffs_gap;
|
220 |
|
|
end
|
221 |
|
|
endcase
|
222 |
|
|
end
|
223 |
|
|
|
224 |
|
|
always@(negedge ff_clk) begin //flow the data out of the buffer
|
225 |
|
|
case(ff_state)
|
226 |
|
|
ffs_idle: begin
|
227 |
|
|
ff_cnt <= 0;
|
228 |
|
|
delay_cnt <= 0;
|
229 |
|
|
cycle <= 0;
|
230 |
|
|
ff_en <= 0;
|
231 |
|
|
ff_idx <= 0;
|
232 |
|
|
ffIDX <= rxIDX + 1;
|
233 |
|
|
start <= 0;
|
234 |
|
|
rxdata_buf_reader_address <= ffIDX*`rxdata_len+ff_idx;
|
235 |
|
|
end
|
236 |
|
|
|
237 |
|
|
ffs_transfer: begin
|
238 |
|
|
`ifdef frameIDfromRx
|
239 |
|
|
frameid <= frameid_buf[ffIDX];
|
240 |
|
|
`endif
|
241 |
|
|
if(delay_cnt == `delay_cnt_config) start <= 1;
|
242 |
|
|
delay_cnt <= delay_cnt + 1;
|
243 |
|
|
gap_cnt <= 0;
|
244 |
|
|
ff_cnt <= ff_cnt + 1;
|
245 |
|
|
cycle <= cycle + 1;
|
246 |
|
|
ff_en <= 1;
|
247 |
|
|
|
248 |
|
|
if(cycle==0) begin
|
249 |
|
|
{ff_d[2:0],ff_data} <= rxdata_buf[rxdata_buf_reader_address];
|
250 |
|
|
if(ff_idx == `rxdata_len-1)begin
|
251 |
|
|
if(ffIDX!=rxIDX) begin
|
252 |
|
|
queue_empty <= 0;
|
253 |
|
|
if(queue_empty) begin
|
254 |
|
|
ffIDX <= rxIDX + ((`delay_cnt_config==0)? 1:2) ;
|
255 |
|
|
rxdata_buf_reader_address <= (rxIDX + ((`delay_cnt_config==0)? 1:2))*`rxdata_len;
|
256 |
|
|
end
|
257 |
|
|
else begin
|
258 |
|
|
ffIDX <= ffIDX + 1;
|
259 |
|
|
rxdata_buf_reader_address <= (ffIDX+1)*`rxdata_len;
|
260 |
|
|
end
|
261 |
|
|
end else begin
|
262 |
|
|
rxdata_buf_reader_address <= ffIDX*`rxdata_len;
|
263 |
|
|
queue_empty <= 1;
|
264 |
|
|
end
|
265 |
|
|
ff_idx <= 0;
|
266 |
|
|
end
|
267 |
|
|
else begin
|
268 |
|
|
ff_idx <= ff_idx + 1;
|
269 |
|
|
rxdata_buf_reader_address <= ffIDX*`rxdata_len+ff_idx+1;
|
270 |
|
|
end
|
271 |
|
|
end else
|
272 |
|
|
{ff_d[1:0],ff_data} <= ff_d;
|
273 |
|
|
end
|
274 |
|
|
|
275 |
|
|
ffs_gap: begin //the 8.25 bit gap is implement by (3*8+9)/4
|
276 |
|
|
ff_en <= 0;
|
277 |
|
|
ff_data <= 0;
|
278 |
|
|
ff_cnt <= 0;
|
279 |
|
|
gap_cnt <= gap_cnt + 1;
|
280 |
|
|
end
|
281 |
|
|
endcase
|
282 |
|
|
end
|
283 |
|
|
endmodule
|