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

Subversion Repositories openarty

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

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

powered by: WebSVN 2.1.0

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