OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [enetpackets.v] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    enetpackets.v
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7
// Purpose:     To communicate between the Ethernet PHY, and thus to coordinate
8
//              (and direct/arrange for) the transmission, and receiption, of 
9
//      packets via the Ethernet interface.
10
//
11
//
12
//      Using this interface requires four registers to be properly configured.
13
//      These are the receive and transmit control registers, as well as the
14
//      hardware MAC register(s).
15
//
16
//
17
//      To use the interface, after the system has been alive for a full
18
//      second, drop the reset line.  Do this by writing to the transmit
19
//      register a value with zero length, zero command, and the RESET bit as
20
//      zero.
21
//
22
//      This interface is big endian.  Therefore, the most significant byte
23
//      in each word will be transmitted first.  If the interface references
24
//      a number of octets less than a multiple of four, the least significant
25
//      octets in the last word will not be transmitted/were not received.
26
//
27
//      To transmit,
28
//              1. set the source MAC address in the two mac registers.  These
29
//                      are persistent across packets, so once set (whether for
30
//                      transmit or receive) they need not be set again.
31
//              2. Fill the packet buffer with your packet.  In general, the
32
//                      first 32-bit word must contain the hardware MAC address
33
//                      of your destination, spilling into the 16-bits of the
34
//                      next word.  The bottom 16-bits of that second word
35
//                      must also contain the EtherType (0x0800 for IP,
36
//                      0x0806 for ARP, etc.)  The third word will begin your
37
//                      user data.
38
//              3. Write a 0x4000 plus the number of bytes in your buffer to
39
//                      the transmit command register.  If your packet is less
40
//                      than 64 bytes, it will automatically be paddedd to 64
41
//                      bytes before being sent.
42
//              4. Once complete, the controller will raise an interrupt
43
//                      line to note that the interface is idle.
44
//      OPTIONS:
45
//              You can turn off the internal insertion of the hardware source
46
//              MAC by turning the respective bit on in the transmit command
47
//              register.  If you do this, half of the second word and all the
48
//              third word must contain the hardware MAC.  The third word must
49
//              contain the EtherType, both in the top and bottom sixteen bits.
50
//              The Fourth word will begin user data.
51
//
52
//              You can also turn off the automatic insertion of the FCS, or
53
//              ethernet CRC.  Doing this means that you will need to both 
54
//              guarantee for yourself that the packet has a minimum of 64
55
//              bytes in length, and that the last four bytes contain the
56
//              CRC.
57
//
58
//      To Receive: 
59
//              The receiver is always on.  Receiving is really just a matter
60
//              of pulling the received packet from the interface, and resetting
61
//              the interface for the next packet.
62
//
63
//              If the VALID bit is set, the receive interface has a valid
64
//              packet within it.  Write a zero to this bit to reset the
65
//              interface to accept the next packet.
66
//
67
//              If a packet with a CRC error is received, the CRC error bit
68
//              will be set.  Likewise if a packet has been missed, usually 
69
//              because the buffer was full when it started, the miss bit
70
//              will be set.  Finally, if an error occurrs while receiving
71
//              a packet, the error bit will be set.  These bits may be cleared
72
//              by writing a one to each of them--something that may be done
73
//              when clearing the interface for the next packet.
74
//      OPTIONS:
75
//              The same options that apply to the transmitter apply to the
76
//              receiver:
77
//
78
//              HWMAC.  If the hardware MAC is turned on, the receiver will
79
//              only accept packets to either 1) our network address, or 2)
80
//              a broadcast address.  Further, the first two words will be
81
//              adjusted to contain the source MAC and the EtherType, so that
82
//              the user information begins on the third word.  If this feature
83
//              is turned off, all packets will be received, and the first
84
//              three words will contain the destination and then source
85
//              MAC.  The fourth word will contain the EtherType in the lowest,
86
//              16 bits, meaning user data will begin on the fifth word.
87
//
88
//              HWCRC.  If the HWCRC is turned on, the receiver will only
89
//              detect packets that pass their CRC check.  Further, the packet
90
//              length (always in octets) will not include the CRC.  However,
91
//              the CRC will still be left/written to packet memory either way.
92
//
93
// Registers:
94
//      0        Receiver control
95
//              13'h0   |CRCerr|MISS|ERR|BUSY|VALID |14-bit length (in octets)|
96
//
97
//      1       Transmitter control
98
//              14'h0   |NET_RST|SW-MAC-CHK|SW-CRCn|BUSY/CMD | 14 bit length(in octets)|
99
//
100
//      2       // MAC address (high) ??
101
//      3       // MAC address (low)  ??
102
//      4       Number of receive packets missed (buffer was full)
103
//      5       Number of receive packets ending in error
104
//      6       Number of receive packets with invalid CRCs
105
//      7       (Number of transmit collisions ??)
106
//
107
// Creator:     Dan Gisselquist, Ph.D.
108
//              Gisselquist Technology, LLC
109
//
110
////////////////////////////////////////////////////////////////////////////////
111
//
112
// Copyright (C) 2016, Gisselquist Technology, LLC
113
//
114
// This program is free software (firmware): you can redistribute it and/or
115
// modify it under the terms of  the GNU General Public License as published
116
// by the Free Software Foundation, either version 3 of the License, or (at
117
// your option) any later version.
118
//
119
// This program is distributed in the hope that it will be useful, but WITHOUT
120
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
121
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
122
// for more details.
123
//
124
// You should have received a copy of the GNU General Public License along
125
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
126
// target there if the PDF file isn't present.)  If not, see
127
// <http://www.gnu.org/licenses/> for a copy.
128
//
129
// License:     GPL, v3, as defined and found on www.gnu.org,
130
//              http://www.gnu.org/licenses/gpl.html
131
//
132
//
133
////////////////////////////////////////////////////////////////////////////////
134
//
135
//
136
// `define      RX_SYNCHRONOUS_WITH_WB_CLK
137
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
138
`define RXCLK   i_wb_clk
139
`else
140
`define RXCLK   i_net_rx_clk
141
`endif
142
// `define      TX_SYNCHRONOUS_WITH_WB_CLK
143
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
144
`define TXCLK   i_wb_clk
145
`else
146
`define TXCLK   i_net_tx_clk
147
`endif
148
module  enetpackets(i_wb_clk, i_reset,
149
        i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
150
                o_wb_ack, o_wb_stall, o_wb_data,
151
        //
152
        o_net_reset_n,
153
        i_net_rx_clk, i_net_col, i_net_crs, i_net_dv, i_net_rxd, i_net_rxerr,
154
        i_net_tx_clk, o_net_tx_en, o_net_txd,
155
        //
156
        o_rx_int, o_tx_int,
157
        //
158
        o_debug
159
        );
