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

Subversion Repositories xge_mac

[/] [xge_mac/] [trunk/] [rtl/] [verilog/] [tx_dequeue.v] - Blame information for rev 24

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

Line No. Rev Author Line
1 2 antanguay
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "tx_dequeue.v"                                    ////
4
////                                                              ////
5
////  This file is part of the "10GE MAC" project                 ////
6
////  http://www.opencores.org/cores/xge_mac/                     ////
7
////                                                              ////
8
////  Author(s):                                                  ////
9
////      - A. Tanguay (antanguay@opencores.org)                  ////
10
////                                                              ////
11
//////////////////////////////////////////////////////////////////////
12
////                                                              ////
13
//// Copyright (C) 2008 AUTHORS. All rights reserved.             ////
14
////                                                              ////
15
//// This source file may be used and distributed without         ////
16
//// restriction provided that this copyright statement is not    ////
17
//// removed from the file and that any derivative work contains  ////
18
//// the original copyright notice and the associated disclaimer. ////
19
////                                                              ////
20
//// This source file is free software; you can redistribute it   ////
21
//// and/or modify it under the terms of the GNU Lesser General   ////
22
//// Public License as published by the Free Software Foundation; ////
23
//// either version 2.1 of the License, or (at your option) any   ////
24
//// later version.                                               ////
25
////                                                              ////
26
//// This source is distributed in the hope that it will be       ////
27
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
28
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
29
//// PURPOSE.  See the GNU Lesser General Public License for more ////
30
//// details.                                                     ////
31
////                                                              ////
32
//// You should have received a copy of the GNU Lesser General    ////
33
//// Public License along with this source; if not, download it   ////
34
//// from http://www.opencores.org/lgpl.shtml                     ////
35
////                                                              ////
36
//////////////////////////////////////////////////////////////////////
37
 
38
 
39
`include "defines.v"
40
 
41
module tx_dequeue(/*AUTOARG*/
42
  // Outputs
43 12 antanguay
  txdfifo_ren, txhfifo_ren, txhfifo_wdata, txhfifo_wstatus,
44
  txhfifo_wen, xgmii_txd, xgmii_txc, status_txdfifo_udflow_tog,
45 24 antanguay
  txsfifo_wen, txsfifo_wdata,
46 2 antanguay
  // Inputs
47 12 antanguay
  clk_xgmii_tx, reset_xgmii_tx_n, ctrl_tx_enable_ctx,
48
  status_local_fault_ctx, status_remote_fault_ctx, txdfifo_rdata,
49
  txdfifo_rstatus, txdfifo_rempty, txdfifo_ralmost_empty,
50
  txhfifo_rdata, txhfifo_rstatus, txhfifo_rempty,
51 2 antanguay
  txhfifo_ralmost_empty, txhfifo_wfull, txhfifo_walmost_full
52
  );
53
`include "CRC32_D64.v"
54
`include "CRC32_D8.v"
55
`include "utils.v"
56
 
57
input         clk_xgmii_tx;
58
input         reset_xgmii_tx_n;
59
 
60
input         ctrl_tx_enable_ctx;
61 20 antanguay
 
62 2 antanguay
input         status_local_fault_ctx;
63
input         status_remote_fault_ctx;
64 20 antanguay
 
65 2 antanguay
input  [63:0] txdfifo_rdata;
66
input  [7:0]  txdfifo_rstatus;
67
input         txdfifo_rempty;
68
input         txdfifo_ralmost_empty;
69
 
70
input  [63:0] txhfifo_rdata;
71
input  [7:0]  txhfifo_rstatus;
72
input         txhfifo_rempty;
73
input         txhfifo_ralmost_empty;
74
 
75
input         txhfifo_wfull;
76
input         txhfifo_walmost_full;
77
 
78
output        txdfifo_ren;
79
 
80
output        txhfifo_ren;
81
 
82
output [63:0] txhfifo_wdata;
83
output [7:0]  txhfifo_wstatus;
84 20 antanguay
output        txhfifo_wen;
85 2 antanguay
 
86
output [63:0] xgmii_txd;
87
output [7:0]  xgmii_txc;
88
 
89
output        status_txdfifo_udflow_tog;
90
 
91 24 antanguay
output        txsfifo_wen;
92
output [13:0] txsfifo_wdata;
93 2 antanguay
 
94
 
95
/*AUTOREG*/
96
// Beginning of automatic regs (for this module's undeclared outputs)
97
reg                     status_txdfifo_udflow_tog;
98
reg                     txdfifo_ren;
99
reg                     txhfifo_ren;
100
reg [63:0]              txhfifo_wdata;
101
reg                     txhfifo_wen;
102
reg [7:0]               txhfifo_wstatus;
103 24 antanguay
reg [13:0]              txsfifo_wdata;
104
reg                     txsfifo_wen;
105 2 antanguay
reg [7:0]               xgmii_txc;
106
reg [63:0]              xgmii_txd;
107
// End of automatics
108
 
109
/*AUTOWIRE*/
110
 
111
 
112
reg   [63:0]    xgxs_txd;
113
reg   [7:0]     xgxs_txc;
114
 
