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

Subversion Repositories openarty

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

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

powered by: WebSVN 2.1.0

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