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

Subversion Repositories openarty

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

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 49 dgisselq
        wire    rx_broadcast;
204 30 dgisselq
        wire    [(MAW+1):0]      rx_len;
205
`else
206 49 dgisselq
        (* ASYNC_REG = "TRUE" *) reg    rx_broadcast;
207 30 dgisselq
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      rx_len;
208
`endif
209
 
210
        reg     tx_cmd, tx_cancel;
211
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
212
        wire    tx_busy, tx_complete;
213
`else
214
        reg     tx_busy, tx_complete;
215
`endif
216 33 dgisselq
        reg     config_hw_crc, config_hw_mac, config_hw_ip_check;
217 30 dgisselq
        reg     rx_crcerr, rx_err, rx_miss, rx_clear;
218
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
219
        wire    rx_valid, rx_busy;
220
`else
221
        reg     rx_valid, rx_busy;
222
`endif
223
        reg     rx_wb_valid, pre_ack, pre_cmd, tx_nzero_cmd;
224
        reg     [4:0]    caseaddr;
225
        reg     [31:0]   rx_wb_data, tx_wb_data;
226
        reg             rx_err_stb, rx_miss_stb, rx_crc_stb;
227
 
228
        reg     [47:0]   hw_mac;
229
        reg             p_rx_clear;
230
        reg     [7:0]    clear_pipe;
231
 
232
        initial config_hw_crc = 0;
233
        initial config_hw_mac = 0;
234 33 dgisselq
        initial config_hw_ip_check = 0;
235 30 dgisselq
        initial o_net_reset_n = 1'b0;
236
        initial tx_cmd    = 1'b0;
237
        initial tx_cancel = 1'b0;
238
        initial rx_crcerr = 1'b0;
239
        initial rx_err    = 1'b0;
240
        initial rx_miss   = 1'b0;
241
        initial rx_clear  = 1'b0;
242
        always @(posedge i_wb_clk)
243
        begin
244
                // if (i_wb_addr[(MAW+1):MAW] == 2'b10)
245
                        // Writes to rx memory not allowed here
246
                if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11))
247
                        txmem[i_wb_addr[(MAW-1):0]] <= i_wb_data;
248
 
249
                // Set the err bits on these conditions (filled out below)
250
                if (rx_err_stb)
251
                        rx_err <= 1'b1;
252
                if (rx_miss_stb)
253
                        rx_miss <= 1'b1;
254
                if (rx_crc_stb)
255
                        rx_crcerr <= 1'b1;
256
 