115
reg   [63:0]    next_xgxs_txd;
116
reg   [7:0]     next_xgxs_txc;
117
 
118 10 antanguay
reg   [2:0]     curr_state_enc;
119
reg   [2:0]     next_state_enc;
120 2 antanguay
 
121 10 antanguay
reg   [0:0]     curr_state_pad;
122
reg   [0:0]     next_state_pad;
123 2 antanguay
 
124
reg             start_on_lane0;
125
reg             next_start_on_lane0;
126
 
127
reg   [2:0]     ifg_deficit;
128
reg   [2:0]     next_ifg_deficit;
129
 
130
reg             ifg_4b_add;
131
reg             next_ifg_4b_add;
132
 
133
reg             ifg_8b_add;
134
reg             next_ifg_8b_add;
135
 
136
reg             ifg_8b2_add;
137
reg             next_ifg_8b2_add;
138
 
139 6 antanguay
reg   [7:0]     eop;
140
reg   [7:0]     next_eop;
141
 
142 2 antanguay
reg   [63:32]   xgxs_txd_barrel;
143
reg   [7:4]     xgxs_txc_barrel;
144
 
145
reg   [63:0]    txhfifo_rdata_d1;
146
 
147
reg   [13:0]    byte_cnt;
148
 
149
reg   [31:0]    crc32_d64;
150
reg   [31:0]    crc32_d8;
151
reg   [31:0]    crc32_tx;
152
 
153
reg   [63:0]    shift_crc_data;
154 6 antanguay
reg   [3:0]     shift_crc_eop;
155
reg   [3:0]     shift_crc_cnt;
156 2 antanguay
 
157
reg   [31:0]    crc_data;
158
 
159
reg             frame_available;
160
reg             next_frame_available;
161
 
162
reg   [63:0]    next_txhfifo_wdata;
163
reg   [7:0]     next_txhfifo_wstatus;
164 20 antanguay
reg             next_txhfifo_wen;
165 2 antanguay
 
166 6 antanguay
reg             txdfifo_ren_d1;
167
 
168 23 antanguay
reg             frame_end;
169
 
170 2 antanguay
parameter [2:0]
171
             SM_IDLE      = 3'd0,
172
             SM_PREAMBLE  = 3'd1,
173
             SM_TX        = 3'd2,
174
             SM_EOP       = 3'd3,
175
             SM_TERM      = 3'd4,
176
             SM_TERM_FAIL = 3'd5,
177
             SM_IFG       = 3'd6;
178
 
179 6 antanguay
parameter [0:0]
180 10 antanguay
             SM_PAD_EQ    = 1'd0,
181
             SM_PAD_PAD   = 1'd1;
182 2 antanguay
 
183
 
184
//---
185
// RC layer
186
 
187
always @(posedge clk_xgmii_tx or negedge reset_xgmii_tx_n) begin
188
 
