4 (input clk125, input reset,
5 input GMII_RX_CLK, input GMII_RX_DV, input GMII_RX_ER, input [7:0] GMII_RXD,
6 output rx_clk, output [7:0] rx_data, output reg rx_valid, output rx_error, output reg rx_ack,
7 input [47:0] ucast_addr, input [47:0] mcast_addr,
8 input pass_ucast, input pass_mcast, input pass_bcast, input pass_pause, input pass_all,
9 output reg [15:0] pause_quanta_rcvd, output pause_rcvd );
12 reg rx_dv_d1, rx_er_d1;
13 assign rx_clk = GMII_RX_CLK;
15 always @(posedge rx_clk)
17 rx_dv_d1 <= GMII_RX_DV;
18 rx_er_d1 <= GMII_RX_ER;
23 wire rx_dv_del, rx_er_del;
27 delay_line #(.WIDTH(10)) rx_delay
28 (.clk(rx_clk), .delay(DELAY), .din({rx_dv_d1,rx_er_d1,rxd_d1}),.dout({rx_dv_del,rx_er_dl,rxd_del}));
30 always @(posedge rx_clk)
34 rx_ack <= (rx_state == RX_GOODFRAME);
36 wire is_ucast, is_bcast, is_mcast, is_pause;
37 wire keep_packet = (pass_ucast & is_ucast) | (pass_mcast & is_mcast) |
38 (pass_bcast & is_bcast) | (pass_pause & is_pause) | pass_all;
41 assign rx_data = rxd_del;
42 assign rx_error = (rx_state == RX_ERROR);
44 always @(posedge rx_clk)
49 else if((rx_state == RX_IDLE)|(rx_state == RX_ERROR))
52 address_filter af_ucast (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1),
53 .address(ucast_addr), .match(is_ucast), .done());
54 address_filter af_mcast (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1),
55 .address(mcast_addr), .match(is_mcast), .done());
56 address_filter af_bcast (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1),
57 .address(48'hFFFF_FFFF_FFFF), .match(is_bcast), .done());
58 address_filter af_pause (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1),
59 .address(48'h0180_c200_0001), .match(is_pause), .done());
61 localparam RX_IDLE = 0;
62 localparam RX_PREAMBLE = 1;
63 localparam RX_FRAME = 2;
64 localparam RX_GOODFRAME = 3;
65 localparam RX_DO_PAUSE = 4;
66 localparam RX_ERROR = 5;
67 localparam RX_DROP = 6;
69 localparam RX_PAUSE = 16;
70 localparam RX_PAUSE_CHK88 = RX_PAUSE + 5;
71 localparam RX_PAUSE_CHK08 = RX_PAUSE_CHK88 + 1;
72 localparam RX_PAUSE_CHK00 = RX_PAUSE_CHK08 + 1;
73 localparam RX_PAUSE_CHK01 = RX_PAUSE_CHK00 + 1;
74 localparam RX_PAUSE_STORE_MSB = RX_PAUSE_CHK01 + 1;
75 localparam RX_PAUSE_STORE_LSB = RX_PAUSE_STORE_MSB + 1;
76 localparam RX_PAUSE_WAIT_CRC = RX_PAUSE_STORE_LSB + 1;
79 always @(posedge rx_clk)
80 go_filt <= (rx_state==RX_PREAMBLE) & (rxd_d1 == 8'hD5);
82 reg [15:0] pkt_len_ctr;
83 always @(posedge rx_clk)
84 if(reset |(rx_state == RX_IDLE))
87 pkt_len_ctr <= pkt_len_ctr + 1;
89 localparam MIN_PAUSE_LEN = 71; // 6
90 wire pkt_long_enough = (pkt_len_ctr >= MIN_PAUSE_LEN);
91 always @(posedge rx_clk)
95 if(rx_er_d1) // | (~pkt_long_enough & ~rx_dv_d1) & (rx_state != RX_IDLE))
102 rx_state <= RX_PREAMBLE;
104 rx_state <= RX_ERROR;
107 rx_state <= RX_ERROR;
108 else if(rxd_d1 == 8'hD5)
109 rx_state <= RX_FRAME;
110 else if(rxd_d1 != 8'h55)
111 rx_state <= RX_ERROR;
114 rx_state <= RX_PAUSE;
117 rx_state <= RX_GOODFRAME;
119 rx_state <= RX_ERROR;
124 rx_state <= RX_PAUSE_CHK08;
129 rx_state <= RX_PAUSE_CHK00;
134 rx_state <= RX_PAUSE_CHK01;
139 rx_state <= RX_PAUSE_STORE_MSB;
143 rx_state <= RX_DO_PAUSE;
154 rx_state <= rx_state + 1;
155 endcase // case (rx_state)
157 assign pause_rcvd = (rx_state == RX_DO_PAUSE);
159 wire clear_crc = rx_state == RX_IDLE;
160 wire calc_crc = (rx_state == RX_FRAME) | rx_state[7:4]==4'h1;
161 crc crc_check(.clk(rx_clk),.reset(reset),.clear(clear_crc),
162 .data(rxd_d1),.calc(calc_crc),.crc_out(),.match(match_crc));
164 always @(posedge rx_clk)
166 pause_quanta_rcvd <= 0;
167 else if(rx_state == RX_PAUSE_STORE_MSB)
168 pause_quanta_rcvd[15:8] <= rxd_d1;
169 else if(rx_state == RX_PAUSE_STORE_LSB)
170 pause_quanta_rcvd[7:0] <= rxd_d1;
172 assign rx_clk = GMII_RX_CLK;
174 endmodule // simple_gemac_rx