257
                if ((wr_ctrl)&&(wr_addr==3'b000))
258
                begin // RX command register
259
                        rx_crcerr<= (!wr_data[18])&&(!rx_crcerr);
260
                        rx_err   <= (!wr_data[17])&&(!rx_err);
261
                        rx_miss  <= (!wr_data[16])&&(!rx_miss);
262
                        // busy bit cannot be written to
263
                        rx_clear <= rx_clear || (wr_data[14]);
264
                        // Length bits are cleared when invalid
265
                end else if (!rx_valid)
266
                        rx_clear <= 1'b0;
267
 
268
                clear_pipe <= { clear_pipe[6:0], rx_clear };
269
                p_rx_clear <= |clear_pipe;
270
 
271
                if ((tx_busy)||(tx_cancel))
272
                        tx_cmd <= 1'b0;
273
                if (!tx_busy)
274
                        tx_cancel <= 1'b0;
275
                pre_cmd <= 1'b0;
276
                if ((wr_ctrl)&&(wr_addr==3'b001))
277
                begin // TX command register
278
 
279
                        // Reset bit must be held down to be valid
280 33 dgisselq
                        config_hw_ip_check <= (!wr_data[18]);
281 30 dgisselq
                        o_net_reset_n <= (!wr_data[17]);
282
                        config_hw_mac <= (!wr_data[16]);
283
                        config_hw_crc <= (!wr_data[15]);
284
                        pre_cmd <= (wr_data[14]);
285
                        tx_cancel <= (tx_busy)&&(!wr_data[14]);
286
//              14'h0   | SW-CRCn |NET-RST|BUSY/CMD | 14 bit length(in octets)|
287
                        tx_len <= wr_data[(MAW+1):0];
288
                end
289
                tx_nzero_cmd <= ((pre_cmd)&&(tx_len != 0));
290
                if (tx_nzero_cmd)
291
                        tx_cmd <= 1'b1;
292
                if (!o_net_reset_n)
293
                        tx_cancel <= 1'b1;
294
                if (!o_net_reset_n)
295
                        tx_cmd <= 1'b0;
296
 
297
                if ((wr_ctrl)&&(wr_addr==3'b010))
298
                        hw_mac[47:32] <= wr_data[15:0];
299
                if ((wr_ctrl)&&(wr_addr==3'b011))
300
                        hw_mac[31:0] <= wr_data[31:0];
301
        end
302
 
303
        wire    [31:0]   w_tx_ctrl;
304
        wire    [31:0]   w_rx_ctrl;
305
        wire    [3:0]    w_maw;
306
 
307
        assign  w_maw = MAW+2; // Number of bits in the packet length field
308 49 dgisselq
        assign  w_rx_ctrl = { 4'h0, w_maw, {(24-20){1'b0}},
309
                        (rx_valid)&&(rx_broadcast)&&(!rx_clear),
310
                        rx_crcerr, rx_err,
311 30 dgisselq
                        rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
312
                        {(14-MAW-2){1'b0}}, rx_len };
313
 
314 33 dgisselq
        assign  w_tx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}},
315
                        !config_hw_ip_check,
316 30 dgisselq
                        !o_net_reset_n,!config_hw_mac,
317
                        !config_hw_crc, tx_busy,
318
                                {(14-MAW-2){1'b0}}, tx_len };
319
 
320
        reg     [31:0]   counter_rx_miss, counter_rx_err, counter_rx_crc;
321
        initial counter_rx_miss = 32'h00;
322
        initial counter_rx_err  = 32'h00;
323
        initial counter_rx_crc  = 32'h00;
324
 
325
        // Reads from the bus ... always done, regardless of i_wb_we
326
        always @(posedge i_wb_clk)
327
        begin
328
                rx_wb_data  <= rxmem[i_wb_addr[(MAW-1):0]];
329
                rx_wb_valid <= (i_wb_addr[(MAW-1):0] <= { rx_len[(MAW+1):2] });
330
                tx_wb_data  <= txmem[i_wb_addr[(MAW-1):0]];
331
                pre_ack <= i_wb_stb;
332
                caseaddr <= {i_wb_addr[(MAW+1):MAW], i_wb_addr[2:0] };
333
 
334
                casez(caseaddr)
335
                5'h00: o_wb_data <= w_rx_ctrl;
336
                5'h01: o_wb_data <= w_tx_ctrl;
337
                5'h02: o_wb_data <= {16'h00, hw_mac[47:32] };
338
                5'h03: o_wb_data <= hw_mac[31:0];
339
                5'h04: o_wb_data <= counter_rx_miss;
340
                5'h05: o_wb_data <= counter_rx_err;
341
                5'h06: o_wb_data <= counter_rx_crc;
342
                5'h07: o_wb_data <= 32'h00;
343
                5'b10???: o_wb_data <= (rx_wb_valid)?rx_wb_data:32'h00;
344
                5'b11???: o_wb_data <= tx_wb_data;
345
                default: o_wb_data <= 32'h00;
346
                endcase
347
                o_wb_ack <= pre_ack;
348
        end
349
 
350
        /////////////////////////////////////
351
        //
352
        //
353
        //
354
        // Transmitter code
355
        //
356
        //
357
        //
358
        /////////////////////////////////////
359
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
360
        reg     [(MAW+1):0]      n_tx_len;
361
        wire    n_tx_cmd, n_tx_cancel;
362
        assign  n_tx_cmd = tx_cmd;
363
        assign  n_tx_cancel = tx_cancel;
364
`else
365
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      n_tx_len;
366
        (* ASYNC_REG = "TRUE" *) reg r_tx_cmd, r_tx_cancel;
367
        reg     n_tx_cmd, n_tx_cancel;
368
        always @(posedge `TXCLK)
369
        begin
370
                r_tx_cmd    <= tx_cmd;
371
                r_tx_cancel <= tx_cancel;
372
 
373
                n_tx_cmd    <= r_tx_cmd;
374
                n_tx_cancel <= r_tx_cancel;
375
        end
376
`endif
377
 
378
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
379
        reg     last_tx_clk, tx_clk_stb;
380
        (* ASYNC_REG = "TRUE" *) reg    r_tx_clk;
381
        always @(posedge i_wb_clk)
382
                r_tx_clk <= i_net_tx_clk;
383
        always @(posedge i_wb_clk)
384
                last_tx_clk <= r_tx_clk;
385
        always @(posedge i_wb_clk)
386
                tx_clk_stb <= (r_tx_clk)&&(!last_tx_clk);
387
`else
388
        wire    tx_clk_stb, last_tx_clk;
389
 
390
        assign  tx_clk_stb = 1'b1;
391
        assign  last_tx_clk= 1'b0;
392
`endif
393
 
394
        wire    [(MAW+2):0]      rd_tx_addr;
395
        assign  rd_tx_addr = (n_tx_addr+8);
396
 
397
        reg     [(MAW+2):0]      n_tx_addr;
398
        reg     [31:0]           n_tx_data, n_next_tx_data;
399
        reg                     n_tx_complete;
400
`ifdef  TX_SYNCHRONOUSH_WITH_WB
401
        reg             n_tx_busy, n_tx_config_hw_mac, n_tx_config_hw_crc;
402
`else
403
        (* ASYNC_REG = "TRUE" *) reg    n_tx_busy,
404
                                        n_tx_config_hw_mac, n_tx_config_hw_crc;
405
`endif
406
        (* ASYNC_REG = "TRUE" *) reg r_tx_crs;
407
        reg     n_tx_crs;
408
        always @(posedge `TXCLK)
409
        begin
410
                r_tx_crs <= i_net_crs;
411
                n_tx_crs <= r_tx_crs;
412
        end
413
 
414
        wire    [31:0]   n_remap_tx_data;
415
        assign  n_remap_tx_data[31:28] = n_next_tx_data[27:24];
416
        assign  n_remap_tx_data[27:24] = n_next_tx_data[31:28];
417
        assign  n_remap_tx_data[23:20] = n_next_tx_data[19:16];
418
        assign  n_remap_tx_data[19:16] = n_next_tx_data[23:20];
419
        assign  n_remap_tx_data[15:12] = n_next_tx_data[11: 8];
420
        assign  n_remap_tx_data[11: 8] = n_next_tx_data[15:12];
421
        assign  n_remap_tx_data[ 7: 4] = n_next_tx_data[ 3: 0];
422
        assign  n_remap_tx_data[ 3: 0] = n_next_tx_data[ 7: 4];
423
 
424
        reg             r_txd_en;
425
        reg     [3:0]    r_txd;
426
        initial r_txd_en = 1'b0;
427
 
428
        initial n_tx_busy  = 1'b0;
429
        initial n_tx_complete  = 1'b0;
430
        always @(posedge `TXCLK)
431
        begin
432
                if (tx_clk_stb)
433
                begin
434
                        // While this operation doesn't strictly need to 
435
                        // operate *only* if tx_clk_stb is true, by doing so
436
                        // our code stays compatible with both synchronous
437
                        // to wishbone and synchronous to tx clk options.
438
                        n_next_tx_data  <= txmem[(!n_tx_busy)?0:rd_tx_addr[(MAW+2):3]];
439
                end
440
 
441
 
442
                if (n_tx_cancel)
443
                        n_tx_busy <= 1'b0;
444
                else if (!n_tx_busy)
445
                        n_tx_busy <= (n_tx_cmd)&&(!i_net_crs);
446
                else if (n_tx_addr >= { n_tx_len,1'b0 })
447
                        n_tx_busy     <= 1'b0;
448
 
449
                if (!n_tx_busy)
450
                begin
451
                        n_tx_addr  <= {{(MAW+2){1'b0}},1'b1};
452
                        n_tx_data <= { n_remap_tx_data[27:0], 4'h0 };
453
                        if (n_tx_complete)
454
                                n_tx_complete <= (!n_tx_cmd);
455
                        r_txd_en <= (!n_tx_complete)&&(n_tx_cmd)&&(!i_net_crs);
456
                        r_txd  <= n_remap_tx_data[31:28];
457
                        n_tx_config_hw_mac <= config_hw_mac;
458
                        n_tx_config_hw_crc <= config_hw_crc;
459
                        n_tx_len <= tx_len;
460
                end else if (!r_txd_en)
461
                        r_txd_en <= (!n_tx_crs);
462
                else if (tx_clk_stb) begin
463
                        n_tx_addr <= n_tx_addr + 1'b1;
464
                        r_txd <= n_tx_data[31:28];
465
                        if (n_tx_addr[2:0] == 3'h7)
466
                                n_tx_data <= n_remap_tx_data;
467
                        else
468
                                n_tx_data <= { n_tx_data[27:0], 4'h0 };
469
                        if (n_tx_addr >= { n_tx_len,1'b0 })
470
                                n_tx_complete <= 1'b1;
471
                        r_txd_en <= (n_tx_addr < { n_tx_len, 1'b0 });
472
                end
473
        end
474
 
475
        wire    n_tx_config_hw_preamble;
476
        assign  n_tx_config_hw_preamble = 1'b1;
477
 
478
        wire            w_macen, w_paden, w_txcrcen;
479
        wire    [3:0]    w_macd,  w_padd,  w_txcrcd;
480
 
481
`ifndef TX_BYPASS_HW_MAC
482
        addemac txmaci(`TXCLK, tx_clk_stb, n_tx_config_hw_mac, n_tx_cancel,
483
                                hw_mac, r_txd_en, r_txd, w_macen, w_macd);
484
`else
485
        assign  w_macen = r_txd_en;
486
        assign  w_macd  = r_txd;
487
`endif
488
 
489
`ifndef TX_BYPASS_PADDING
490
        addepad txpadi(`TXCLK, tx_clk_stb, 1'b1, n_tx_cancel,
491
                                w_macen, w_macd, w_paden, w_padd);
492
`else
493
        assign  w_paden = w_macen;
494
        assign  w_padd  = w_macd;
495
`endif
496
 
497
`ifndef TX_BYPASS_HW_CRC
498
        addecrc txcrci(`TXCLK, tx_clk_stb, n_tx_config_hw_crc, n_tx_cancel,
499
                                w_paden, w_padd, w_txcrcen, w_txcrcd);
500
`else
501
        assign  w_txcrcen = w_macen;
502
        assign  w_txcrcd  = w_macd;
503
`endif
504
 
505
        addepreamble txprei(`TXCLK, tx_clk_stb, n_tx_config_hw_preamble, n_tx_cancel,
506
                                w_txcrcen, w_txcrcd, o_net_tx_en, o_net_txd);
507
 
508
`ifdef  TX_SYNCRONOUS_WITH_WB_CLK
509
        assign  tx_busy = n_tx_busy;
510
        assign  tx_complete = n_tx_complete;
511
`else
512
        (* ASYNC_REG = "TRUE" *) reg    r_tx_busy, r_tx_complete;
513
        always @(posedge i_wb_clk)
514
        begin
515
                r_tx_busy <= (n_tx_busy || o_net_tx_en || w_txcrcen || w_macen || w_paden);
516
                tx_busy <= r_tx_busy;
517
 
518
                r_tx_complete <= n_tx_complete;
519
                tx_busy <= r_tx_busy;
520
        end
521
`endif
522
 
523
 
524
 
525
 
526
 
527
        /////////////////////////////////////
528
        //
529
        //
530
        //
531
        // Receiver code
532
        //
533
        //
534
        //
535
        /////////////////////////////////////
536
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
537
        reg     last_rx_clk, rx_clk_stb;
538
        (* ASYNC_REG="TRUE" *) reg r_rx_clk;
539
        always @(posedge i_wb_clk)
540
                r_rx_clk <= i_net_rx_clk;
541
        always @(posedge i_wb_clk)
542
                last_rx_clk <= r_rx_clk;
543
        always @(posedge i_wb_clk)
544
                rx_clk_stb <= (r_rx_clk)&&(!last_rx_clk);
545
 
546
`else
547
        wire    rx_clk_stb, last_rx_clk;
548
        assign  rx_clk_stb = 1'b1;
549
        assign  last_rx_clk = 1'b0;
550
`endif
551
 
552
 
553
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
554
        wire    n_rx_clear;
555 33 dgisselq
        reg     n_rx_config_hw_mac, n_rx_config_hw_crc, n_rx_config_ip_check;
556 30 dgisselq
        assign  n_rx_clear = rx_clear;
557
`else
558 33 dgisselq
        (* ASYNC_REG = "TRUE" *) reg n_rx_config_hw_mac, n_rx_config_hw_crc,
559
                        n_rx_config_ip_check;
560 30 dgisselq
        (* ASYNC_REG = "TRUE" *) reg r_rx_clear;
561
        reg     n_rx_clear;
562
        always @(posedge `RXCLK)
563
        begin
564
                r_rx_clear <= (p_rx_clear)||(!o_net_reset_n);
565
                n_rx_clear <= r_rx_clear;
566
        end
567
`endif
568
 
569
 
570
        reg             n_rx_net_err;
571 33 dgisselq
        wire            w_npre,  w_rxmin,  w_rxcrc,  w_rxmac;
572
        wire    [3:0]    w_npred, w_rxmind, w_rxcrcd, w_rxmacd;
573 30 dgisselq
        wire            w_minerr, w_rxcrcerr, w_macerr, w_broadcast, w_iperr;
574
`ifndef RX_BYPASS_HW_PREAMBLE
575
        rxepreambl rxprei(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
576
                        i_net_dv, i_net_rxd, w_npre, w_npred);
577
`else
578
        assign  w_npre  = i_net_dv;
579
        assign  w_npred = i_net_rxerr;
580
`endif
581
 
582 33 dgisselq
`ifdef  RX_BYPASS_HW_MINLENGTH
583 30 dgisselq
        // Insist on a minimum of 64-byte packets
584 33 dgisselq
        rxemin  rxmini(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
585
                        w_npre, w_npred, w_minerr);
586 30 dgisselq
`else
587 33 dgisselq
        assign  w_minerr= 1'b0;
588
`endif
589 30 dgisselq
        assign  w_rxmin = w_npre;
590
        assign  w_rxmind= w_npred;
591
 
592
`ifndef RX_BYPASS_HW_CRC
593
        rxecrc  rxcrci(`RXCLK, rx_clk_stb, n_rx_config_hw_crc, (n_rx_net_err),
594
                        w_rxmin, w_rxmind, w_rxcrc, w_rxcrcd, w_rxcrcerr);
595
`else
596
        assign  w_rxcrc   = w_rxmin;
597
        assign  w_rxcrcd  = w_rxmind;
598
        assign  w_rxcrcerr= 1'b0;
599
`endif
600
 
601
`ifndef RX_BYPASS_HW_RMMAC
602
        rxehwmac rxmaci(`RXCLK, rx_clk_stb, n_rx_config_hw_mac, (n_rx_net_err), hw_mac,
603
                        w_rxcrc, w_rxcrcd,
604
                        w_rxmac, w_rxmacd,
605
                        w_macerr, w_broadcast);
606
`else
607
        assign  w_rxmac  = w_rxcrc;
608
        assign  w_rxmacd = w_rxcrcd;
609
`endif
610
 
611 33 dgisselq
`define RX_HW_IPCHECK
612 30 dgisselq
`ifdef  RX_HW_IPCHECK
613
        // Check: if this packet is an IP packet, is the IP header checksum
614
        // valid?
615 33 dgisselq
        rxeipchk rxipci(`RXCLK, rx_clk_stb, n_rx_config_ip_check,(n_rx_net_err),
616
                        w_rxcrc, w_rxcrcd, w_iperr);
617 30 dgisselq
`else
618
        assign  w_iperr = 1'b0;
619
`endif
620
 
621
        wire                    w_rxwr;
622
        wire    [(MAW-1):0]      w_rxaddr;
623
        wire    [31:0]           w_rxdata;
624
        wire    [(MAW+1):0]      w_rxlen;
625
 
626 33 dgisselq
        rxewrite #(MAW) rxememi(`RXCLK, 1'b1, (n_rx_net_err), w_rxmac, w_rxmacd,
627 30 dgisselq
                        w_rxwr, w_rxaddr, w_rxdata, w_rxlen);
628
 
629
        reg     last_rxwr, n_rx_valid, n_rxmiss, n_eop, n_rx_busy, n_rx_crcerr,
630
                n_rx_err, n_rx_broadcast, n_rx_miss;
631
        reg     [(MAW+1):0]      n_rx_len;
632
 
633
        initial n_rx_valid = 1'b0;
634
        initial n_rx_clear = 1'b1;
635
        initial n_rx_miss  = 1'b0;
636
        always @(posedge `RXCLK)
637
        begin
638
                if ((w_rxwr)&&(!n_rx_valid))
639
                        rxmem[w_rxaddr] <= w_rxdata;
640
 
641
                // n_rx_net_err goes true as soon as an error is detected,
642
                // and stays true as long as valid data is coming in
643
                n_rx_net_err <= (i_net_dv)&&((i_net_rxerr)||(i_net_col)
644
                                ||(w_minerr)||(w_macerr)||(w_rxcrcerr)
645 33 dgisselq
                                ||(w_iperr)
646 30 dgisselq
                                ||(n_rx_net_err)
647
                                ||((w_rxwr)&&(n_rx_valid)));
648
 
649
                last_rxwr <= w_rxwr;
650
                n_eop <= (!w_rxwr)&&(last_rxwr)&&(!n_rx_net_err);
651
 
652
                n_rx_busy <= (!n_rx_net_err)&&((i_net_dv)||(w_npre)||(w_rxmin)
653 33 dgisselq
                        ||(w_rxcrc)||(w_rxmac)||(w_rxwr));
654 30 dgisselq
 
655
                // Oops ... we missed a packet
656
                n_rx_miss <= (n_rx_valid)&&(w_rxwr)||
657
                        ((n_rx_miss)&&(!n_rx_clear));
658
 
659
                n_rx_crcerr <= ((w_rxcrcerr)&&(!n_rx_net_err))
660
                        ||((n_rx_crcerr)&&(!n_rx_clear));
661
 
662
                n_rx_err <= ((n_rx_err)&&(!n_rx_clear))
663
                        ||((i_net_rxerr)||(i_net_col)||(w_minerr));
664
 
665
                n_rx_broadcast <= (w_broadcast)||((n_rx_broadcast)&&(!n_rx_clear));
666
 
667
                if (n_rx_clear)
668
                begin
669
                        n_rx_valid <= 1'b0;
670
                        n_rx_len <= 0;
671
                end else if (n_eop)
672
                begin
673
                        n_rx_valid <= 1'b1;
674
                        n_rx_len   <= w_rxlen - ((n_rx_config_hw_crc)?{{(MAW-1){1'b0}},3'h4}:0);
675
                end
676
                // else n_rx_valid = n_rx_valid;
677
 
678
                if ((!i_net_dv)||(n_rx_clear))
679
                begin
680 33 dgisselq
                        n_rx_config_hw_mac   <= config_hw_mac;
681
                        n_rx_config_hw_crc   <= config_hw_crc;
682
                        n_rx_config_ip_check <= config_hw_ip_check;
683 30 dgisselq
                end
684
        end
685
 
686
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
687
        assign  rx_busy  = n_rx_busy;
688
        assign  rx_valid = n_rx_valid;
689
        assign  rx_len   = n_rx_len;
690 49 dgisselq
        assign  rx_broadcast = n_rx_broadcast;
691 30 dgisselq
`else
692
        reg     r_rx_busy, r_rx_valid;
693
        always @(posedge i_wb_clk)
694
        begin
695
                r_rx_valid <= n_rx_valid;
696
                rx_valid <= r_rx_valid;
697
 
698
                r_rx_busy <= n_rx_busy;
699
                rx_busy <= r_rx_busy;
700
 
701
                rx_len <= n_rx_len;
702 49 dgisselq
                rx_broadcast <= n_rx_broadcast;
703 30 dgisselq
        end
704
 
705
`endif
706
 
707
        reg     [3:0]    rx_err_pipe, rx_miss_pipe, rx_crc_pipe;
708
        always @(posedge i_wb_clk)
709
        begin
710
                rx_err_pipe  <= { rx_err_pipe[ 2:0],(n_rx_err)&&(rx_clk_stb)  };
711
                rx_miss_pipe <= { rx_miss_pipe[2:0],(n_rx_miss)&&(rx_clk_stb) };
712
                rx_crc_pipe  <= { rx_crc_pipe[ 2:0],(n_rx_crcerr)&&(rx_clk_stb) };
713
                rx_err_stb   <= (rx_err_pipe[ 3:2] == 2'b01);
714
                rx_miss_stb  <= (rx_miss_pipe[3:2] == 2'b01);
715
                rx_crc_stb   <= (rx_crc_pipe[ 3:2] == 2'b01);
716
        end
717
 
718
        always @(posedge i_wb_clk)
719
                if (o_net_reset_n)
720
                        counter_rx_miss <= 32'h0;
721
                else if (rx_miss_stb)
722
                        counter_rx_miss <= counter_rx_miss + 32'h1;
723
        always @(posedge i_wb_clk)
724
                if (o_net_reset_n)
725
                        counter_rx_err <= 32'h0;
726
                else if (rx_err_stb)
727
                        counter_rx_err <= counter_rx_err + 32'h1;
728
        always @(posedge i_wb_clk)
729
                if (o_net_reset_n)
730
                        counter_rx_crc <= 32'h0;
731
                else if (rx_crc_stb)
732
                        counter_rx_crc <= counter_rx_crc + 32'h1;
733
 
734
        assign  o_tx_int = !tx_busy;
735
        assign  o_rx_int = (rx_valid)&&(!rx_clear);
736
        assign  o_wb_stall = 1'b0;
737
 
738
        wire    [31:0]   rxdbg;
739
        wire    rx_trigger; // reg      rx_trigger;
740
        /*
741
        always @(posedge `RXCLK)
742
        begin
743
                if ((n_rx_clear)&&(!rx_trigger))
744
                        rx_trigger <= 1'b1;
745
                else if (!n_rx_clear)
746
                        rx_trigger <= 1'b0;
747
        end
748
        */
749
        assign  rx_trigger = i_net_dv;
750
 
751
        assign  rxdbg = { rx_trigger, n_eop, w_rxwr,
752
                w_npre, w_npred,
753
                w_rxcrc, w_rxcrcd,
754
                w_macerr, w_broadcast, w_rxmac, w_rxmacd,
755
                n_rx_clear, i_net_rxerr, n_rx_miss, n_rx_net_err,// 4 bits
756
                n_rx_valid, n_rx_busy, i_net_crs, i_net_dv,     // 4 bits
757
                i_net_rxd };                                    // 4 bits
758
 
759
 
760
        wire    [31:0]   txdbg;
761
        assign  txdbg = { n_tx_cmd, i_net_dv, rx_busy, n_rx_err, i_net_rxd,
762
                        {(24-(MAW+3)-10){1'b0}},
763
                        n_tx_addr[(MAW+2):0],
764
                tx_clk_stb, n_tx_cancel,
765
                n_tx_cmd, n_tx_complete, n_tx_busy, o_net_tx_en,
766
                o_net_txd
767
                };
768
 
769
        assign  o_debug = rxdbg;
770
endmodule

powered by: WebSVN 2.1.0

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