189
    if (reset_xgmii_tx_n == 1'b0) begin
190
 
191
        xgmii_txd <= {8{`IDLE}};
192
        xgmii_txc <= 8'hff;
193
 
194
    end
195
    else begin
196
 
197
 
198
        //---
199
        // RC Layer, insert local or remote fault messages based on status
200
        // of fault state-machine
201
 
202
        if (status_local_fault_ctx) begin
203
 
204
            // If local fault detected, send remote fault message to
205
            // link partner
206 20 antanguay
 
207 2 antanguay
            xgmii_txd <= {`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE,
208
                          `REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE};
209
            xgmii_txc <= {4'b0001, 4'b0001};
210
        end
211
        else if (status_remote_fault_ctx) begin
212
 
213
            // If remote fault detected, inhibit transmission and send
214
            // idle codes
215 20 antanguay
 
216 2 antanguay
            xgmii_txd <= {8{`IDLE}};
217
            xgmii_txc <= 8'hff;
218
        end
219
        else begin
220
            xgmii_txd <= xgxs_txd;
221
            xgmii_txc <= xgxs_txc;
222
        end
223
    end
224
 
225
end
226
 
227
 
228
always @(posedge clk_xgmii_tx or negedge reset_xgmii_tx_n) begin
229
 
230
    if (reset_xgmii_tx_n == 1'b0) begin
231
 
232 10 antanguay
        curr_state_enc <= SM_IDLE;
233 2 antanguay
 
234
        start_on_lane0 <= 1'b1;
235
        ifg_deficit <= 3'b0;
236
        ifg_4b_add <= 1'b0;
237
        ifg_8b_add <= 1'b0;
238
        ifg_8b2_add <= 1'b0;
239
 
240 6 antanguay
        eop <= 8'b0;
241
 
242 2 antanguay
        txhfifo_rdata_d1 <= 64'b0;
243
 
244
        xgxs_txd_barrel <= {4{`IDLE}};
245
        xgxs_txc_barrel <= 4'hf;
246
 
247
        frame_available <= 1'b0;
248
 
249
        xgxs_txd <= {8{`IDLE}};
250
        xgxs_txc <= 8'hff;
251
 
252
        status_txdfifo_udflow_tog <= 1'b0;
253
 
254 24 antanguay
        txsfifo_wen <= 1'b0;
255
        txsfifo_wdata <= 14'b0;
256 23 antanguay
 
257 2 antanguay
    end
258
    else begin
259
 
260 10 antanguay
        curr_state_enc <= next_state_enc;
261 2 antanguay
 
262
        start_on_lane0 <= next_start_on_lane0;
263
        ifg_deficit <= next_ifg_deficit;
264
        ifg_4b_add <= next_ifg_4b_add;
265
        ifg_8b_add <= next_ifg_8b_add;
266
        ifg_8b2_add <= next_ifg_8b2_add;
267
 
268 6 antanguay
        eop <= next_eop;
269
 
270 2 antanguay
        txhfifo_rdata_d1 <= txhfifo_rdata;
271
 
272
        xgxs_txd_barrel <= next_xgxs_txd[63:32];
273
        xgxs_txc_barrel <= next_xgxs_txc[7:4];
274
 
275
        frame_available <= next_frame_available;
276
 
277 24 antanguay
        txsfifo_wen <= 1'b0;
278
        txsfifo_wdata <= byte_cnt;
279
 
280 2 antanguay
        //---
281
        // Barrel shifter. Previous stage always align packet with LANE0.
282
        // This stage allow us to shift packet to align with LANE4 if needed
283
        // for correct inter frame gap (IFG).
284
 
285
        if (next_start_on_lane0) begin
286
 
287
            xgxs_txd <= next_xgxs_txd;
288
            xgxs_txc <= next_xgxs_txc;
289
 
290
        end
291
        else begin
292
 
293
            xgxs_txd <= {next_xgxs_txd[31:0], xgxs_txd_barrel};
294
            xgxs_txc <= {next_xgxs_txc[3:0], xgxs_txc_barrel};
295
 
296
        end
297
 
298
        //---
299
        // FIFO errors, used to generate interrupts.
300 20 antanguay
 
301 2 antanguay
        if (txdfifo_ren && txdfifo_rempty) begin
302
            status_txdfifo_udflow_tog <= ~status_txdfifo_udflow_tog;
303
        end
304
 
305 23 antanguay
        //---
306
        // Frame count and size
307
 
308
        if (frame_end) begin
309 24 antanguay
            txsfifo_wen <= 1'b1;
310 23 antanguay
        end
311
 
312 2 antanguay
    end
313
 
314
end
315
 
316 10 antanguay
always @(/*AS*/crc32_tx or ctrl_tx_enable_ctx or curr_state_enc or eop
317 2 antanguay
         or frame_available or ifg_4b_add or ifg_8b2_add or ifg_8b_add
318
         or ifg_deficit or start_on_lane0 or status_local_fault_ctx
319 21 antanguay
         or status_remote_fault_ctx or txhfifo_ralmost_empty
320
         or txhfifo_rdata_d1 or txhfifo_rempty or txhfifo_rstatus) begin
321 2 antanguay
 
322 10 antanguay
    next_state_enc = curr_state_enc;
323 2 antanguay
 
324
    next_start_on_lane0 = start_on_lane0;
325
    next_ifg_deficit = ifg_deficit;
326
    next_ifg_4b_add = ifg_4b_add;
327
    next_ifg_8b_add = ifg_8b_add;
328
    next_ifg_8b2_add = ifg_8b2_add;
329
 
330 6 antanguay
    next_eop = eop;
331
 
332 2 antanguay
    next_xgxs_txd = {8{`IDLE}};
333
    next_xgxs_txc = 8'hff;
334
 
335
    txhfifo_ren = 1'b0;
336
 
337
    next_frame_available = frame_available;
338
 
339 10 antanguay
    case (curr_state_enc)
340 2 antanguay
 
341
        SM_IDLE:
342
          begin
343
 
344
              // Wait for frame to be available. There should be a least N bytes in the
345
              // data fifo or a crc in the control fifo. The N bytes in the data fifo
346
              // give time to the enqueue engine to calculate crc and write it to the
347
              // control fifo. If crc is already in control fifo we can start transmitting
348
              // with no concern. Transmission is inhibited if local or remote faults
349
              // are detected.
350
 
351
              if (ctrl_tx_enable_ctx && frame_available &&
352 20 antanguay
                  !status_local_fault_ctx && !status_remote_fault_ctx) begin
353 2 antanguay
 
354
                  txhfifo_ren = 1'b1;
355 10 antanguay
                  next_state_enc = SM_PREAMBLE;
356 2 antanguay
 
357
              end
358
              else begin
359
 
360
                  next_frame_available = !txhfifo_ralmost_empty;
361
                  next_ifg_4b_add = 1'b0;
362
 
363
              end
364
 
365
          end
366
 
367
        SM_PREAMBLE:
368
         begin
369
 
370
             // On reading SOP from fifo, send SFD and preamble characters
371
 
372 6 antanguay
             if (txhfifo_rstatus[`TXSTATUS_SOP]) begin
373 2 antanguay
 
374
                 next_xgxs_txd = {`SFD, {6{`PREAMBLE}}, `START};
375
                 next_xgxs_txc = 8'h01;
376
 
377 6 antanguay
                 txhfifo_ren = 1'b1;
378 2 antanguay
 
379 10 antanguay
                 next_state_enc = SM_TX;
380 2 antanguay
 
381 6 antanguay
             end
382
             else begin
383
 
384
                 next_frame_available = 1'b0;
385 10 antanguay
                 next_state_enc = SM_IDLE;
386 6 antanguay
 
387
             end
388
 
389
 
390 2 antanguay
             // Depending on deficit idle count calculations, add 4 bytes
391
             // or IFG or not. This will determine on which lane start the
392
             // next frame.
393 20 antanguay
 
394 2 antanguay
             if (ifg_4b_add) begin
395
                 next_start_on_lane0 = 1'b0;
396
             end
397
             else begin
398
                 next_start_on_lane0 = 1'b1;
399
             end
400
 
401
          end
402
 
403
        SM_TX:
404
          begin
405
 
406
              next_xgxs_txd = txhfifo_rdata_d1;
407
              next_xgxs_txc = 8'h00;
408
 
409
              txhfifo_ren = 1'b1;
410
 
411
 
412
              // Wait for EOP indication to be read from the fifo, then
413
              // transition to next state.
414
 
415 6 antanguay
              if (txhfifo_rstatus[`TXSTATUS_EOP]) begin
