1// 2// Copyright 2011 Ettus Research LLC 3// Copyright 2018 Ettus Research, a National Instruments Company 4// 5// SPDX-License-Identifier: LGPL-3.0-or-later 6// 7 8 9 10 11module simple_gemac_rx 12 (input reset, 13 input GMII_RX_CLK, input GMII_RX_DV, input GMII_RX_ER, input [7:0] GMII_RXD, 14 output rx_clk, output [7:0] rx_data, output reg rx_valid, output rx_error, output reg rx_ack, 15 input [47:0] ucast_addr, input [47:0] mcast_addr, 16 input pass_ucast, input pass_mcast, input pass_bcast, input pass_pause, input pass_all, 17 output reg [15:0] pause_quanta_rcvd, output pause_rcvd, 18 output [31:0] debug ); 19 20 localparam RX_IDLE = 0; 21 localparam RX_PREAMBLE = 1; 22 localparam RX_FRAME = 2; 23 localparam RX_GOODFRAME = 3; 24 localparam RX_DO_PAUSE = 4; 25 localparam RX_ERROR = 5; 26 localparam RX_DROP = 6; 27 28 localparam RX_PAUSE = 16; 29 localparam RX_PAUSE_CHK88 = RX_PAUSE + 5; 30 localparam RX_PAUSE_CHK08 = RX_PAUSE_CHK88 + 1; 31 localparam RX_PAUSE_CHK00 = RX_PAUSE_CHK08 + 1; 32 localparam RX_PAUSE_CHK01 = RX_PAUSE_CHK00 + 1; 33 localparam RX_PAUSE_STORE_MSB = RX_PAUSE_CHK01 + 1; 34 localparam RX_PAUSE_STORE_LSB = RX_PAUSE_STORE_MSB + 1; 35 localparam RX_PAUSE_WAIT_CRC = RX_PAUSE_STORE_LSB + 1; 36 37 reg [7:0] rxd_d1; 38 reg rx_dv_d1, rx_er_d1; 39 assign rx_clk = GMII_RX_CLK; 40 41 always @(posedge rx_clk) 42 begin 43 rx_dv_d1 <= GMII_RX_DV; 44 rx_er_d1 <= GMII_RX_ER; 45 rxd_d1 <= GMII_RXD; 46 end 47 48 reg [7:0] rx_state; 49 wire [7:0] rxd_del; 50 wire rx_dv_del, rx_er_del; 51 reg go_filt; 52 53 wire match_crc; 54 wire clear_crc = rx_state == RX_IDLE; 55 wire calc_crc = (rx_state == RX_FRAME) | rx_state[7:4]==4'h1; 56 57 localparam DELAY = 6; 58 delay_line #(.WIDTH(10)) rx_delay 59 (.clk(rx_clk), .delay(DELAY), .din({rx_dv_d1,rx_er_d1,rxd_d1}),.dout({rx_dv_del,rx_er_del,rxd_del})); 60 61 always @(posedge rx_clk) 62 if(reset) 63 rx_ack <= 0; 64 else 65 rx_ack <= (rx_state == RX_GOODFRAME); 66 67 wire is_ucast, is_bcast, is_mcast, is_pause, is_any_ucast; 68 wire keep_packet = (pass_all & is_any_ucast) | (pass_ucast & is_ucast) | (pass_mcast & is_mcast) | 69 (pass_bcast & is_bcast) | (pass_pause & is_pause); 70 71 assign rx_data = rxd_del; 72 assign rx_error = (rx_state == RX_ERROR); 73 74 always @(posedge rx_clk) 75 if(reset) 76 rx_valid <= 0; 77 else if(keep_packet) 78 rx_valid <= 1; 79 else if((rx_state == RX_IDLE)|(rx_state == RX_ERROR)) 80 rx_valid <= 0; 81 82 address_filter af_ucast (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1), 83 .address(ucast_addr), .match(is_ucast), .done()); 84 address_filter af_mcast (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1), 85 .address(mcast_addr), .match(is_mcast), .done()); 86 address_filter af_bcast (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1), 87 .address(48'hFFFF_FFFF_FFFF), .match(is_bcast), .done()); 88 address_filter af_pause (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1), 89 .address(48'h0180_c200_0001), .match(is_pause), .done()); 90 address_filter_promisc af_promisc (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1), 91 .match(is_any_ucast), .done()); 92 93 always @(posedge rx_clk) 94 go_filt <= (rx_state==RX_PREAMBLE) & (rxd_d1 == 8'hD5); 95 96 reg [15:0] pkt_len_ctr; 97 always @(posedge rx_clk) 98 if(reset |(rx_state == RX_IDLE)) 99 pkt_len_ctr <= 0; 100 else 101 pkt_len_ctr <= pkt_len_ctr + 1; 102 103 localparam MIN_PAUSE_LEN = 71; // 6 104 wire pkt_long_enough = (pkt_len_ctr >= MIN_PAUSE_LEN); 105 always @(posedge rx_clk) 106 if(reset) 107 rx_state <= RX_IDLE; 108 else 109 if(rx_er_d1 & ~((rxd_d1==8'h0F)&(~rx_dv_d1))) //Handle odd-length pkts from Xilinx IP. 110 rx_state <= RX_ERROR; 111 else 112 case(rx_state) 113 RX_IDLE : 114 if(rx_dv_d1) 115 if(rxd_d1 == 8'h55) 116 rx_state <= RX_PREAMBLE; 117 else 118 rx_state <= RX_ERROR; 119 RX_PREAMBLE : 120 if(~rx_dv_d1) 121 rx_state <= RX_ERROR; 122 else if(rxd_d1 == 8'hD5) 123 rx_state <= RX_FRAME; 124 else if(rxd_d1 != 8'h55) 125 rx_state <= RX_ERROR; 126 RX_FRAME : 127 if(is_pause) 128 rx_state <= RX_PAUSE; 129 else if(~rx_dv_d1) 130 if(match_crc) 131 rx_state <= RX_GOODFRAME; 132 else 133 rx_state <= RX_ERROR; 134 RX_PAUSE_CHK88 : 135 if(rxd_d1 != 8'h88) 136 rx_state <= RX_DROP; 137 else 138 rx_state <= RX_PAUSE_CHK08; 139 RX_PAUSE_CHK08 : 140 if(rxd_d1 != 8'h08) 141 rx_state <= RX_DROP; 142 else 143 rx_state <= RX_PAUSE_CHK00; 144 RX_PAUSE_CHK00 : 145 if(rxd_d1 != 8'h00) 146 rx_state <= RX_DROP; 147 else 148 rx_state <= RX_PAUSE_CHK01; 149 RX_PAUSE_CHK01 : 150 if(rxd_d1 != 8'h01) 151 rx_state <= RX_DROP; 152 else 153 rx_state <= RX_PAUSE_STORE_MSB; 154 RX_PAUSE_WAIT_CRC : 155 if(pkt_long_enough) 156 if(match_crc) 157 rx_state <= RX_DO_PAUSE; 158 else 159 rx_state <= RX_DROP; 160 RX_DO_PAUSE : 161 rx_state <= RX_IDLE; 162 RX_GOODFRAME : 163 rx_state <= RX_IDLE; 164 RX_DROP, RX_ERROR : 165 if(~rx_dv_d1) 166 rx_state <= RX_IDLE; 167 default 168 rx_state <= rx_state + 1; 169 endcase // case (rx_state) 170 171 assign pause_rcvd = (rx_state == RX_DO_PAUSE); 172 crc crc_check(.clk(rx_clk),.reset(reset),.clear(clear_crc), 173 .data(rxd_d1),.calc(calc_crc),.crc_out(),.match(match_crc)); 174 175 always @(posedge rx_clk) 176 if(reset) 177 pause_quanta_rcvd <= 0; 178 else if(rx_state == RX_PAUSE_STORE_MSB) 179 pause_quanta_rcvd[15:8] <= rxd_d1; 180 else if(rx_state == RX_PAUSE_STORE_LSB) 181 pause_quanta_rcvd[7:0] <= rxd_d1; 182 183 assign debug = rx_state; 184 185endmodule // simple_gemac_rx 186