1 //////////////////////////////////////////////////////////////////////
\r
3 //// MAC_rx_ctrl.v ////
\r
5 //// This file is part of the Ethernet IP core project ////
\r
6 //// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode/////
\r
9 //// - Jon Gao (gaojon@yahoo.com) ////
\r
12 //////////////////////////////////////////////////////////////////////
\r
14 //// Copyright (C) 2001 Authors ////
\r
16 //// This source file may be used and distributed without ////
\r
17 //// restriction provided that this copyright statement is not ////
\r
18 //// removed from the file and that any derivative work contains ////
\r
19 //// the original copyright notice and the associated disclaimer. ////
\r
21 //// This source file is free software; you can redistribute it ////
\r
22 //// and/or modify it under the terms of the GNU Lesser General ////
\r
23 //// Public License as published by the Free Software Foundation; ////
\r
24 //// either version 2.1 of the License, or (at your option) any ////
\r
25 //// later version. ////
\r
27 //// This source is distributed in the hope that it will be ////
\r
28 //// useful, but WITHOUT ANY WARRANTY; without even the implied ////
\r
29 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
\r
30 //// PURPOSE. See the GNU Lesser General Public License for more ////
\r
33 //// You should have received a copy of the GNU Lesser General ////
\r
34 //// Public License along with this source; if not, download it ////
\r
35 //// from http://www.opencores.org/lgpl.shtml ////
\r
37 //////////////////////////////////////////////////////////////////////
\r
39 // CVS Revision History
\r
41 // $Log: MAC_rx_ctrl.v,v $
\r
42 // Revision 1.4 2006/06/25 04:58:56 maverickist
\r
45 // Revision 1.3 2006/01/19 14:07:54 maverickist
\r
46 // verification is complete.
\r
48 // Revision 1.3 2005/12/16 06:44:17 Administrator
\r
49 // replaced tab with space.
\r
50 // passed 9.6k length frame test.
\r
52 // Revision 1.2 2005/12/13 12:15:37 Administrator
\r
55 // Revision 1.1.1.1 2005/12/13 01:51:45 Administrator
\r
59 module MAC_rx_ctrl (
\r
66 //CRC_chk interface
\r
71 //MAC_rx_add_chk interface
\r
74 MAC_rx_add_chk_err ,
\r
78 //flow_control signals
\r
81 //MAC_rx_FF interface
\r
90 Rx_pkt_length_rmon ,
\r
92 Rx_pkt_err_type_rmon ,
\r
103 input [7:0] MRxD ;
\r
105 //CRC_chk interface
\r
108 output [7:0] CRC_data;
\r
110 //MAC_rx_add_chk interface
\r
111 output MAC_add_en ;
\r
112 output [7:0] MAC_add_data;
\r
113 input MAC_rx_add_chk_err ;
\r
115 output broadcast_ptr ;
\r
116 input broadcast_drop ;
\r
117 //flow_control signals
\r
118 output [15:0] pause_quanta ;
\r
119 output pause_quanta_val ;
\r
120 //MAC_rx_FF interface
\r
121 output [7:0] Fifo_data ;
\r
122 output Fifo_data_en ;
\r
123 output Fifo_data_err ;
\r
124 output Fifo_data_drop ;
\r
125 output Fifo_data_end ;
\r
128 output [15:0] Rx_pkt_length_rmon ;
\r
129 output Rx_apply_rmon ;
\r
130 output [2:0] Rx_pkt_err_type_rmon ;
\r
131 output [2:0] Rx_pkt_type_rmon ;
\r
133 input [5:0] RX_IFG_SET ;
\r
134 input [15:0] RX_MAX_LENGTH ;// 1518
\r
135 input [6:0] RX_MIN_LENGTH ;// 64
\r
137 //******************************************************************************
\r
139 //******************************************************************************
\r
140 parameter State_idle =4'd00;
\r
141 parameter State_preamble =4'd01;
\r
142 parameter State_SFD =4'd02;
\r
143 parameter State_data =4'd03;
\r
144 parameter State_checkCRC =4'd04;
\r
145 parameter State_OkEnd =4'd07;
\r
146 parameter State_DropEnd =4'd08;
\r
147 parameter State_ErrEnd =4'd09;
\r
148 parameter State_CRCErrEnd =4'd10;
\r
149 parameter State_FFFullDrop =4'd11;
\r
150 parameter State_FFFullErrEnd =4'd12;
\r
151 parameter State_IFG =4'd13;
\r
152 parameter State_Drop2End =4'd14;
\r
154 parameter Pause_idle =4'd0;
\r
155 parameter Pause_pre_syn =4'd1;
\r
156 parameter Pause_quanta_hi =4'd2;
\r
157 parameter Pause_quanta_lo =4'd3;
\r
158 parameter Pause_syn =4'd4;
\r
160 reg [3:0] Current_state /* synthesis syn_keep=1 */;
\r
161 reg [3:0] Next_state;
\r
162 reg [3:0] Pause_current /* synthesis syn_keep=1 */;
\r
163 reg [3:0] Pause_next;
\r
164 reg [5:0] IFG_counter;
\r
167 reg [7:0] RxD_dl1 ;
\r
169 reg [15:0] Frame_length_counter;
\r
172 reg ProcessingHeader;
\r
173 //reg Fifo_data_en;
\r
174 //reg Fifo_data_err;
\r
175 //reg Fifo_data_drop;
\r
176 //reg Fifo_data_end;
\r
180 reg [2:0] Rx_pkt_err_type_rmon;
\r
182 reg [2:0] Rx_pkt_type_rmon;
\r
183 reg [7:0] pause_quanta_h ;
\r
184 reg [15:0] pause_quanta ;
\r
185 reg pause_quanta_val ;
\r
186 reg pause_quanta_val_tmp;
\r
187 reg pause_frame_ptr ;
\r
188 reg broadcast_ptr ;
\r
189 //******************************************************************************
\r
191 //******************************************************************************
\r
193 always @ (posedge Reset or posedge Clk)
\r
207 always @ (posedge Reset or posedge Clk)
\r
213 //---------------------------------------------------------------------------
\r
214 // Small pre-FIFO (acutally a synchronously clearable shift-register) for
\r
215 // storing the first part of a packet before writing it to the "real" FIFO
\r
216 // in MAC_rx_FF. This allows a packet to be dropped safely if an error
\r
217 // happens in the beginning of a packet (or if the MAC address doesn't pass
\r
218 // the receive filter!)
\r
219 //---------------------------------------------------------------------------
\r
221 reg pre_fifo_data_drop;
\r
222 reg pre_fifo_data_en;
\r
223 reg pre_fifo_data_err;
\r
224 reg pre_fifo_data_end;
\r
225 wire [7:0] pre_fifo_wrdata;
\r
227 reg [8+3-1:0] pre_fifo_element_0;
\r
228 reg [8+3-1:0] pre_fifo_element_1;
\r
229 reg [8+3-1:0] pre_fifo_element_2;
\r
230 reg [8+3-1:0] pre_fifo_element_3;
\r
231 reg [8+3-1:0] pre_fifo_element_4;
\r
232 reg [8+3-1:0] pre_fifo_element_5;
\r
233 reg [8+3-1:0] pre_fifo_element_6;
\r
234 reg [8+3-1:0] pre_fifo_element_7;
\r
235 reg [8+3-1:0] pre_fifo_element_8;
\r
236 reg [8+3-1:0] pre_fifo_element_9;
\r
238 always @( posedge Reset or posedge Clk )
\r
241 pre_fifo_element_0 <= 'b0;
\r
242 pre_fifo_element_1 <= 'b0;
\r
243 pre_fifo_element_2 <= 'b0;
\r
244 pre_fifo_element_3 <= 'b0;
\r
245 pre_fifo_element_4 <= 'b0;
\r
246 pre_fifo_element_5 <= 'b0;
\r
247 pre_fifo_element_6 <= 'b0;
\r
248 pre_fifo_element_7 <= 'b0;
\r
249 pre_fifo_element_8 <= 'b0;
\r
250 pre_fifo_element_9 <= 'b0;
\r
254 if ( pre_fifo_data_drop )
\r
256 pre_fifo_element_0 <= 'b0;
\r
257 pre_fifo_element_1 <= 'b0;
\r
258 pre_fifo_element_2 <= 'b0;
\r
259 pre_fifo_element_3 <= 'b0;
\r
260 pre_fifo_element_4 <= 'b0;
\r
261 pre_fifo_element_5 <= 'b0;
\r
262 pre_fifo_element_6 <= 'b0;
\r
263 pre_fifo_element_7 <= 'b0;
\r
264 pre_fifo_element_8 <= 'b0;
\r
265 pre_fifo_element_9 <= 'b0;
\r
269 pre_fifo_element_0 <= pre_fifo_element_1;
\r
270 pre_fifo_element_1 <= pre_fifo_element_2;
\r
271 pre_fifo_element_2 <= pre_fifo_element_3;
\r
272 pre_fifo_element_3 <= pre_fifo_element_4;
\r
273 pre_fifo_element_4 <= pre_fifo_element_5;
\r
274 pre_fifo_element_5 <= pre_fifo_element_6;
\r
275 pre_fifo_element_6 <= pre_fifo_element_7;
\r
276 pre_fifo_element_7 <= pre_fifo_element_8;
\r
277 pre_fifo_element_8 <= pre_fifo_element_9;
\r
278 pre_fifo_element_9 <= { pre_fifo_data_en,
\r
285 assign Fifo_data = pre_fifo_element_0[7:0];
\r
286 assign Fifo_data_end = pre_fifo_element_0[8];
\r
287 assign Fifo_data_err = pre_fifo_element_0[9];
\r
288 assign Fifo_data_en = pre_fifo_element_0[10];
\r
290 assign CRC_data = pre_fifo_wrdata;
\r
291 assign MAC_add_data = pre_fifo_wrdata;
\r
293 //******************************************************************************
\r
295 //******************************************************************************
\r
297 always @( posedge Reset or posedge Clk )
\r
299 Current_state <= State_idle;
\r
301 Current_state <= Next_state;
\r
304 case (Current_state)
\r
306 if ( Crs_dv&&RxD==8'h55 )
\r
307 Next_state = State_preamble;
\r
309 Next_state = Current_state;
\r
313 Next_state = State_DropEnd;
\r
315 Next_state = State_DropEnd;
\r
316 else if ( RxD==8'hd5 )
\r
317 Next_state = State_SFD;
\r
318 else if ( RxD==8'h55 )
\r
319 Next_state =Current_state;
\r
321 Next_state = State_DropEnd;
\r
325 Next_state = State_DropEnd;
\r
327 Next_state = State_DropEnd;
\r
329 Next_state = State_data;
\r
332 if ( !Crs_dv && !ProcessingHeader && !Too_short && !Too_long )
\r
333 Next_state = State_checkCRC;
\r
334 else if ( !Crs_dv && ProcessingHeader )
\r
335 Next_state = State_Drop2End;
\r
336 else if ( !Crs_dv && (Too_short | Too_long) )
\r
337 Next_state = State_ErrEnd;
\r
338 else if ( Fifo_full )
\r
339 Next_state = State_FFFullErrEnd;
\r
340 else if ( RxErr && ProcessingHeader )
\r
341 Next_state = State_Drop2End;
\r
342 else if ( RxErr || Too_long )
\r
343 Next_state = State_ErrEnd;
\r
344 else if ( MAC_rx_add_chk_err || broadcast_drop )
\r
345 Next_state = State_DropEnd;
\r
347 Next_state = State_data;
\r
351 Next_state = State_CRCErrEnd;
\r
353 Next_state = State_OkEnd;
\r
356 Next_state = State_IFG;
\r
359 Next_state = State_IFG;
\r
362 Next_state = State_IFG;
\r
365 Next_state = State_IFG;
\r
368 Next_state = State_IFG;
\r
370 State_FFFullErrEnd:
\r
371 Next_state = State_FFFullDrop;
\r
375 Next_state =State_IFG;
\r
377 Next_state =Current_state;
\r
380 if ( IFG_counter==RX_IFG_SET-4 ) // Remove some additional time?
\r
381 Next_state = State_idle;
\r
383 Next_state = Current_state;
\r
386 Next_state = State_idle;
\r
389 always @( posedge Reset or posedge Clk )
\r
392 else if ( Current_state!=State_IFG )
\r
395 IFG_counter <= IFG_counter + 1;
\r
397 //******************************************************************************
\r
398 //gen fifo interface signals
\r
399 //******************************************************************************
\r
401 assign pre_fifo_wrdata = RxD_dl1;
\r
403 always @( Current_state )
\r
404 if ( Current_state==State_data )
\r
405 pre_fifo_data_en = 1;
\r
407 pre_fifo_data_en = 0;
\r
409 always @( Current_state )
\r
410 if ( (Current_state==State_ErrEnd ) ||
\r
411 (Current_state==State_OkEnd ) ||
\r
412 (Current_state==State_CRCErrEnd ) ||
\r
413 (Current_state==State_FFFullErrEnd) ||
\r
414 (Current_state==State_DropEnd ) ||
\r
415 (Current_state==State_Drop2End ) )
\r
416 pre_fifo_data_end = 1;
\r
418 pre_fifo_data_end = 0;
\r
420 always @( Current_state )
\r
421 if ( (Current_state==State_ErrEnd ) ||
\r
422 (Current_state==State_CRCErrEnd ) ||
\r
423 (Current_state==State_FFFullErrEnd) ||
\r
424 (Current_state==State_DropEnd ) ||
\r
425 (Current_state==State_Drop2End ) )
\r
426 pre_fifo_data_err = 1;
\r
428 pre_fifo_data_err = 0;
\r
430 always @( Current_state )
\r
431 if ( (Current_state==State_DropEnd ) ||
\r
432 (Current_state==State_Drop2End) )
\r
433 pre_fifo_data_drop = 1;
\r
435 pre_fifo_data_drop = 0;
\r
437 // Drop in main Rx FIFO is no longer supported!
\r
438 assign Fifo_data_drop = 0;
\r
440 //******************************************************************************
\r
441 //CRC_chk interface
\r
442 //******************************************************************************
\r
444 always @(Current_state)
\r
445 if (Current_state==State_data)
\r
450 always @(Current_state)
\r
451 if (Current_state==State_SFD)
\r
456 //******************************************************************************
\r
457 //gen rmon signals
\r
458 //******************************************************************************
\r
459 always @ (posedge Clk or posedge Reset)
\r
461 Frame_length_counter <=0;
\r
462 else if (Current_state==State_SFD)
\r
463 Frame_length_counter <=1;
\r
464 else if (Current_state==State_data)
\r
465 Frame_length_counter <=Frame_length_counter+ 1'b1;
\r
467 always @( Frame_length_counter )
\r
468 if ( Frame_length_counter < 8 )
\r
469 ProcessingHeader = 1;
\r
471 ProcessingHeader = 0;
\r
473 always @ (Frame_length_counter or RX_MIN_LENGTH)
\r
474 if (Frame_length_counter<RX_MIN_LENGTH)
\r
480 if (Frame_length_counter>RX_MAX_LENGTH)
\r
485 assign Rx_pkt_length_rmon = Frame_length_counter-1'b1;
\r
487 reg [2:0] Rx_apply_rmon_reg;
\r
489 always @( posedge Clk or posedge Reset )
\r
492 Rx_apply_rmon <= 0;
\r
493 Rx_apply_rmon_reg <= 'b0;
\r
497 if ( (Current_state==State_OkEnd ) ||
\r
498 (Current_state==State_ErrEnd ) ||
\r
499 (Current_state==State_CRCErrEnd ) ||
\r
500 (Current_state==State_Drop2End ) ||
\r
501 (Current_state==State_FFFullErrEnd) )
\r
502 Rx_apply_rmon <= 1;
\r
504 if ( Rx_apply_rmon_reg[2] )
\r
505 Rx_apply_rmon <= 0;
\r
507 Rx_apply_rmon_reg <= { Rx_apply_rmon_reg[1:0], Rx_apply_rmon };
\r
510 always @ (posedge Clk or posedge Reset)
\r
512 Rx_pkt_err_type_rmon <=0;
\r
513 else if (Current_state==State_CRCErrEnd)
\r
514 Rx_pkt_err_type_rmon <=3'b001 ;//
\r
515 else if (Current_state==State_FFFullErrEnd)
\r
516 Rx_pkt_err_type_rmon <=3'b010 ;//
\r
517 else if ( (Current_state==State_ErrEnd) || (Current_state==State_Drop2End) )
\r
518 Rx_pkt_err_type_rmon <=3'b011 ;//
\r
519 else if(Current_state==State_OkEnd)
\r
520 Rx_pkt_err_type_rmon <=3'b100 ;
\r
524 always @ (posedge Clk or posedge Reset)
\r
526 Rx_pkt_type_rmon <=0;
\r
527 else if (Current_state==State_OkEnd&&pause_frame_ptr)
\r
528 Rx_pkt_type_rmon <=3'b100 ;//
\r
529 else if(Current_state==State_SFD&&Next_state==State_data)
\r
530 Rx_pkt_type_rmon <={1'b0,MRxD[7:6]};
\r
532 always @ (posedge Clk or posedge Reset)
\r
535 else if(Current_state==State_IFG)
\r
537 else if(Current_state==State_SFD&&Next_state==State_data&&MRxD[7:6]==2'b11)
\r
542 //******************************************************************************
\r
543 //MAC add checker signals
\r
544 //******************************************************************************
\r
545 always @ (Frame_length_counter or pre_fifo_data_en)
\r
546 if(Frame_length_counter>=1&&Frame_length_counter<=6)
\r
547 MAC_add_en <=pre_fifo_data_en;
\r
551 //******************************************************************************
\r
552 //flow control signals
\r
553 //******************************************************************************
\r
554 always @ (posedge Clk or posedge Reset)
\r
556 Pause_current <=Pause_idle;
\r
558 Pause_current <=Pause_next;
\r
561 case (Pause_current)
\r
563 if(Current_state==State_SFD)
\r
564 Pause_next =Pause_pre_syn;
\r
566 Pause_next =Pause_current;
\r
568 case (Frame_length_counter)
\r
569 16'd1: if (RxD_dl1==8'h01)
\r
570 Pause_next =Pause_current;
\r
572 Pause_next =Pause_idle;
\r
573 16'd2: if (RxD_dl1==8'h80)
\r
574 Pause_next =Pause_current;
\r
576 Pause_next =Pause_idle;
\r
577 16'd3: if (RxD_dl1==8'hc2)
\r
578 Pause_next =Pause_current;
\r
580 Pause_next =Pause_idle;
\r
581 16'd4: if (RxD_dl1==8'h00)
\r
582 Pause_next =Pause_current;
\r
584 Pause_next =Pause_idle;
\r
585 16'd5: if (RxD_dl1==8'h00)
\r
586 Pause_next =Pause_current;
\r
588 Pause_next =Pause_idle;
\r
589 16'd6: if (RxD_dl1==8'h01)
\r
590 Pause_next =Pause_current;
\r
592 Pause_next =Pause_idle;
\r
593 16'd13: if (RxD_dl1==8'h88)
\r
594 Pause_next =Pause_current;
\r
596 Pause_next =Pause_idle;
\r
597 16'd14: if (RxD_dl1==8'h08)
\r
598 Pause_next =Pause_current;
\r
600 Pause_next =Pause_idle;
\r
601 16'd15: if (RxD_dl1==8'h00)
\r
602 Pause_next =Pause_current;
\r
604 Pause_next =Pause_idle;
\r
605 16'd16: if (RxD_dl1==8'h01)
\r
606 Pause_next =Pause_quanta_hi;
\r
608 Pause_next =Pause_idle;
\r
609 default: Pause_next =Pause_current;
\r
612 Pause_next =Pause_quanta_lo;
\r
614 Pause_next =Pause_syn;
\r
616 if (Current_state==State_IFG)
\r
617 Pause_next =Pause_idle;
\r
619 Pause_next =Pause_current;
\r
621 Pause_next =Pause_idle;
\r
624 always @ (posedge Clk or posedge Reset)
\r
626 pause_quanta_h <=0;
\r
627 else if(Pause_current==Pause_quanta_hi)
\r
628 pause_quanta_h <=RxD_dl1;
\r
630 always @ (posedge Clk or posedge Reset)
\r
633 else if(Pause_current==Pause_quanta_lo)
\r
634 pause_quanta <={pause_quanta_h,RxD_dl1};
\r
636 // The following 2 always blocks are a strange way of holding
\r
637 // pause_quanta_val high for 2 cycles
\r
638 always @ (posedge Clk or posedge Reset)
\r
640 pause_quanta_val_tmp <=0;
\r
641 else if(Current_state==State_OkEnd&&Pause_current==Pause_syn)
\r
642 pause_quanta_val_tmp <=1;
\r
644 pause_quanta_val_tmp <=0;
\r
646 always @ (posedge Clk or posedge Reset)
\r
648 pause_quanta_val <=0;
\r
649 else if(Current_state==State_OkEnd&&Pause_current==Pause_syn||pause_quanta_val_tmp)
\r
650 pause_quanta_val <=1;
\r
652 pause_quanta_val <=0;
\r
654 always @ (posedge Clk or posedge Reset)
\r
656 pause_frame_ptr <=0;
\r
657 else if(Pause_current==Pause_syn)
\r
658 pause_frame_ptr <=1;
\r
660 pause_frame_ptr <=0;
\r