416 20 antanguay
 
417 2 antanguay
                  txhfifo_ren = 1'b0;
418
                  next_frame_available = !txhfifo_ralmost_empty;
419 10 antanguay
                  next_state_enc = SM_EOP;
420 6 antanguay
 
421 2 antanguay
              end
422 6 antanguay
              else if (txhfifo_rempty || txhfifo_rstatus[`TXSTATUS_SOP]) begin
423 2 antanguay
 
424
                  // Failure condition, we did not see EOP and there
425 6 antanguay
                  // is no more data in fifo or SOP, force end of packet transmit.
426 2 antanguay
 
427 10 antanguay
                  next_state_enc = SM_TERM_FAIL;
428 2 antanguay
 
429
              end
430
 
431 6 antanguay
              next_eop[0] = txhfifo_rstatus[2:0] == 3'd1;
432
              next_eop[1] = txhfifo_rstatus[2:0] == 3'd2;
433
              next_eop[2] = txhfifo_rstatus[2:0] == 3'd3;
434
              next_eop[3] = txhfifo_rstatus[2:0] == 3'd4;
435
              next_eop[4] = txhfifo_rstatus[2:0] == 3'd5;
436
              next_eop[5] = txhfifo_rstatus[2:0] == 3'd6;
437
              next_eop[6] = txhfifo_rstatus[2:0] == 3'd7;
438
              next_eop[7] = txhfifo_rstatus[2:0] == 3'd0;
439 20 antanguay
 
440 2 antanguay
          end
441
 
442
        SM_EOP:
443
          begin
444
 
445
              // Insert TERMINATE character in correct lane depending on position
446
              // of EOP read from fifo. Also insert CRC read from control fifo.
447
 
448 6 antanguay
              if (eop[0]) begin
449 20 antanguay
                  next_xgxs_txd = {{2{`IDLE}}, `TERMINATE,
450 2 antanguay
                                   crc32_tx[31:0], txhfifo_rdata_d1[7:0]};
451
                  next_xgxs_txc = 8'b11100000;
452
              end
453
 
454 6 antanguay
              if (eop[1]) begin
455 2 antanguay
                  next_xgxs_txd = {`IDLE, `TERMINATE,
456
                                   crc32_tx[31:0], txhfifo_rdata_d1[15:0]};
457
                  next_xgxs_txc = 8'b11000000;
458
              end
459
 
460 6 antanguay
              if (eop[2]) begin
461 2 antanguay
                  next_xgxs_txd = {`TERMINATE, crc32_tx[31:0], txhfifo_rdata_d1[23:0]};
462
                  next_xgxs_txc = 8'b10000000;
463
              end
464
 
465 6 antanguay
              if (eop[3]) begin
466 2 antanguay
                  next_xgxs_txd = {crc32_tx[31:0], txhfifo_rdata_d1[31:0]};
467
                  next_xgxs_txc = 8'b00000000;
468
              end
469
 
470 6 antanguay
              if (eop[4]) begin
471 2 antanguay
                  next_xgxs_txd = {crc32_tx[23:0], txhfifo_rdata_d1[39:0]};
472
                  next_xgxs_txc = 8'b00000000;
473
              end
474
 
475 6 antanguay
              if (eop[5]) begin
476 2 antanguay
                  next_xgxs_txd = {crc32_tx[15:0], txhfifo_rdata_d1[47:0]};
477
                  next_xgxs_txc = 8'b00000000;
478
              end
479
 
480 6 antanguay
              if (eop[6]) begin
481 2 antanguay
                  next_xgxs_txd = {crc32_tx[7:0], txhfifo_rdata_d1[55:0]};
482
                  next_xgxs_txc = 8'b00000000;
483
              end
484
 
485 6 antanguay
              if (eop[7]) begin
486 2 antanguay
                  next_xgxs_txd = {txhfifo_rdata_d1[63:0]};