160
        parameter       MEMORY_ADDRESS_WIDTH = 12; // Log_2 octet width:11..14
161
        localparam      MAW =((MEMORY_ADDRESS_WIDTH>14)? 14: // width of words
162
                        ((MEMORY_ADDRESS_WIDTH<11)? 11:MEMORY_ADDRESS_WIDTH))-2;
163
        input                   i_wb_clk, i_reset;
164
        //
165
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
166
        input   [(MAW+1):0]      i_wb_addr; // 1-bit for ctrl/data, 1 for tx/rx
167
        input   [31:0]           i_wb_data;
168
        //
169
        output  reg             o_wb_ack;
170
        output  wire            o_wb_stall;
171
        output  reg     [31:0]   o_wb_data;
172
        //
173
        output  reg             o_net_reset_n;
174
        //
175
        input                   i_net_rx_clk, i_net_col, i_net_crs, i_net_dv;
176
        input           [3:0]    i_net_rxd;
177
        input                   i_net_rxerr;
178
        //
179
        input                   i_net_tx_clk;
180
        output  wire            o_net_tx_en;
181
        output  wire    [3:0]    o_net_txd;
182
        //
183
        output  wire            o_rx_int, o_tx_int;
184
        //
185
        output  wire    [31:0]   o_debug;
186
 
187
        reg     wr_ctrl;
188
        reg     [2:0]    wr_addr;
189
        reg     [31:0]   wr_data;
190
        always @(posedge i_wb_clk)
191
        begin
192
                wr_ctrl<=((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b00));
193
                wr_addr <= i_wb_addr[2:0];
194
                wr_data <= i_wb_data;
195
        end
196
 
197
        reg     [31:0]   txmem   [0:((1<<MAW)-1)];
198
        reg     [31:0]   rxmem   [0:((1<<MAW)-1)];
199
 
200
        reg     [(MAW+1):0]      tx_len;
201
 
202
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
203
        wire    [(MAW+1):0]      rx_len;
204
`else
205
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      rx_len;
206
`endif
207
 
208
        reg     tx_cmd, tx_cancel;
