Copied wb_1master back from quad radio
[debian/gnuradio] / usrp2 / fpga / simple_gemac / simple_gemac_rx.v
1
2
3 module simple_gemac_rx
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 );
10
11    reg [7:0] rxd_d1;
12    reg rx_dv_d1, rx_er_d1;
13    assign rx_clk     = GMII_RX_CLK;
14    
15    always @(posedge rx_clk)
16      begin
17         rx_dv_d1    <= GMII_RX_DV;
18         rx_er_d1    <= GMII_RX_ER;
19         rxd_d1      <= GMII_RXD;
20      end
21
22    wire [7:0] rxd_del;
23    wire rx_dv_del, rx_er_del;
24    reg go_filt;
25    
26    localparam DELAY  = 6;
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}));
29
30    always @(posedge rx_clk)
31      if(reset)
32        rx_ack      <= 0;
33      else
34        rx_ack <= (rx_state == RX_GOODFRAME);
35
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;
39    
40    reg [7:0] rx_state;
41    assign rx_data   = rxd_del;
42    assign rx_error  = (rx_state == RX_ERROR);
43
44    always @(posedge rx_clk)
45      if(reset)
46        rx_valid <= 0;
47      else if(keep_packet)
48        rx_valid <= 1;
49      else if((rx_state == RX_IDLE)|(rx_state == RX_ERROR))
50        rx_valid <= 0;
51    
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());
60
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;
68
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;
77    
78    
79    always @(posedge rx_clk)
80      go_filt                     <= (rx_state==RX_PREAMBLE) & (rxd_d1 == 8'hD5);
81
82    reg [15:0] pkt_len_ctr;
83    always @(posedge rx_clk)
84      if(reset |(rx_state == RX_IDLE))
85        pkt_len_ctr      <= 0;
86      else
87        pkt_len_ctr      <= pkt_len_ctr + 1;
88
89    localparam MIN_PAUSE_LEN = 71;  // 6
90    wire pkt_long_enough  = (pkt_len_ctr >= MIN_PAUSE_LEN);
91    always @(posedge rx_clk)
92      if(reset)
93        rx_state         <= RX_IDLE;
94      else
95        if(rx_er_d1) // | (~pkt_long_enough & ~rx_dv_d1) & (rx_state != RX_IDLE))
96          rx_state       <= RX_ERROR;
97        else
98          case(rx_state)
99            RX_IDLE :
100              if(rx_dv_d1)
101                if(rxd_d1 == 8'h55)
102                  rx_state   <= RX_PREAMBLE;
103                else
104                  rx_state   <= RX_ERROR;
105            RX_PREAMBLE :
106              if(~rx_dv_d1)
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;
112            RX_FRAME :
113              if(is_pause)
114                rx_state <= RX_PAUSE;
115              else if(~rx_dv_d1)
116                if(match_crc)
117                  rx_state <= RX_GOODFRAME;
118                else
119                  rx_state <= RX_ERROR;
120            RX_PAUSE_CHK88 :
121              if(rxd_d1 != 8'h88)
122                rx_state <= RX_DROP;
123              else
124                rx_state <= RX_PAUSE_CHK08;
125            RX_PAUSE_CHK08 :
126              if(rxd_d1 != 8'h08)
127                rx_state <= RX_DROP;
128              else
129                rx_state <= RX_PAUSE_CHK00;
130            RX_PAUSE_CHK00 :
131              if(rxd_d1 != 8'h00)
132                rx_state <= RX_DROP;
133              else
134                rx_state <= RX_PAUSE_CHK01;
135            RX_PAUSE_CHK01 :
136              if(rxd_d1 != 8'h01)
137                rx_state <= RX_DROP;
138              else
139                rx_state <= RX_PAUSE_STORE_MSB;
140            RX_PAUSE_WAIT_CRC :
141              if(pkt_long_enough)
142                if(match_crc)
143                  rx_state <= RX_DO_PAUSE;
144                else
145                  rx_state <= RX_DROP;
146            RX_DO_PAUSE :
147              rx_state <= RX_IDLE;
148            RX_GOODFRAME :
149              rx_state <= RX_IDLE;
150            RX_DROP, RX_ERROR :
151              if(~rx_dv_d1)
152                rx_state <= RX_IDLE;
153            default
154              rx_state <= rx_state + 1;
155          endcase // case (rx_state)
156
157    assign pause_rcvd = (rx_state == RX_DO_PAUSE);
158    wire match_crc;
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));
163
164    always @(posedge rx_clk)
165      if(reset)
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;
171    
172    assign rx_clk          = GMII_RX_CLK;
173    
174 endmodule // simple_gemac_rx