487
                  next_xgxs_txc = 8'b00000000;
488
              end
489
 
490
              if (!frame_available) begin
491
 
492
                  // If there is not another frame ready to be transmitted, interface
493
                  // will go idle and idle deficit idle count calculation is irrelevant.
494
                  // Set deficit to 0.
495 20 antanguay
 
496 2 antanguay
                  next_ifg_deficit = 3'b0;
497
 
498
              end
499
              else begin
500
 
501
                  // Idle deficit count calculated based on number of "wasted" bytes
502
                  // between TERMINATE and alignment of next frame in LANE0.
503
 
504
                  next_ifg_deficit = ifg_deficit +
505 6 antanguay
                                     {2'b0, eop[0] | eop[4]} +
506
                                     {1'b0, eop[1] | eop[5], 1'b0} +
507
                                     {1'b0, eop[2] | eop[6],
508
                                      eop[2] | eop[6]};
509 2 antanguay
              end
510
 
511
              // IFG corrections based on deficit count and previous starting lane
512
              // Calculated based on following table:
513
              //
514
              //                 DIC=0          DIC=1          DIC=2          DIC=3
515
              //              -------------  -------------  -------------  -------------
516
              // PktLen       IFG      Next  IFG      Next  IFG      Next  IFG      Next
517
              // Modulus      Length   DIC   Length   DIC   Length   DIC   Length   DIC
518
              // -----------------------------------------------------------------------
519
              //    0           12      0      12      1      12      2      12      3
520
              //    1           11      1      11      2      11      3      15      0
521
              //    2           10      2      10      3      14      0      14      1
522
              //    3            9      3      13      0      13      1      13      2
523
              //
524
              //
525
              // In logic it translates into adding 4, 8, or 12 bytes of IFG relative
526
              // to LANE0.
527
              //   IFG and Add columns assume no deficit applied
528
              //   IFG+DIC and Add+DIC assume deficit must be applied
529
              //
530 20 antanguay
              //                        Start lane 0       Start lane 4
531 2 antanguay
              // EOP Pads IFG  IFG+DIC  Add   Add+DIC      Add    Add IFG
532
              // 0   3    11   15        8     12           12     16
533
              // 1   2    10   14        8     12           12     16
534
              // 2   1    9    13        8     12           12     16
535
              // 3   8    12   12        4     4            8      8
536
              // 4   7    11   15        4     8            8      12
537
              // 5   6    10   14        4     8            8      12
538
              // 6   5    9    13        4     8            8      12
539
              // 7   4    12   12        8     8            12     12
540
 
541
              if (!frame_available) begin
542
 
543
                  // If there is not another frame ready to be transmitted, interface
544
                  // will go idle and idle deficit idle count calculation is irrelevant.
545 20 antanguay
 
546 2 antanguay
                  next_ifg_4b_add = 1'b0;
547
                  next_ifg_8b_add = 1'b0;
548
                  next_ifg_8b2_add = 1'b0;
549
 
550
              end
551
              else if (next_ifg_deficit[2] == ifg_deficit[2]) begin
552
 
553
                  // Add 4 bytes IFG
554 20 antanguay
 
555 6 antanguay
                  next_ifg_4b_add = (eop[0] & !start_on_lane0) |
556
                                    (eop[1] & !start_on_lane0) |
557
                                    (eop[2] & !start_on_lane0) |
558
                                    (eop[3] & start_on_lane0) |
559
                                    (eop[4] & start_on_lane0) |
560
                                    (eop[5] & start_on_lane0) |
561
                                    (eop[6] & start_on_lane0) |
562
                                    (eop[7] & !start_on_lane0);
563 2 antanguay
 
564
                  // Add 8 bytes IFG
565 20 antanguay
 
566 6 antanguay
                  next_ifg_8b_add = (eop[0]) |
567
                                    (eop[1]) |
568
                                    (eop[2]) |
569
                                    (eop[3] & !start_on_lane0) |
570
                                    (eop[4] & !start_on_lane0) |
571
                                    (eop[5] & !start_on_lane0) |
572
                                    (eop[6] & !start_on_lane0) |
573
                                    (eop[7]);
574 2 antanguay
 
575
                  // Add another 8 bytes IFG
576
 
577
                  next_ifg_8b2_add = 1'b0;
578
 
579
              end
580
              else begin
581
 
582
                  // Add 4 bytes IFG
583
 
584 6 antanguay
                  next_ifg_4b_add = (eop[0] & start_on_lane0) |
585
                                    (eop[1] & start_on_lane0) |
586
                                    (eop[2] & start_on_lane0) |
587
                                    (eop[3] &  start_on_lane0) |
588
                                    (eop[4] & !start_on_lane0) |
589
                                    (eop[5] & !start_on_lane0) |
590
                                    (eop[6] & !start_on_lane0) |
591
                                    (eop[7] & !start_on_lane0);
592 2 antanguay
 
593
                  // Add 8 bytes IFG
594 20 antanguay
 
595 6 antanguay
                  next_ifg_8b_add = (eop[0]) |
596
                                    (eop[1]) |
597
                                    (eop[2]) |
598
                                    (eop[3] & !start_on_lane0) |
599
                                    (eop[4]) |
600
                                    (eop[5]) |
601
                                    (eop[6]) |
602
                                    (eop[7]);
603 2 antanguay
 
604
                  // Add another 8 bytes IFG
605
 
606 6 antanguay
                  next_ifg_8b2_add = (eop[0] & !start_on_lane0) |
607
                                     (eop[1] & !start_on_lane0) |
608
                                     (eop[2] & !start_on_lane0);
609 2 antanguay
 
610
              end
611
 
612 6 antanguay
              if (|eop[2:0]) begin
613 2 antanguay
 
614
                  if (frame_available) begin
615
 
616
                      // Next state depends on number of IFG bytes to be inserted.
617
                      // Skip idle state if needed.
618
 
619
                      if (next_ifg_8b2_add) begin
620 10 antanguay
                          next_state_enc = SM_IFG;
621 2 antanguay
                      end
622
                      else if (next_ifg_8b_add) begin
623 10 antanguay
                          next_state_enc = SM_IDLE;
624 2 antanguay
                      end
625
                      else begin
626
                          txhfifo_ren = 1'b1;
627 10 antanguay
                          next_state_enc = SM_PREAMBLE;
628 2 antanguay
                      end
629
 
630
                  end
631
                  else begin
632 10 antanguay
                      next_state_enc = SM_IFG;
633 2 antanguay
                  end
634
              end
635
 
636 6 antanguay
              if (|eop[7:3]) begin
637 10 antanguay
                  next_state_enc = SM_TERM;
638 2 antanguay
              end
639
 
640
          end
641
 
642
        SM_TERM:
643
          begin
644
 
645
              // Insert TERMINATE character in correct lane depending on position
646
              // of EOP read from fifo. Also insert CRC read from control fifo.
647
 
648 6 antanguay
              if (eop[3]) begin
649 2 antanguay
                  next_xgxs_txd = {{7{`IDLE}}, `TERMINATE};
650
                  next_xgxs_txc = 8'b11111111;
651
              end
652
 
653 6 antanguay
              if (eop[4]) begin
654 2 antanguay
                  next_xgxs_txd = {{6{`IDLE}}, `TERMINATE, crc32_tx[31:24]};
655
                  next_xgxs_txc = 8'b11111110;
656
              end
657
 
658 6 antanguay
              if (eop[5]) begin
659 2 antanguay
                  next_xgxs_txd = {{5{`IDLE}}, `TERMINATE, crc32_tx[31:16]};
660
                  next_xgxs_txc = 8'b11111100;
661
              end
662
 
663 6 antanguay
              if (eop[6]) begin
664 2 antanguay
                  next_xgxs_txd = {{4{`IDLE}}, `TERMINATE, crc32_tx[31:8]};
665
                  next_xgxs_txc = 8'b11111000;
666
              end
667
 
668 6 antanguay
              if (eop[7]) begin
669 2 antanguay
                  next_xgxs_txd = {{3{`IDLE}}, `TERMINATE, crc32_tx[31:0]};
670
                  next_xgxs_txc = 8'b11110000;
671
              end
672
 
673
              // Next state depends on number of IFG bytes to be inserted.
674
              // Skip idle state if needed.
675
 
676
              if (frame_available && !ifg_8b_add) begin
677
                  txhfifo_ren = 1'b1;
678 10 antanguay
                  next_state_enc = SM_PREAMBLE;
679 2 antanguay
              end
680
              else if (frame_available) begin
681 10 antanguay
                  next_state_enc = SM_IDLE;
682 2 antanguay
              end
683
              else begin
684 10 antanguay
                  next_state_enc = SM_IFG;
685 2 antanguay
              end
686
 
687
          end
688
 
689
        SM_TERM_FAIL:
690
          begin
691
 
692
              next_xgxs_txd = {{7{`IDLE}}, `TERMINATE};
693
              next_xgxs_txc = 8'b11111111;
694 10 antanguay
              next_state_enc = SM_IFG;
695 2 antanguay
 
696
          end
697
 
698
        SM_IFG:
699
          begin
700
 
701 10 antanguay
              next_state_enc = SM_IDLE;
702 2 antanguay
 
703
          end
704
 
705
        default:
706
          begin
707 10 antanguay
              next_state_enc = SM_IDLE;
708 2 antanguay
          end
709
 
710
    endcase
711
 
712
end
713
 
714
 
715
always @(/*AS*/crc32_d64 or txhfifo_wen or txhfifo_wstatus) begin
716
 
717 6 antanguay
    if (txhfifo_wen && txhfifo_wstatus[`TXSTATUS_SOP]) begin
718 2 antanguay
        crc_data = 32'hffffffff;
719
    end
720
    else begin
721
        crc_data = crc32_d64;
722
    end
723 20 antanguay
 
724 2 antanguay
end
725
 
726 10 antanguay
always @(/*AS*/byte_cnt or curr_state_pad or txdfifo_rdata
727 6 antanguay
         or txdfifo_rempty or txdfifo_ren_d1 or txdfifo_rstatus
728 2 antanguay
         or txhfifo_walmost_full) begin
729
 
730 10 antanguay
    next_state_pad = curr_state_pad;
731 2 antanguay
 
732
    next_txhfifo_wdata = txdfifo_rdata;
733
    next_txhfifo_wstatus = txdfifo_rstatus;
734
 
735
    txdfifo_ren = 1'b0;
736
    next_txhfifo_wen = 1'b0;
737
 
738 10 antanguay
    case (curr_state_pad)
739 2 antanguay
 
740 10 antanguay
      SM_PAD_EQ: begin
741 2 antanguay
 
742
 
743 6 antanguay
          //---
744
          // If room availabe in hoding fifo and data available in
745
          // data fifo, transfer data words. If transmit state machine
746
          // is reading from fifo we can assume room will be available.
747 2 antanguay
 
748 6 antanguay
          if (!txhfifo_walmost_full) begin
749
 
750
              txdfifo_ren = !txdfifo_rempty;
751
 
752 2 antanguay
          end
753
 
754
 
755 6 antanguay
          //---
756
          // This logic dependent on read during previous cycle.
757 2 antanguay
 
758 6 antanguay
          if (txdfifo_ren_d1) begin
759
 
760 2 antanguay
              next_txhfifo_wen = 1'b1;
761
 
762 6 antanguay
              // On EOP, decide if padding is required for this packet.
763 2 antanguay
 
764 6 antanguay
              if (txdfifo_rstatus[`TXSTATUS_EOP]) begin
765 2 antanguay
 
766 23 antanguay
                  if (byte_cnt < 14'd60) begin
767 2 antanguay
 
768
                      next_txhfifo_wstatus = `TXSTATUS_NONE;
769 6 antanguay
                      txdfifo_ren = 1'b0;
770 10 antanguay
                      next_state_pad = SM_PAD_PAD;
771 2 antanguay
 
772
                  end
773 23 antanguay
                  else if (byte_cnt == 14'd60 &&
774 6 antanguay
                           (txdfifo_rstatus[2:0] == 3'd1 ||
775
                            txdfifo_rstatus[2:0] == 3'd2 ||
776
                            txdfifo_rstatus[2:0] == 3'd3)) begin
777 2 antanguay
 
778
                      // Pad up to LANE3, keep the other 4 bytes for crc that will
779
                      // be inserted by dequeue engine.
780 20 antanguay
 
781 6 antanguay
                      next_txhfifo_wstatus[2:0] = 3'd4;
782 2 antanguay
 
783
                      // Pad end bytes with zeros.
784
 
785 6 antanguay
                      if (txdfifo_rstatus[2:0] == 3'd1)
786 2 antanguay
                        next_txhfifo_wdata[31:8] = 24'b0;
787 6 antanguay
                      if (txdfifo_rstatus[2:0] == 3'd2)
788 2 antanguay
                        next_txhfifo_wdata[31:16] = 16'b0;
789 6 antanguay
                      if (txdfifo_rstatus[2:0] == 3'd3)
790 2 antanguay
                        next_txhfifo_wdata[31:24] = 8'b0;
791
 
792 6 antanguay
                      txdfifo_ren = 1'b0;
793 2 antanguay
 
794
                  end
795
                  else begin
796
 
797 6 antanguay
                      txdfifo_ren = 1'b0;
798 20 antanguay
 
799 2 antanguay
                  end
800
 
801
              end
802 20 antanguay
 
803 2 antanguay
          end
804
 
805
      end
806
 
807 10 antanguay
      SM_PAD_PAD: begin
808 2 antanguay
 
809 6 antanguay
          //---
810
          // Pad packet to 64 bytes by writting zeros to holding fifo.
811 2 antanguay
 
812 6 antanguay
          if (!txhfifo_walmost_full) begin
813
 
814 2 antanguay
              next_txhfifo_wdata = 64'b0;
815
              next_txhfifo_wstatus = `TXSTATUS_NONE;
816
              next_txhfifo_wen = 1'b1;
817 20 antanguay
 
818 23 antanguay
              if (byte_cnt == 14'd60) begin
819 2 antanguay
 
820
 
821
                  // Pad up to LANE3, keep the other 4 bytes for crc that will
822
                  // be inserted by dequeue engine.
823
 
824 6 antanguay
                  next_txhfifo_wstatus[`TXSTATUS_EOP] = 1'b1;
825
                  next_txhfifo_wstatus[2:0] = 3'd4;
826 2 antanguay
 
827 10 antanguay
                  next_state_pad = SM_PAD_EQ;
828 2 antanguay
 
829
              end
830
 
831
          end
832
 
833
      end
834
 
835
      default:
836
        begin
837 10 antanguay
            next_state_pad = SM_PAD_EQ;
838 2 antanguay
        end
839
 
840
    endcase
841
 
842
end
843
 
844
 
845
always @(posedge clk_xgmii_tx or negedge reset_xgmii_tx_n) begin
846
 
847
    if (reset_xgmii_tx_n == 1'b0) begin
848
 
849 10 antanguay
        curr_state_pad <= SM_PAD_EQ;
850 2 antanguay
 
851 6 antanguay
        txdfifo_ren_d1 <= 1'b0;
852
 
853 2 antanguay
        txhfifo_wdata <= 64'b0;
854
        txhfifo_wstatus <= 8'b0;
855 20 antanguay
        txhfifo_wen <= 1'b0;
856 2 antanguay
 
857
        byte_cnt <= 14'b0;
858
 
859
        shift_crc_data <= 64'b0;
860 6 antanguay
        shift_crc_eop <= 4'b0;
861
        shift_crc_cnt <= 4'b0;
862 2 antanguay
 
863 20 antanguay
        crc32_d64 <= 32'b0;
864
        crc32_d8 <= 32'b0;
865
        crc32_tx <= 32'b0;
866
 
867 23 antanguay
        frame_end <= 1'b0;
868
 
869 2 antanguay
    end
870
    else begin
871
 
872 10 antanguay
        curr_state_pad <= next_state_pad;
873 2 antanguay
 
874 6 antanguay
        txdfifo_ren_d1 <= txdfifo_ren;
875
 
876 2 antanguay
        txhfifo_wdata <= next_txhfifo_wdata;
877
        txhfifo_wstatus <= next_txhfifo_wstatus;
878
        txhfifo_wen <= next_txhfifo_wen;
879
 
880 23 antanguay
        frame_end <= 1'b0;
881 2 antanguay
 
882 6 antanguay
        //---
883
        // Reset byte count on SOP
884 20 antanguay
 
885 6 antanguay
        if (next_txhfifo_wen) begin
886 2 antanguay
 
887 6 antanguay
            if (next_txhfifo_wstatus[`TXSTATUS_SOP]) begin
888
 
889 23 antanguay
                // Init byte count, 8-bytes + 4-bytes for CRC at the end of frame
890 2 antanguay
 
891 23 antanguay
                byte_cnt <= 14'd12;
892
 
893 2 antanguay
            end
894
            else begin
895
 
896 23 antanguay
                if (next_txhfifo_wstatus[`TXSTATUS_EOP] && next_txhfifo_wstatus[2:0] != 3'b0) begin
897 2 antanguay
 
898 23 antanguay
                    byte_cnt <= byte_cnt + {11'b0, next_txhfifo_wstatus[2:0]};
899
 
900
                end
901
                else begin
902
 
903
                    byte_cnt <= byte_cnt + 14'd8;
904
 
905
                end
906
 
907 2 antanguay
            end
908
 
909 23 antanguay
            frame_end <= next_txhfifo_wstatus[`TXSTATUS_EOP];
910
 
911 2 antanguay
        end
912
 
913 6 antanguay
 
914
        //---
915
        // Calculate CRC as data is written to holding fifo. The holding fifo creates
916
        // a delay that allow the CRC calculation to complete before the end of the frame
917
        // is ready to be transmited.
918
 
919 2 antanguay
        if (txhfifo_wen) begin
920
 
921
            crc32_d64 <= nextCRC32_D64(reverse_64b(txhfifo_wdata), crc_data);
922
 
923
        end
924
 
925 6 antanguay
        if (txhfifo_wen && txhfifo_wstatus[`TXSTATUS_EOP]) begin
926 2 antanguay
 
927
            // Last bytes calculated 8-bit at a time instead of 64-bit. Start
928
            // this process at the end of the frame.
929 20 antanguay
 
930 2 antanguay
            crc32_d8 <= crc32_d64;
931
 
932
            shift_crc_data <= txhfifo_wdata;
933 6 antanguay
            shift_crc_cnt <= 4'd9;
934 2 antanguay
 
935 6 antanguay
            if (txhfifo_wstatus[2:0] == 3'b0) begin
936
              shift_crc_eop <= 4'd8;
937
            end
938
            else begin
939
                shift_crc_eop <= {1'b0, txhfifo_wstatus[2:0]};
940
            end
941
 
942 2 antanguay
        end
943 6 antanguay
        else if (shift_crc_eop != 4'b0) begin
944 2 antanguay
 
945
            // Complete crc calculation 8-bit at a time until finished. This can
946
            // be 1 to 8 bytes long.
947
 
948
            crc32_d8 <= nextCRC32_D8(reverse_8b(shift_crc_data[7:0]), crc32_d8);
949
 
950
            shift_crc_data <= {8'b0, shift_crc_data[63:8]};
951 6 antanguay
            shift_crc_eop <= shift_crc_eop - 4'd1;
952 20 antanguay
 
953 2 antanguay
        end
954
 
955 6 antanguay
 
956
        //---
957
        // Update CRC register at the end of calculation. Always update after 8
958
        // cycles for deterministic results, even if a single byte was present in
959
        // last data word.
960 20 antanguay
 
961 6 antanguay
        if (shift_crc_cnt == 4'b1) begin
962
 
963 2 antanguay
            crc32_tx <= ~reverse_32b(crc32_d8);
964 6 antanguay
 
965 2 antanguay
        end
966
        else begin
967 6 antanguay
 
968
            shift_crc_cnt <= shift_crc_cnt - 4'd1;
969
 
970 2 antanguay
        end
971
 
972
    end
973
 
974
end
975
 
976
endmodule

powered by: WebSVN 2.1.0

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