209
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
210
        wire    tx_busy, tx_complete;
211
`else
212
        reg     tx_busy, tx_complete;
213
`endif
214
        reg     config_hw_crc, config_hw_mac;
215
        reg     rx_crcerr, rx_err, rx_miss, rx_clear;
216
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
217
        wire    rx_valid, rx_busy;
218
`else
219
        reg     rx_valid, rx_busy;
220
`endif
221
        reg     rx_wb_valid, pre_ack, pre_cmd, tx_nzero_cmd;
222
        reg     [4:0]    caseaddr;
223
        reg     [31:0]   rx_wb_data, tx_wb_data;
224
        reg             rx_err_stb, rx_miss_stb, rx_crc_stb;
225
 
226
        reg     [47:0]   hw_mac;
227
        reg             p_rx_clear;
228
        reg     [7:0]    clear_pipe;
229
 
230
        initial config_hw_crc = 0;
231
        initial config_hw_mac = 0;
232
        initial o_net_reset_n = 1'b0;
233
        initial tx_cmd    = 1'b0;
234
        initial tx_cancel = 1'b0;
235
        initial rx_crcerr = 1'b0;
236
        initial rx_err    = 1'b0;
237
        initial rx_miss   = 1'b0;
238
        initial rx_clear  = 1'b0;
239
        always @(posedge i_wb_clk)
240
        begin
241
                // if (i_wb_addr[(MAW+1):MAW] == 2'b10)
242
                        // Writes to rx memory not allowed here
243
                if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11))
244
                        txmem[i_wb_addr[(MAW-1):0]] <= i_wb_data;
245
 
246
                // Set the err bits on these conditions (filled out below)
247
                if (rx_err_stb)
248
                        rx_err <= 1'b1;
249
                if (rx_miss_stb)
250
                        rx_miss <= 1'b1;
251
                if (rx_crc_stb)
252
                        rx_crcerr <= 1'b1;
253
 
254
                if ((wr_ctrl)&&(wr_addr==3'b000))
255
                begin // RX command register
256
                        rx_crcerr<= (!wr_data[18])&&(!rx_crcerr);
257
                        rx_err   <= (!wr_data[17])&&(!rx_err);
258
                        rx_miss  <= (!wr_data[16])&&(!rx_miss);
259
                        // busy bit cannot be written to
260
                        rx_clear <= rx_clear || (wr_data[14]);
261
                        // Length bits are cleared when invalid
262
                end else if (!rx_valid)
263
                        rx_clear <= 1'b0;
264
 
265
                clear_pipe <= { clear_pipe[6:0], rx_clear };
266
                p_rx_clear <= |clear_pipe;
267
 
268
                if ((tx_busy)||(tx_cancel))
269
                        tx_cmd <= 1'b0;
270
                if (!tx_busy)
271
                        tx_cancel <= 1'b0;
272
                pre_cmd <= 1'b0;
273
                if ((wr_ctrl)&&(wr_addr==3'b001))
274
                begin // TX command register
275
 
276
                        // Reset bit must be held down to be valid
277
                        o_net_reset_n <= (!wr_data[17]);
278
                        config_hw_mac <= (!wr_data[16]);
279
                        config_hw_crc <= (!wr_data[15]);
280
                        pre_cmd <= (wr_data[14]);
281
                        tx_cancel <= (tx_busy)&&(!wr_data[14]);
282
//              14'h0   | SW-CRCn |NET-RST|BUSY/CMD | 14 bit length(in octets)|
283
                        tx_len <= wr_data[(MAW+1):0];
284
                end
285
                tx_nzero_cmd <= ((pre_cmd)&&(tx_len != 0));
286
                if (tx_nzero_cmd)
287
                        tx_cmd <= 1'b1;
288
                if (!o_net_reset_n)
289
                        tx_cancel <= 1'b1;
290
                if (!o_net_reset_n)
291
                        tx_cmd <= 1'b0;
292
 
293
                if ((wr_ctrl)&&(wr_addr==3'b010))
294
                        hw_mac[47:32] <= wr_data[15:0];
295
                if ((wr_ctrl)&&(wr_addr==3'b011))
296
                        hw_mac[31:0] <= wr_data[31:0];
297
        end
298
 
299
        wire    [31:0]   w_tx_ctrl;
300
        wire    [31:0]   w_rx_ctrl;
301
        wire    [3:0]    w_maw;
302
 
303
        assign  w_maw = MAW+2; // Number of bits in the packet length field
304
        assign  w_rx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}}, rx_crcerr, rx_err,
305
                        rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
306
                        {(14-MAW-2){1'b0}}, rx_len };
307
 
308
        assign  w_tx_ctrl = { 4'h0, w_maw, {(24-18){1'b0}},
309
                        !o_net_reset_n,!config_hw_mac,
310
                        !config_hw_crc, tx_busy,
311
                                {(14-MAW-2){1'b0}}, tx_len };
312
 
313
        reg     [31:0]   counter_rx_miss, counter_rx_err, counter_rx_crc;
314
        initial counter_rx_miss = 32'h00;
315
        initial counter_rx_err  = 32'h00;
316
        initial counter_rx_crc  = 32'h00;
317
 
318
        // Reads from the bus ... always done, regardless of i_wb_we
319
        always @(posedge i_wb_clk)
320
        begin
321
                rx_wb_data  <= rxmem[i_wb_addr[(MAW-1):0]];
322
                rx_wb_valid <= (i_wb_addr[(MAW-1):0] <= { rx_len[(MAW+1):2] });
323
                tx_wb_data  <= txmem[i_wb_addr[(MAW-1):0]];
324
                pre_ack <= i_wb_stb;
325
                caseaddr <= {i_wb_addr[(MAW+1):MAW], i_wb_addr[2:0] };
326
 
327
                casez(caseaddr)
328
                5'h00: o_wb_data <= w_rx_ctrl;
329
                5'h01: o_wb_data <= w_tx_ctrl;
330
                5'h02: o_wb_data <= {16'h00, hw_mac[47:32] };
331
                5'h03: o_wb_data <= hw_mac[31:0];
332
                5'h04: o_wb_data <= counter_rx_miss;
333
                5'h05: o_wb_data <= counter_rx_err;
334
                5'h06: o_wb_data <= counter_rx_crc;
335
                5'h07: o_wb_data <= 32'h00;
336
                5'b10???: o_wb_data <= (rx_wb_valid)?rx_wb_data:32'h00;
337
                5'b11???: o_wb_data <= tx_wb_data;
338
                default: o_wb_data <= 32'h00;
339
                endcase
340
                o_wb_ack <= pre_ack;
341
        end
342
 
343
        /////////////////////////////////////
344
        //
345
        //
346
        //
347
        // Transmitter code
348
        //
349
        //
350
        //
351
        /////////////////////////////////////
352
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
353
        reg     [(MAW+1):0]      n_tx_len;
354
        wire    n_tx_cmd, n_tx_cancel;
355
        assign  n_tx_cmd = tx_cmd;
356
        assign  n_tx_cancel = tx_cancel;
357
`else
358
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      n_tx_len;
359
        (* ASYNC_REG = "TRUE" *) reg r_tx_cmd, r_tx_cancel;
360
        reg     n_tx_cmd, n_tx_cancel;
361
        always @(posedge `TXCLK)
362
        begin
363
                r_tx_cmd    <= tx_cmd;
364
                r_tx_cancel <= tx_cancel;
365
 
366
                n_tx_cmd    <= r_tx_cmd;
367
                n_tx_cancel <= r_tx_cancel;
368
        end
369
`endif
370
 
371
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
372
        reg     last_tx_clk, tx_clk_stb;
373
        (* ASYNC_REG = "TRUE" *) reg    r_tx_clk;
374
        always @(posedge i_wb_clk)
375
                r_tx_clk <= i_net_tx_clk;
376
        always @(posedge i_wb_clk)
377
                last_tx_clk <= r_tx_clk;
378
        always @(posedge i_wb_clk)
379
                tx_clk_stb <= (r_tx_clk)&&(!last_tx_clk);
380
`else
381
        wire    tx_clk_stb, last_tx_clk;
382
 
383
        assign  tx_clk_stb = 1'b1;
384
        assign  last_tx_clk= 1'b0;
385
`endif
386
 
387
        wire    [(MAW+2):0]      rd_tx_addr;
388
        assign  rd_tx_addr = (n_tx_addr+8);
389
 
390
        reg     [(MAW+2):0]      n_tx_addr;
391
        reg     [31:0]           n_tx_data, n_next_tx_data;
392
        reg                     n_tx_complete;
393
`ifdef  TX_SYNCHRONOUSH_WITH_WB
394
        reg             n_tx_busy, n_tx_config_hw_mac, n_tx_config_hw_crc;
395
`else
396
        (* ASYNC_REG = "TRUE" *) reg    n_tx_busy,
397
                                        n_tx_config_hw_mac, n_tx_config_hw_crc;
398
`endif
399
        (* ASYNC_REG = "TRUE" *) reg r_tx_crs;
400
        reg     n_tx_crs;
401
        always @(posedge `TXCLK)
402
        begin
403
                r_tx_crs <= i_net_crs;
404
                n_tx_crs <= r_tx_crs;
405
        end
406
 
407
        wire    [31:0]   n_remap_tx_data;
408
        assign  n_remap_tx_data[31:28] = n_next_tx_data[27:24];
409
        assign  n_remap_tx_data[27:24] = n_next_tx_data[31:28];
410
        assign  n_remap_tx_data[23:20] = n_next_tx_data[19:16];
411
        assign  n_remap_tx_data[19:16] = n_next_tx_data[23:20];
412
        assign  n_remap_tx_data[15:12] = n_next_tx_data[11: 8];
413
        assign  n_remap_tx_data[11: 8] = n_next_tx_data[15:12];
414
        assign  n_remap_tx_data[ 7: 4] = n_next_tx_data[ 3: 0];
415
        assign  n_remap_tx_data[ 3: 0] = n_next_tx_data[ 7: 4];
416
 
417
        reg             r_txd_en;
418
        reg     [3:0]    r_txd;
419
        initial r_txd_en = 1'b0;
420
 
421
        initial n_tx_busy  = 1'b0;
422
        initial n_tx_complete  = 1'b0;
423
        always @(posedge `TXCLK)
424
        begin
425
                if (tx_clk_stb)
426
                begin
427
                        // While this operation doesn't strictly need to 
428
                        // operate *only* if tx_clk_stb is true, by doing so
429
                        // our code stays compatible with both synchronous
430
                        // to wishbone and synchronous to tx clk options.
431
                        n_next_tx_data  <= txmem[(!n_tx_busy)?0:rd_tx_addr[(MAW+2):3]];
432
                end
433
 
434
 
435
                if (n_tx_cancel)
436
                        n_tx_busy <= 1'b0;
437
                else if (!n_tx_busy)
438
                        n_tx_busy <= (n_tx_cmd)&&(!i_net_crs);
439
                else if (n_tx_addr >= { n_tx_len,1'b0 })
440
                        n_tx_busy     <= 1'b0;
441
 
442
                if (!n_tx_busy)
443
                begin
444
                        n_tx_addr  <= {{(MAW+2){1'b0}},1'b1};
445
                        n_tx_data <= { n_remap_tx_data[27:0], 4'h0 };
446
                        if (n_tx_complete)
447
                                n_tx_complete <= (!n_tx_cmd);
448
                        r_txd_en <= (!n_tx_complete)&&(n_tx_cmd)&&(!i_net_crs);
449
                        r_txd  <= n_remap_tx_data[31:28];
450
                        n_tx_config_hw_mac <= config_hw_mac;
451
                        n_tx_config_hw_crc <= config_hw_crc;
452
                        n_tx_len <= tx_len;
453
                end else if (!r_txd_en)
454
                        r_txd_en <= (!n_tx_crs);
455
                else if (tx_clk_stb) begin
456
                        n_tx_addr <= n_tx_addr + 1'b1;
457
                        r_txd <= n_tx_data[31:28];
458
                        if (n_tx_addr[2:0] == 3'h7)
459
                                n_tx_data <= n_remap_tx_data;
460
                        else
461
                                n_tx_data <= { n_tx_data[27:0], 4'h0 };
462
                        if (n_tx_addr >= { n_tx_len,1'b0 })
463
                                n_tx_complete <= 1'b1;
464
                        r_txd_en <= (n_tx_addr < { n_tx_len, 1'b0 });
465
                end
466
        end
467
 
468
        wire    n_tx_config_hw_preamble;
469
        assign  n_tx_config_hw_preamble = 1'b1;
470
 
471
        wire            w_macen, w_paden, w_txcrcen;
472
        wire    [3:0]    w_macd,  w_padd,  w_txcrcd;
473
 
474
`ifndef TX_BYPASS_HW_MAC
475
        addemac txmaci(`TXCLK, tx_clk_stb, n_tx_config_hw_mac, n_tx_cancel,
476
                                hw_mac, r_txd_en, r_txd, w_macen, w_macd);
477
`else
478
        assign  w_macen = r_txd_en;
479
        assign  w_macd  = r_txd;
480
`endif
481
 
482
`ifndef TX_BYPASS_PADDING
483
        addepad txpadi(`TXCLK, tx_clk_stb, 1'b1, n_tx_cancel,
484
                                w_macen, w_macd, w_paden, w_padd);
485
`else
486
        assign  w_paden = w_macen;
487
        assign  w_padd  = w_macd;
488
`endif
489
 
490
`ifndef TX_BYPASS_HW_CRC
491
        addecrc txcrci(`TXCLK, tx_clk_stb, n_tx_config_hw_crc, n_tx_cancel,
492
                                w_paden, w_padd, w_txcrcen, w_txcrcd);
493
`else
494
        assign  w_txcrcen = w_macen;
495
        assign  w_txcrcd  = w_macd;
496
`endif
497
 
498
        addepreamble txprei(`TXCLK, tx_clk_stb, n_tx_config_hw_preamble, n_tx_cancel,
499
                                w_txcrcen, w_txcrcd, o_net_tx_en, o_net_txd);
500
 
501
`ifdef  TX_SYNCRONOUS_WITH_WB_CLK
502
        assign  tx_busy = n_tx_busy;
503
        assign  tx_complete = n_tx_complete;
504
`else
505
        (* ASYNC_REG = "TRUE" *) reg    r_tx_busy, r_tx_complete;
506
        always @(posedge i_wb_clk)
507
        begin
508
                r_tx_busy <= (n_tx_busy || o_net_tx_en || w_txcrcen || w_macen || w_paden);
509
                tx_busy <= r_tx_busy;
510
 
511
                r_tx_complete <= n_tx_complete;
512
                tx_busy <= r_tx_busy;
513
        end
514
`endif
515
 
516
 
517
 
518
 
519
 
520
        /////////////////////////////////////
521
        //
522
        //
523
        //
524
        // Receiver code
525
        //
526
        //
527
        //
528
        /////////////////////////////////////
529
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
530
        reg     last_rx_clk, rx_clk_stb;
531
        (* ASYNC_REG="TRUE" *) reg r_rx_clk;
532
        always @(posedge i_wb_clk)
533
                r_rx_clk <= i_net_rx_clk;
534
        always @(posedge i_wb_clk)
535
                last_rx_clk <= r_rx_clk;
536
        always @(posedge i_wb_clk)
537
                rx_clk_stb <= (r_rx_clk)&&(!last_rx_clk);
538
 
539
`else
540
        wire    rx_clk_stb, last_rx_clk;
541
        assign  rx_clk_stb = 1'b1;
542
        assign  last_rx_clk = 1'b0;
543
`endif
544
 
545
 
546
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
547
        wire    n_rx_clear;
548
        reg     n_rx_config_hw_mac, n_rx_config_hw_crc;
549
        assign  n_rx_clear = rx_clear;
550
`else
551
        (* ASYNC_REG = "TRUE" *) reg n_rx_config_hw_mac, n_rx_config_hw_crc;
552
        (* ASYNC_REG = "TRUE" *) reg r_rx_clear;
553
        reg     n_rx_clear;
554
        always @(posedge `RXCLK)
555
        begin
556
                r_rx_clear <= (p_rx_clear)||(!o_net_reset_n);
557
                n_rx_clear <= r_rx_clear;
558
        end
559
`endif
560
 
561
 
562
        reg             n_rx_net_err;
563
        wire            w_npre,  w_rxmin,  w_rxcrc,  w_rxmac,  w_rxip;
564
        wire    [3:0]    w_npred, w_rxmind, w_rxcrcd, w_rxmacd, w_rxipd;
565
        wire            w_minerr, w_rxcrcerr, w_macerr, w_broadcast, w_iperr;
566
`ifndef RX_BYPASS_HW_PREAMBLE
567
        rxepreambl rxprei(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
568
                        i_net_dv, i_net_rxd, w_npre, w_npred);
569
`else
570
        assign  w_npre  = i_net_dv;
571
        assign  w_npred = i_net_rxerr;
572
`endif
573
 
574
`ifdef  RX_HW_MINLENGTH
575
        // Insist on a minimum of 64-byte packets
576
        rxeminlen       rxmini(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
577
                        w_npre, w_npred, w_rxmin, w_rxmind, w_minerr);
578
`else
579
        assign  w_rxmin = w_npre;
580
        assign  w_rxmind= w_npred;
581
        assign  w_minerr= 1'b0;
582
`endif
583
 
584
`ifndef RX_BYPASS_HW_CRC
585
        rxecrc  rxcrci(`RXCLK, rx_clk_stb, n_rx_config_hw_crc, (n_rx_net_err),
586
                        w_rxmin, w_rxmind, w_rxcrc, w_rxcrcd, w_rxcrcerr);
587
`else
588
        assign  w_rxcrc   = w_rxmin;
589
        assign  w_rxcrcd  = w_rxmind;
590
        assign  w_rxcrcerr= 1'b0;
591
`endif
592
 
593
`ifndef RX_BYPASS_HW_RMMAC
594
        rxehwmac rxmaci(`RXCLK, rx_clk_stb, n_rx_config_hw_mac, (n_rx_net_err), hw_mac,
595
                        w_rxcrc, w_rxcrcd,
596
                        w_rxmac, w_rxmacd,
597
                        w_macerr, w_broadcast);
598
`else
599
        assign  w_rxmac  = w_rxcrc;
600
        assign  w_rxmacd = w_rxcrcd;
601
`endif
602
 
603
`ifdef  RX_HW_IPCHECK
604
        // Check: if this packet is an IP packet, is the IP header checksum
605
        // valid?
606
`else
607
        assign  w_rxip  = w_rxmac;
608
        assign  w_rxipd = w_rxmacd;
609
        assign  w_iperr = 1'b0;
610
`endif
611
 
612
        wire                    w_rxwr;
613
        wire    [(MAW-1):0]      w_rxaddr;
614
        wire    [31:0]           w_rxdata;
615
        wire    [(MAW+1):0]      w_rxlen;
616
 
617
        rxewrite #(MAW) rxememi(`RXCLK, 1'b1, (n_rx_net_err), w_rxip, w_rxipd,
618
                        w_rxwr, w_rxaddr, w_rxdata, w_rxlen);
619
 
620
        reg     last_rxwr, n_rx_valid, n_rxmiss, n_eop, n_rx_busy, n_rx_crcerr,
621
                n_rx_err, n_rx_broadcast, n_rx_miss;
622
        reg     [(MAW+1):0]      n_rx_len;
623
 
624
        initial n_rx_valid = 1'b0;
625
        initial n_rx_clear = 1'b1;
626
        initial n_rx_miss  = 1'b0;
627
        always @(posedge `RXCLK)
628
        begin
629
                if ((w_rxwr)&&(!n_rx_valid))
630
                        rxmem[w_rxaddr] <= w_rxdata;
631
 
632
                // n_rx_net_err goes true as soon as an error is detected,
633
                // and stays true as long as valid data is coming in
634
                n_rx_net_err <= (i_net_dv)&&((i_net_rxerr)||(i_net_col)
635
                                ||(w_minerr)||(w_macerr)||(w_rxcrcerr)
636
                                ||(n_rx_net_err)
637
                                ||((w_rxwr)&&(n_rx_valid)));
638
 
639
                last_rxwr <= w_rxwr;
640
                n_eop <= (!w_rxwr)&&(last_rxwr)&&(!n_rx_net_err);
641
 
642
                n_rx_busy <= (!n_rx_net_err)&&((i_net_dv)||(w_npre)||(w_rxmin)
643
                        ||(w_rxcrc)||(w_rxmac)||(w_rxip)||(w_rxwr));
644
 
645
                // Oops ... we missed a packet
646
                n_rx_miss <= (n_rx_valid)&&(w_rxwr)||
647
                        ((n_rx_miss)&&(!n_rx_clear));
648
 
649
                n_rx_crcerr <= ((w_rxcrcerr)&&(!n_rx_net_err))
650
                        ||((n_rx_crcerr)&&(!n_rx_clear));
651
 
652
                n_rx_err <= ((n_rx_err)&&(!n_rx_clear))
653
                        ||((i_net_rxerr)||(i_net_col)||(w_minerr));
654
 
655
                n_rx_broadcast <= (w_broadcast)||((n_rx_broadcast)&&(!n_rx_clear));
656
 
657
                if (n_rx_clear)
658
                begin
659
                        n_rx_valid <= 1'b0;
660
                        n_rx_len <= 0;
661
                end else if (n_eop)
662
                begin
663
                        n_rx_valid <= 1'b1;
664
                        n_rx_len   <= w_rxlen - ((n_rx_config_hw_crc)?{{(MAW-1){1'b0}},3'h4}:0);
665
                end
666
                // else n_rx_valid = n_rx_valid;
667
 
668
                if ((!i_net_dv)||(n_rx_clear))
669
                begin
670
                        n_rx_config_hw_mac <= config_hw_mac;
671
                        n_rx_config_hw_crc <= config_hw_crc;
672
                end
673
        end
674
 
675
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
676
        assign  rx_busy  = n_rx_busy;
677
        assign  rx_valid = n_rx_valid;
678
        assign  rx_len   = n_rx_len;
679
`else
680
        reg     r_rx_busy, r_rx_valid;
681
        always @(posedge i_wb_clk)
682
        begin
683
                r_rx_valid <= n_rx_valid;
684
                rx_valid <= r_rx_valid;
685
 
686
                r_rx_busy <= n_rx_busy;
687
                rx_busy <= r_rx_busy;
688
 
689
                rx_len <= n_rx_len;
690
        end
691
 
692
`endif
693
 
694
        reg     [3:0]    rx_err_pipe, rx_miss_pipe, rx_crc_pipe;
695
        always @(posedge i_wb_clk)
696
        begin
697
                rx_err_pipe  <= { rx_err_pipe[ 2:0],(n_rx_err)&&(rx_clk_stb)  };
698
                rx_miss_pipe <= { rx_miss_pipe[2:0],(n_rx_miss)&&(rx_clk_stb) };
699
                rx_crc_pipe  <= { rx_crc_pipe[ 2:0],(n_rx_crcerr)&&(rx_clk_stb) };
700
                rx_err_stb   <= (rx_err_pipe[ 3:2] == 2'b01);
701
                rx_miss_stb  <= (rx_miss_pipe[3:2] == 2'b01);
702
                rx_crc_stb   <= (rx_crc_pipe[ 3:2] == 2'b01);
703
        end
704
 
705
        always @(posedge i_wb_clk)
706
                if (o_net_reset_n)
707
                        counter_rx_miss <= 32'h0;
708
                else if (rx_miss_stb)
709
                        counter_rx_miss <= counter_rx_miss + 32'h1;
710
        always @(posedge i_wb_clk)
711
                if (o_net_reset_n)
712
                        counter_rx_err <= 32'h0;
713
                else if (rx_err_stb)
714
                        counter_rx_err <= counter_rx_err + 32'h1;
715
        always @(posedge i_wb_clk)
716
                if (o_net_reset_n)
717
                        counter_rx_crc <= 32'h0;
718
                else if (rx_crc_stb)
719
                        counter_rx_crc <= counter_rx_crc + 32'h1;
720
 
721
        assign  o_tx_int = !tx_busy;
722
        assign  o_rx_int = (rx_valid)&&(!rx_clear);
723
        assign  o_wb_stall = 1'b0;
724
 
725
        wire    [31:0]   rxdbg;
726
        wire    rx_trigger; // reg      rx_trigger;
727
        /*
728
        always @(posedge `RXCLK)
729
        begin
730
                if ((n_rx_clear)&&(!rx_trigger))
731
                        rx_trigger <= 1'b1;
732
                else if (!n_rx_clear)
733
                        rx_trigger <= 1'b0;
734
        end
735
        */
736
        assign  rx_trigger = i_net_dv;
737
 
738
        assign  rxdbg = { rx_trigger, n_eop, w_rxwr,
739
                w_npre, w_npred,
740
                w_rxcrc, w_rxcrcd,
741
                w_macerr, w_broadcast, w_rxmac, w_rxmacd,
742
                n_rx_clear, i_net_rxerr, n_rx_miss, n_rx_net_err,// 4 bits
743
                n_rx_valid, n_rx_busy, i_net_crs, i_net_dv,     // 4 bits
744
                i_net_rxd };                                    // 4 bits
745
 
746
 
747
        wire    [31:0]   txdbg;
748
        assign  txdbg = { n_tx_cmd, i_net_dv, rx_busy, n_rx_err, i_net_rxd,
749
                        {(24-(MAW+3)-10){1'b0}},
750
                        n_tx_addr[(MAW+2):0],
751
                tx_clk_stb, n_tx_cancel,
752
                n_tx_cmd, n_tx_complete, n_tx_busy, o_net_tx_en,
753
                o_net_txd
754
                };
755
 
756
        assign  o_debug = rxdbg;
757
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.