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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [eth_phy.v] - Blame information for rev 408

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

Line No. Rev Author Line
1 408 julius
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name: eth_phy.v                                        ////
4
////                                                              ////
5
////  This file is part of the Ethernet IP core project           ////
6
////  http://www.opencores.org/projects/ethmac/                   ////
7
////                                                              ////
8
////  Author(s):                                                  ////
9
////      - Tadej Markovic, tadej@opencores.org                   ////
10
////                                                              ////
11
////  All additional information is available in the README.txt   ////
12
////  file.                                                       ////
13
////                                                              ////
14
//////////////////////////////////////////////////////////////////////
15
////                                                              ////
16
//// Copyright (C) 2002  Authors                                  ////
17
////                                                              ////
18
//// This source file may be used and distributed without         ////
19
//// restriction provided that this copyright statement is not    ////
20
//// removed from the file and that any derivative work contains  ////
21
//// the original copyright notice and the associated disclaimer. ////
22
////                                                              ////
23
//// This source file is free software; you can redistribute it   ////
24
//// and/or modify it under the terms of the GNU Lesser General   ////
25
//// Public License as published by the Free Software Foundation; ////
26
//// either version 2.1 of the License, or (at your option) any   ////
27
//// later version.                                               ////
28
////                                                              ////
29
//// This source is distributed in the hope that it will be       ////
30
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
31
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
32
//// PURPOSE.  See the GNU Lesser General Public License for more ////
33
//// details.                                                     ////
34
////                                                              ////
35
//// You should have received a copy of the GNU Lesser General    ////
36
//// Public License along with this source; if not, download it   ////
37
//// from http://www.opencores.org/lgpl.shtml                     ////
38
////                                                              ////
39
//////////////////////////////////////////////////////////////////////
40
//
41
// CVS Revision History
42
//
43
// $Log: not supported by cvs2svn $
44
// Revision 1.7  2002/10/18 13:58:22  tadejm
45
// Some code changed due to bug fixes.
46
//
47
// Revision 1.6  2002/10/09 13:16:51  tadejm
48
// Just back-up; not completed testbench and some testcases are not
49
// wotking properly yet.
50
//
51
// Revision 1.5  2002/09/18 17:55:08  tadej
52
// Bug repaired in eth_phy device
53
//
54
// Revision 1.3  2002/09/13 14:50:15  mohor
55
// Bug in MIIM fixed.
56
//
57
// Revision 1.2  2002/09/13 12:29:14  mohor
58
// Headers changed.
59
//
60
// Revision 1.1  2002/09/13 11:57:20  mohor
61
// New testbench. Thanks to Tadej M - "The Spammer".
62
//
63
//
64
//
65
 
66
`include "timescale.v"
67
`include "eth_phy_defines.v"
68
 
69
// ORPSoCv2 testbench include
70
// Will enable verbose if eth test
71
`ifdef TEST_DEFINE_FILE
72
 `include "test_define.v"
73
`endif
74
 
75
 
76
`define MULTICAST_XFR          0
77
`define UNICAST_XFR            1
78
`define BROADCAST_XFR          2
79
`define UNICAST_WRONG_XFR      3
80
 
81
 
82
`define ETH_PHY_VERBOSE 1
83
 
84
module eth_phy // This PHY model simulate simplified Intel LXT971A PHY
85
  (
86
   // COMMON
87
   m_rst_n_i,
88
 
89
   // MAC TX
90
   mtx_clk_o,
91
   mtxd_i,
92
   mtxen_i,
93
   mtxerr_i,
94
 
95
   // MAC RX
96
   mrx_clk_o,
97
   mrxd_o,
98
   mrxdv_o,
99
   mrxerr_o,
100
 
101
   // SMII signals
102
   smii_clk_i,
103
   smii_sync_i,
104
   smii_rx_o,
105
 
106
   mcoll_o,
107
   mcrs_o,
108
 
109
   // MIIM
110
   mdc_i,
111
   md_io,
112
   speed_o,
113
   link_o,
114
   duplex_o
115
   );
116
 
117
   //////////////////////////////////////////////////////////////////////
118
         //
119
   // Input/output signals
120
   //
121
   //////////////////////////////////////////////////////////////////////
122
 
123
   // MAC miscellaneous signals
124
   input           m_rst_n_i;
125
   // MAC TX signals
126
   output          mtx_clk_o;
127
   input [3:0]      mtxd_i;
128
   input           mtxen_i;
129
   input           mtxerr_i;
130
   // MAC RX signals
131
   output          mrx_clk_o;
132
   output [3:0]    mrxd_o;
133
   output          mrxdv_o;
134
   output          mrxerr_o;
135
   // SMII RX signals
136
   input           smii_clk_i;
137
   input           smii_sync_i;
138
   output          smii_rx_o;
139
 
140
   // MAC common signals
141
   output          mcoll_o;
142
   output          mcrs_o;
143
   // MAC management signals
144
   input           mdc_i;
145
   inout           md_io;
146
   // Sideband signals for SMII -- jb
147
   output          link_o;
148
   output          speed_o;
149
   output          duplex_o;
150
 
151
 
152
   //////////////////////////////////////////////////////////////////////
153
   //
154
   // PHY management (MIIM) REGISTER definitions
155
   //
156
   //////////////////////////////////////////////////////////////////////
157
   //
158
   //   Supported registers:
159
   //
160
   // Addr | Register Name
161
   //--------------------------------------------------------------------
162
   //   0  | Control reg.     |
163
   //   1  | Status reg. #1   |--> normal operation
164
   //   2  | PHY ID reg. 1    |
165
   //   3  | PHY ID reg. 2    |
166
   //----------------------
167
   // Addr | Data MEMORY      |-->  for testing
168
   //
169
   //--------------------------------------------------------------------
170
   //
171
   // Control register
172
   reg             control_bit15; // self clearing bit
173
   reg [14:10]     control_bit14_10 = 5'b01000; // Init to 100MBPs (speed set)
174
   reg             control_bit9; // self clearing bit
175
   reg [8:0]        control_bit8_0;
176
   // Status register
177
   wire [15:9]     status_bit15_9 = `SUPPORTED_SPEED_AND_PORT;
178
   wire            status_bit8    = `EXTENDED_STATUS;
179
   wire            status_bit7    = 1'b0; // reserved
180
   reg [6:0]        status_bit6_0;
181
   // PHY ID register 1
182
   wire [15:0]      phy_id1        = `PHY_ID1;
183
   // PHY ID register 2
184
   wire [15:0]      phy_id2        = {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM};
185
   //--------------------------------------------------------------------
186
   //
187
   // Data MEMORY
188
   reg [15:0]       data_mem [0:31]; // 32 locations of 16-bit data width
189
   //
190
   //////////////////////////////////////////////////////////////////////
191
 
192
 
193
   //////////////////////////////////////////////////////////////////////
194
   //
195
   // PHY clocks - RX & TX
196
   //
197
   //////////////////////////////////////////////////////////////////////
198
 
199
   reg             mtx_clk_o;
200
   reg             mrx_clk_o;
201
 
202
   // random generator for a RX period when link is down
203
   real            rx_link_down_halfperiod;
204
 
205
   always@(status_bit6_0[2])
206
     begin
207
        if (!status_bit6_0[2]) // Link is down
208
          begin
209
             #1 rx_link_down_halfperiod = ({$random} % 243) + 13;
210
`ifdef ETH_PHY_VERBOSE
211
             #1 $display( "(%0t)(%m)MAC RX clock is %f MHz while ethernet link is down!",
212
                          $time, (1000/(rx_link_down_halfperiod*2)) );
213
`endif
214
          end
215
     end
216
 
217
`ifdef ETH_PHY_VERBOSE
218
   always@(status_bit6_0[2])
219
     begin
220
        if (!status_bit6_0[2]) // Link is down
221
          #1 $display( "(%0t)(%m)Ethernet link is down!", $time);
222
        else
223
          #1 $display( "(%0t)(%m)Ethernet link is up!", $time);
224
     end
225
`endif
226
 
227
   // speed selection signal eth_speed: 1'b1 - 100 Mbps, 1'b0 - 10 Mbps
228
   wire      eth_speed;
229
 
230
   assign eth_speed = ( (control_bit14_10[13]) && !((`LED_CFG1) && (`LED_CFG2)) );
231
 
232
`ifdef ETH_PHY_VERBOSE
233
   always@(eth_speed)
234
     begin
235
        if (eth_speed)
236
          #1 $display( "(%0t)(%m)PHY configured to 100 Mbps!", $time);
237
        else
238
          #1 $display( "(%0t)(%m)PHY configured tp 10 Mbps!", $time);
239
     end
240
`endif
241
 
242
   // different clock calculation between RX and TX, so that there is alsways a litle difference
243
   /*initial
244
    begin
245
    set_mrx_equal_mtx = 1; // default
246
end*/
247
 
248
   always
249
     begin
250
        mtx_clk_o = 0;
251
        #7;
252
        forever
253
          begin
254
             if (eth_speed) // 100 Mbps - 25 MHz, 40 ns
255
               begin
256
                  #20 mtx_clk_o = ~mtx_clk_o;
257
               end
258
             else // 10 Mbps - 2.5 MHz, 400 ns
259
               begin
260
                  #200 mtx_clk_o = ~mtx_clk_o;
261
               end
262
          end
263
     end
264
 
265
   always
266
     begin
267
        // EQUAL mrx_clk to mtx_clk
268
        mrx_clk_o = 0;
269
        #7;
270
        forever
271
          begin
272
             if (eth_speed) // 100 Mbps - 25 MHz, 40 ns
273
               begin
274
                  #20 mrx_clk_o = ~mrx_clk_o;
275
               end
276
             else // 10 Mbps - 2.5 MHz, 400 ns
277
               begin
278
                  #200 mrx_clk_o = ~mrx_clk_o;
279
               end
280
          end
281
        // DIFFERENT mrx_clk than mtx_clk
282
        /*  mrx_clk_diff_than_mtx = 1;
283
         #3;
284
         forever
285
         begin
286
         if (status_bit6_0[2]) // Link is UP
287
         begin
288
         if (eth_speed) // 100 Mbps - 25 MHz, 40 ns
289
         begin
290
         //#(((1/0.025001)/2))
291
         #19.99 mrx_clk_diff_than_mtx = ~mrx_clk_diff_than_mtx; // period is calculated from frequency in GHz
292
      end
293
         else // 10 Mbps - 2.5 MHz, 400 ns
294
         begin
295
         //#(((1/0.0024999)/2))
296
         #200.01 mrx_clk_diff_than_mtx = ~mrx_clk_diff_than_mtx; // period is calculated from frequency in GHz
297
      end
298
    end
299
         else // Link is down
300
         begin
301
         #(rx_link_down_halfperiod) mrx_clk_diff_than_mtx = ~mrx_clk_diff_than_mtx; // random frequency between 2 MHz and 40 MHz
302
    end
303
  end*/
304
        //  // set output mrx_clk
305
        //  if (set_mrx_equal_mtx)
306
        //    mrx_clk_o = mrx_clk_equal_to_mtx;
307
        //  else
308
        //    mrx_clk_o = mrx_clk_diff_than_mtx;
309
     end
310
 
311
   // set output mrx_clk
312
   //assign mrx_clk_o = set_mrx_equal_mtx ? mrx_clk_equal_to_mtx : mrx_clk_diff_than_mtx ;
313
 
314
   //////////////////////////////////////////////////////////////////////
315
   //
316
   // PHY management (MIIM) interface
317
   //
318
   //////////////////////////////////////////////////////////////////////
319
   reg             respond_to_all_phy_addr; // PHY will respond to all phy addresses
320
   reg             no_preamble; // PHY responds to frames without preamble
321
 
322
   integer         md_transfer_cnt; // counter countes the value of whole data transfer
323
   reg             md_transfer_cnt_reset; // for reseting the counter
324
   reg             md_io_reg; // registered input
325
   reg             md_io_output; // registered output
326
   reg             md_io_rd_wr;  // op-code latched (read or write)
327
   reg             md_io_enable; // output enable
328
   reg [4:0]        phy_address; // address of PHY device
329
   reg [4:0]        reg_address; // address of a register
330
   reg             md_get_phy_address; // for shifting PHY address in
331
   reg             md_get_reg_address; // for shifting register address in
332
   reg [15:0]       reg_data_in; // data to be written in a register
333
   reg             md_get_reg_data_in; // for shifting data in
334
   reg             md_put_reg_data_in; // for storing data into a selected register
335
   reg [15:0]       reg_data_out; // data to be read from a register
336
   reg             md_put_reg_data_out; // for registering data from a selected register
337
 
338
   wire [15:0]      register_bus_in; // data bus to a selected register
339
   reg [15:0]       register_bus_out; // data bus from a selected register
340
 
341
   initial
342
     begin
343
        md_io_enable = 1'b0;
344
        respond_to_all_phy_addr = 1'b0;
345
        no_preamble = 1'b0;
346
     end
347
 
348
   // tristate output
349
   assign #1 md_io = (m_rst_n_i && md_io_enable) ? md_io_output : 1'bz ;
350
 
351
   // registering input
352
   always@(posedge mdc_i or negedge m_rst_n_i)
353
     begin
354
        if (!m_rst_n_i)
355
          md_io_reg <= #1 0;
356
        else
357
          md_io_reg <= #1 md_io;
358
     end
359
 
360
   // getting (shifting) PHY address, Register address and Data in
361
   // putting Data out and shifting
362
   always@(posedge mdc_i or negedge m_rst_n_i)
363
     begin
364
        if (!m_rst_n_i)
365
          begin
366
             phy_address <= 0;
367
             reg_address <= 0;
368
             reg_data_in <= 0;
369
             reg_data_out <= 0;
370
             md_io_output <= 0;
371
          end
372
        else
373
          begin
374
             if (md_get_phy_address)
375
               begin
376
                  phy_address[4:1] <= phy_address[3:0]; // correct address is `ETH_PHY_ADDR
377
                  phy_address[0]   <= md_io;
378
               end
379
             if (md_get_reg_address)
380
               begin
381
                  reg_address[4:1] <= reg_address[3:0];
382
                  reg_address[0]   <= md_io;
383
               end
384
             if (md_get_reg_data_in)
385
               begin
386
                  reg_data_in[15:1] <= reg_data_in[14:0];
387
                  reg_data_in[0]    <= md_io;
388
               end
389
             if (md_put_reg_data_out)
390
               begin
391
                  reg_data_out <= register_bus_out;
392
               end
393
             if (md_io_enable)
394
               begin
395
                  md_io_output       <= reg_data_out[15];
396
                  reg_data_out[15:1] <= reg_data_out[14:0];
397
                  reg_data_out[0]    <= 1'b0;
398
               end
399
          end
400
     end
401
 
402
   assign #1 register_bus_in = reg_data_in; // md_put_reg_data_in - allows writing to a selected register
403
 
404
   // counter for transfer to and from MIIM
405
   always@(posedge mdc_i or negedge m_rst_n_i)
406
     begin
407
        if (!m_rst_n_i)
408
          begin
409
             if (no_preamble)
410
               md_transfer_cnt <= 33;
411
             else
412
               md_transfer_cnt <= 1;
413
          end
414
        else
415
          begin
416
             if (md_transfer_cnt_reset)
417
               begin
418
                  if (no_preamble)
419
                    md_transfer_cnt <= 33;
420
                  else
421
                    md_transfer_cnt <= 1;
422
               end
423
             else if (md_transfer_cnt < 64)
424
               begin
425
                  md_transfer_cnt <= md_transfer_cnt + 1'b1;
426
               end
427
             else
428
               begin
429
                  if (no_preamble)
430
                    md_transfer_cnt <= 33;
431
                  else
432
                    md_transfer_cnt <= 1;
433
               end
434
          end
435
     end
436
 
437
   // MIIM transfer control
438
   always@(m_rst_n_i or md_transfer_cnt or md_io_reg or md_io_rd_wr or
439
           phy_address or respond_to_all_phy_addr or no_preamble)
440
     begin
441
        #1;
442
        while ((m_rst_n_i) && (md_transfer_cnt <= 64))
443
          begin
444
             // reset the signal - put registered data in the register (when write)
445
             // check preamble
446
             if (md_transfer_cnt < 33)
447
               begin
448
                  #4 md_put_reg_data_in = 1'b0;
449
                  if (md_io_reg !== 1'b1)
450
                    begin
451
                       #1 md_transfer_cnt_reset = 1'b1;
452
                    end
453
                  else
454
                    begin
455
                       #1 md_transfer_cnt_reset = 1'b0;
456
                    end
457
               end
458
 
459
             // check start bits
460
             else if (md_transfer_cnt == 33)
461
               begin
462
                  if (no_preamble)
463
                    begin
464
                       #4 md_put_reg_data_in = 1'b0;
465
                       if (md_io_reg === 1'b0)
466
                         begin
467
                            #1 md_transfer_cnt_reset = 1'b0;
468
                         end
469
                       else
470
                         begin
471
                            #1 md_transfer_cnt_reset = 1'b1;
472
                            //if ((md_io_reg !== 1'bz) && (md_io_reg !== 1'b1))
473
                            if (md_io_reg !== 1'bz)
474
                              begin
475
                                 // ERROR - start !
476
`ifdef ETH_PHY_VERBOSE
477
                                 $display( "*E (%0t)(%m)MIIM - wrong first start bit (without preamble)", $time);
478
`endif
479
                                 #10 $stop;
480
                              end
481
                         end
482
                    end
483
                  else // with preamble
484
                    begin
485
                       #4 ;
486
`ifdef ETH_PHY_VERBOSE
487
                       $display( "(%0t)(%m)MIIM - 32-bit preamble received", $time);
488
`endif
489
                       // check start bit only if md_transfer_cnt_reset is inactive, because if
490
                       // preamble suppression was changed start bit should not be checked
491
                       if ((md_io_reg !== 1'b0) && (md_transfer_cnt_reset == 1'b0))
492
                         begin
493
                            // ERROR - start !
494
`ifdef ETH_PHY_VERBOSE
495
                            $display( "*E (%0t)(%m)MIIM - wrong first start bit", $time);
496
`endif
497
                            #10 $stop;
498
                         end
499
                    end
500
               end
501
 
502
             else if (md_transfer_cnt == 34)
503
               begin
504
                  #4;
505
                  if (md_io_reg !== 1'b1)
506
                    begin
507
                       // ERROR - start !
508
                       #1;
509
`ifdef ETH_PHY_VERBOSE
510
                       if (no_preamble)
511
                         $display( "*E (%0t)(%m)MIIM - wrong second start bit (without preamble)", $time);
512
                       else
513
                         $display( "*E (%0t)(%m)MIIM - wrong second start bit", $time);
514
`endif
515
                       #10 $stop;
516
                    end
517
                  else
518
                    begin
519
`ifdef ETH_PHY_VERBOSE
520
                       if (no_preamble)
521
                         #1 $display( "(%0t)(%m)MIIM - 2 start bits received (without preamble)", $time);
522
                       else
523
                         #1 $display( "(%0t)(%m)MIIM - 2 start bits received", $time);
524
`endif
525
                    end
526
               end
527
 
528
             // register the op-code (rd / wr)
529
             else if (md_transfer_cnt == 35)
530
               begin
531
                  #4;
532
                  if (md_io_reg === 1'b1)
533
                    begin
534
                       #1 md_io_rd_wr = 1'b1;
535
                    end
536
                  else
537
                    begin
538
                       #1 md_io_rd_wr = 1'b0;
539
                    end
540
               end
541
 
542
             else if (md_transfer_cnt == 36)
543
               begin
544
                  #4;
545
                  if ((md_io_reg === 1'b0) && (md_io_rd_wr == 1'b1))
546
                    begin
547
                       #1 md_io_rd_wr = 1'b1; // reading from PHY registers
548
`ifdef ETH_PHY_VERBOSE
549
                       $display( "(%0t)(%m)MIIM - op-code for READING from registers", $time);
550
`endif
551
                    end
552
                  else if ((md_io_reg === 1'b1) && (md_io_rd_wr == 1'b0))
553
                    begin
554
                       #1 md_io_rd_wr = 1'b0; // writing to PHY registers
555
`ifdef ETH_PHY_VERBOSE
556
                       $display( "(%0t)(%m)MIIM - op-code for WRITING to registers", $time);
557
`endif
558
                    end
559
                  else
560
                    begin
561
                       // ERROR - wrong opcode !
562
`ifdef ETH_PHY_VERBOSE
563
                       #1 $display( "*E (%0t)(%m)MIIM - wrong OP-CODE", $time);
564
`endif
565
                       #10 $stop;
566
                    end
567
                  // set the signal - get PHY address
568
                  begin
569
                     #1 md_get_phy_address = 1'b1;
570
                  end
571
               end
572
 
573
             // reset the signal - get PHY address
574
             else if (md_transfer_cnt == 41)
575
               begin
576
                  #4 md_get_phy_address = 1'b0;
577
                  // set the signal - get register address
578
                  #1 md_get_reg_address = 1'b1;
579
               end
580
 
581
             // reset the signal - get register address
582
             // set the signal - put register data to output register
583
             else if (md_transfer_cnt == 46)
584
               begin
585
                  #4 md_get_reg_address = 1'b0;
586
                  #1 md_put_reg_data_out = 1'b1;
587
               end
588
 
589
             // reset the signal - put register data to output register
590
             // set the signal - enable md_io as output when read
591
             else if (md_transfer_cnt == 47)
592
               begin
593
                  #4 md_put_reg_data_out = 1'b0;
594
                  if (md_io_rd_wr) //read
595
                    begin
596
                       if (md_io_reg !== 1'bz)
597
                         begin
598
                            // ERROR - turn around !
599
`ifdef ETH_PHY_VERBOSE
600
                            #1 $display( "*E (%0t)(%m)MIIM - wrong turn-around cycle before reading data out", $time);
601
`endif
602
                            #10 $stop;
603
                         end
604
                       if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
605
                         begin
606
                            #1 md_io_enable = 1'b1;
607
`ifdef ETH_PHY_VERBOSE
608
                            $display( "(%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address);
609
`endif
610
                         end
611
                       else
612
                         begin
613
`ifdef ETH_PHY_VERBOSE
614
                            #1 $display( "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address);
615
`endif
616
                         end
617
                    end
618
                  else // write
619
                    begin
620
                       #1 md_io_enable = 1'b0;
621
                       // check turn around cycle when write on clock 47
622
                       if (md_io_reg !== 1'b1)
623
                         begin
624
                            // ERROR - turn around !
625
`ifdef ETH_PHY_VERBOSE
626
                            #1 $display( "*E (%0t)(%m)MIIM - wrong 1. turn-around cycle before writing data in",
627
                                         $time);
628
`endif
629
                            #10 $stop;
630
                         end
631
                    end
632
               end
633
 
634
             // set the signal - get register data in when write
635
             else if (md_transfer_cnt == 48)
636
               begin
637
                  #4;
638
                  if (!md_io_rd_wr) // write
639
                    begin
640
                       #1 md_get_reg_data_in = 1'b1;
641
                       // check turn around cycle when write on clock 48
642
                       if (md_io_reg !== 1'b0)
643
                         begin
644
                            // ERROR - turn around !
645
`ifdef ETH_PHY_VERBOSE
646
                            #1 $display( "*E (%0t)(%m)MIIM - wrong 2. turn-around cycle before writing data in",
647
                                         $time);
648
`endif
649
                            #10 $stop;
650
                         end
651
                    end
652
                  else // read
653
                    begin
654
                       #1 md_get_reg_data_in = 1'b0;
655
                    end
656
               end
657
 
658
             // reset the signal - enable md_io as output when read
659
             // reset the signal - get register data in when write
660
             // set the signal - put registered data in the register when write
661
             else if (md_transfer_cnt == 64)
662
               begin
663
                  #1 md_io_enable = 1'b0;
664
                  #4 md_get_reg_data_in = 1'b0;
665
                  if (!md_io_rd_wr) // write
666
                    begin
667
                       if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
668
                         begin
669
                            #1 md_put_reg_data_in = 1'b1;
670
`ifdef ETH_PHY_VERBOSE
671
                            $display( "(%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address);
672
                            $display( "(%0t)(%m)MIIM - WRITING to register %x COMPLETED!", $time, reg_address);
673
`endif
674
                         end
675
                       else
676
                         begin
677
`ifdef ETH_PHY_VERBOSE
678
                            #1 $display( "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address);
679
                            $display( "*W (%0t)(%m)MIIM - NO WRITING to register %x !", $time, reg_address);
680
`endif
681
                         end
682
                    end
683
                  else // read
684
                    begin
685
`ifdef ETH_PHY_VERBOSE
686
                       if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
687
                         #1 $display( "(%0t)(%m)MIIM - READING from register %x COMPLETED!",
688
                                      $time, reg_address);
689
                       else
690
                         #1 $display( "*W (%0t)(%m)MIIM - NO READING from register %x !", $time, reg_address);
691
`endif
692
                    end
693
               end
694
 
695
             // wait for one clock period
696
             @(posedge mdc_i)
697
               #1;
698
          end
699
     end
700
 
701
   //====================================================================
702
   //
703
   // PHY management (MIIM) REGISTERS
704
   //
705
   //====================================================================
706
   //
707
   //   Supported registers (normal operation):
708
   //
709
   // Addr | Register Name 
710
   //--------------------------------------------------------------------
711
   //   0  | Control reg.  
712
   //   1  | Status reg. #1 
713
   //   2  | PHY ID reg. 1 
714
   //   3  | PHY ID reg. 2 
715
   //----------------------
716
   // Addr | Data MEMORY      |-->  for testing
717
   //
718
   //--------------------------------------------------------------------
719
   //
720
   // Control register
721
   //  reg            control_bit15; // self clearing bit
722
   //  reg    [14:10] control_bit14_10;
723
   //  reg            control_bit9; // self clearing bit
724
   //  reg    [8:0]   control_bit8_0;
725
   // Status register
726
   //  wire   [15:9]  status_bit15_9 = `SUPPORTED_SPEED_AND_PORT;
727
   //  wire           status_bit8    = `EXTENDED_STATUS;
728
   //  wire           status_bit7    = 1'b0; // reserved
729
   //  reg    [6:0]   status_bit6_0  = `DEFAULT_STATUS;
730
   // PHY ID register 1
731
   //  wire   [15:0]  phy_id1        = `PHY_ID1;
732
   // PHY ID register 2
733
   //  wire   [15:0]  phy_id2        = {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM};
734
   //--------------------------------------------------------------------
735
   //
736
   // Data MEMORY
737
   //  reg    [15:0]  data_mem [0:31]; // 32 locations of 16-bit data width
738
   //
739
   //====================================================================
740
 
741
   //////////////////////////////////////////////////////////////////////
742
   //
743
   // PHY management (MIIM) REGISTER control
744
   //
745
   //////////////////////////////////////////////////////////////////////
746
 
747
   // wholy writable registers for walking ONE's on data, phy and reg. addresses
748
   reg     registers_addr_data_test_operation;
749
 
750
   // Non writable status registers
751
   initial // always
752
     begin
753
        #1 status_bit6_0[6] = no_preamble;
754
        status_bit6_0[5] = 1'b0;
755
        status_bit6_0[3] = 1'b1;
756
        status_bit6_0[0] = 1'b1;
757
     end
758
   always@(posedge mrx_clk_o)
759
     begin
760
        status_bit6_0[4] <= #1 1'b0;
761
        status_bit6_0[1] <= #1 1'b0;
762
     end
763
   initial
764
     begin
765
        status_bit6_0[2] = 1'b1;
766
        registers_addr_data_test_operation = 0;
767
     end
768
 
769
   // Reading from a selected registers
770
   always@(reg_address or registers_addr_data_test_operation or md_put_reg_data_out or
771
           control_bit15 or control_bit14_10 or control_bit9 or control_bit8_0 or
772
           status_bit15_9 or status_bit8 or status_bit7 or status_bit6_0 or
773
           phy_id1 or phy_id2)
774
     begin
775
        if (registers_addr_data_test_operation) // test operation
776
          begin
777
             if (md_put_reg_data_out) // read enable
778
               begin
779
                  register_bus_out = #1 data_mem[reg_address];
780
               end
781
          end
782
        else // normal operation
783
          begin
784
             if (md_put_reg_data_out) // read enable
785
               begin
786
                  case (reg_address)
787
                    5'h0:    register_bus_out = #1 {control_bit15, control_bit14_10, control_bit9, control_bit8_0};
788
                    5'h1:    register_bus_out = #1 {status_bit15_9, status_bit8, status_bit7, status_bit6_0};
789
                    5'h2:    register_bus_out = #1 phy_id1;
790
                    5'h3:    register_bus_out = #1 phy_id2;
791
                    default: register_bus_out = #1 16'hDEAD;
792
                  endcase
793
               end
794
          end
795
     end
796
 
797
   // Self clear control signals
798
   reg    self_clear_d0;
799
   reg    self_clear_d1;
800
   reg    self_clear_d2;
801
   reg    self_clear_d3;
802
   // Self clearing control
803
   always@(posedge mdc_i or negedge m_rst_n_i)
804
     begin
805
        if (!m_rst_n_i)
806
          begin
807
             self_clear_d0    <= #1 0;
808
             self_clear_d1    <= #1 0;
809
             self_clear_d2    <= #1 0;
810
             self_clear_d3    <= #1 0;
811
          end
812
        else
813
          begin
814
             self_clear_d0    <= #1 md_put_reg_data_in;
815
             self_clear_d1    <= #1 self_clear_d0;
816
             self_clear_d2    <= #1 self_clear_d1;
817
             self_clear_d3    <= #1 self_clear_d2;
818
          end
819
     end
820
 
821
   // Writing to a selected register
822
   always@(posedge mdc_i or negedge m_rst_n_i)
823
     begin
824
        if ((!m_rst_n_i) || (control_bit15))
825
          begin
826
             if (!registers_addr_data_test_operation) // normal operation
827
               begin
828
                  control_bit15    <= #1 0;
829
                  control_bit14_10 <= #1 {1'b0, (`LED_CFG1 || `LED_CFG2), `LED_CFG1, 2'b0};
830
                  control_bit9     <= #1 0;
831
                  control_bit8_0   <= #1 {`LED_CFG3, 8'b0};
832
               end
833
          end
834
        else
835
          begin
836
             if (registers_addr_data_test_operation) // test operation
837
               begin
838
                  if (md_put_reg_data_in)
839
                    begin
840
                       data_mem[reg_address] <= #1 register_bus_in[15:0];
841
                    end
842
               end
843
             else // normal operation
844
               begin
845
                  // bits that are normaly written
846
                  if (md_put_reg_data_in)
847
                    begin
848
                       case (reg_address)
849
                         5'h0:
850
                           begin
851
                              control_bit14_10 <= #1 register_bus_in[14:10];
852
                              control_bit8_0   <= #1 register_bus_in[8:0];
853
                           end
854
                         default:
855
                           begin
856
                           end
857
                       endcase
858
                    end
859
                  // self cleared bits written
860
                  if ((md_put_reg_data_in) && (reg_address == 5'h0))
861
                    begin
862
                       control_bit15 <= #1 register_bus_in[15];
863
                       control_bit9  <= #1 register_bus_in[9];
864
                    end
865
                  else if (self_clear_d3) // self cleared bits cleared
866
                    begin
867
                       control_bit15 <= #1 1'b0;
868
                       control_bit9  <= #1 1'b0;
869
                    end
870
               end
871
          end
872
     end
873
 
874
   //////////////////////////////////////////////////////////////////////
875
         //
876
   // PHY <-> MAC control (RX and TX clocks are at the begining)
877
   //
878
   //////////////////////////////////////////////////////////////////////
879
 
880
   // CARRIER SENSE & COLLISION
881
 
882
   // MAC common signals
883
   reg             mcoll_o;
884
   reg             mcrs_o;
885
   // Internal signals controling Carrier sense & Collision
886
   // MAC common signals generated when appropriate transfer
887
   reg             mcrs_rx;
888
   reg             mcrs_tx;
889
   // delayed mtxen_i signal for generating delayed tx carrier sense
890
   reg             mtxen_d1;
891
   reg             mtxen_d2;
892
   reg             mtxen_d3;
893
   reg             mtxen_d4;
894
   reg             mtxen_d5;
895
   reg             mtxen_d6;
896
   // collision signal set or rest within task for controling collision
897
   reg             task_mcoll;
898
   // carrier sense signal set or rest within task for controling carrier sense
899
   reg             task_mcrs;
900
   reg             task_mcrs_lost;
901
   // do not generate collision in half duplex - not normal operation
902
   reg             no_collision_in_half_duplex;
903
   // generate collision in full-duplex mode also - not normal operation
904
   reg             collision_in_full_duplex;
905
   // do not generate carrier sense in half duplex mode - not normal operation
906
   reg             no_carrier_sense_in_tx_half_duplex;
907
   reg             no_carrier_sense_in_rx_half_duplex;
908
   // generate carrier sense during TX in full-duplex mode also - not normal operation
909
   reg             carrier_sense_in_tx_full_duplex;
910
   // do not generate carrier sense during RX in full-duplex mode - not normal operation
911
   reg             no_carrier_sense_in_rx_full_duplex;
912
   // on RX: delay after carrier sense signal; on TX: carrier sense delayed (delay is one clock period)
913
   reg             real_carrier_sense;
914
 
915
   initial
916
     begin
917
        mcrs_rx = 0;
918
        mcrs_tx = 0;
919
        task_mcoll = 0;
920
        task_mcrs = 0;
921
        task_mcrs_lost = 0;
922
        no_collision_in_half_duplex = 0;
923
        collision_in_full_duplex = 0;
924
        no_carrier_sense_in_tx_half_duplex = 0;
925
        no_carrier_sense_in_rx_half_duplex = 0;
926
        carrier_sense_in_tx_full_duplex = 0;
927
        no_carrier_sense_in_rx_full_duplex = 0;
928
        real_carrier_sense = 0;
929
     end
930
 
931
   // Collision
932
   always@(m_rst_n_i or control_bit8_0 or collision_in_full_duplex or
933
           mcrs_rx or mcrs_tx or task_mcoll or no_collision_in_half_duplex
934
           )
935
     begin
936
        if (!m_rst_n_i)
937
          mcoll_o = 0;
938
        else
939
          begin
940
             if (control_bit8_0[8]) // full duplex
941
               begin
942
                  if (collision_in_full_duplex) // collision is usually not asserted in full duplex
943
                    begin
944
                       mcoll_o = ((mcrs_rx && mcrs_tx) || task_mcoll);
945
`ifdef ETH_PHY_VERBOSE
946
                       if (mcrs_rx && mcrs_tx)
947
                         $display( "(%0t)(%m) Collision set in FullDuplex!", $time);
948
                       if (task_mcoll)
949
                         $display( "(%0t)(%m) Collision set in FullDuplex from TASK!", $time);
950
`endif
951
                    end
952
                  else
953
                    begin
954
                       mcoll_o = task_mcoll;
955
`ifdef ETH_PHY_VERBOSE
956
                       if (task_mcoll)
957
                         $display( "(%0t)(%m) Collision set in FullDuplex from TASK!", $time);
958
`endif
959
                    end
960
               end
961
             else // half duplex
962
               begin
963
                  mcoll_o = ((mcrs_rx && mcrs_tx && !no_collision_in_half_duplex) ||
964
                             task_mcoll);
965
`ifdef ETH_PHY_VERBOSE
966
                  if (mcrs_rx && mcrs_tx)
967
                    $display( "(%0t)(%m) Collision set in HalfDuplex!", $time);
968
                  if (task_mcoll)
969
                    $display( "(%0t)(%m) Collision set in HalfDuplex from TASK!", $time);
970
`endif
971
               end
972
          end
973
     end
974
 
975
   // Carrier sense
976
   always@(m_rst_n_i or control_bit8_0 or carrier_sense_in_tx_full_duplex or
977
           no_carrier_sense_in_rx_full_duplex or
978
           no_carrier_sense_in_tx_half_duplex or
979
           no_carrier_sense_in_rx_half_duplex or
980
           mcrs_rx or mcrs_tx or task_mcrs or task_mcrs_lost
981
           )
982
     begin
983
        if (!m_rst_n_i)
984
          mcrs_o = 0;
985
        else
986
          begin
987
             if (control_bit8_0[8]) // full duplex
988
               begin
989
                  if (carrier_sense_in_tx_full_duplex) // carrier sense is usually not asserted during TX in full duplex
990
                    mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_full_duplex) ||
991
                              mcrs_tx || task_mcrs) && !task_mcrs_lost;
992
                  else
993
                    mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_full_duplex) ||
994
                              task_mcrs) && !task_mcrs_lost;
995
               end
996
             else // half duplex
997
               begin
998
                  mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_half_duplex) ||
999
                            (mcrs_tx && !no_carrier_sense_in_tx_half_duplex) ||
1000
                            task_mcrs) && !task_mcrs_lost;
1001
               end
1002
          end
1003
     end
1004
 
1005
   // MAC TX CONTROL (RECEIVING AT PHY)
1006
 
1007
   // storage memory for TX data received from MAC
1008
   reg     [7:0]  tx_mem [0:4194303]; // 4194304 locations (22 address lines) of 8-bit data width
1009
   reg [31:0]      tx_mem_addr_in; // address for storing to TX memory
1010
   reg [7:0]       tx_mem_data_in; // data for storing to TX memory
1011
   reg [31:0]      tx_cnt; // counts nibbles
1012
 
1013
   // control data of a TX packet for upper layer of testbench
1014
   reg            tx_preamble_ok;
1015
   reg            tx_sfd_ok;
1016
   // if there is a drible nibble, then tx packet is not byte aligned!
1017
   reg            tx_byte_aligned_ok;
1018
   // complete length of TX packet (Bytes) received (without preamble and SFD)
1019
   reg [31:0]      tx_len;
1020
   // complete length of TX packet (Bytes) received (without preamble and SFD) untill MTxErr signal was set first
1021
   reg [31:0]      tx_len_err;
1022
 
1023
   // TX control
1024
   always@(posedge mtx_clk_o)
1025
     begin
1026
        // storing data and basic checking of frame
1027
        if (!m_rst_n_i)
1028
          begin
1029
             tx_cnt <= 0;
1030
             tx_preamble_ok <= 0;
1031
             tx_sfd_ok <= 0;
1032
             tx_len <= 0;
1033
             tx_len_err <= 0;
1034
          end
1035
        else
1036
          begin
1037
             if (!mtxen_i)
1038
               begin
1039
                  tx_cnt <= 0;
1040
               end
1041
             else
1042
               begin
1043
                  // tx nibble counter
1044
                  tx_cnt <= tx_cnt + 1;
1045
                  // set initial values and check first preamble nibble
1046
                  if (tx_cnt == 0)
1047
                    begin
1048
`ifdef ETH_PHY_VERBOSE
1049
                       $display( "(%0t)(%m) TX frame started with tx_en set!", $time);
1050
`endif
1051
                       if (mtxd_i == 4'h5)
1052
                         tx_preamble_ok <= 1;
1053
                       else
1054
                         tx_preamble_ok <= 0;
1055
                       tx_sfd_ok <= 0;
1056
                       tx_byte_aligned_ok <= 0;
1057
                       tx_len <= 0;
1058
                       tx_len_err <= 0;
1059
                       tx_mem_addr_in <= 0; // RESET this here each packet! 
1060
                    end
1061
 
1062
                  // check preamble
1063
                  if ((tx_cnt > 0) && (tx_cnt <= 13))
1064
                    begin
1065
                       if ((tx_preamble_ok != 1) || (mtxd_i != 4'h5))
1066
                         tx_preamble_ok <= 0;
1067
                    end
1068
                  // check SFD
1069
                  if (tx_cnt == 14)
1070
                    begin
1071
`ifdef ETH_PHY_VERBOSE
1072
                       if (tx_preamble_ok == 1)
1073
                         $display( "(%0t)(%m) TX frame preamble OK!", $time);
1074
                       else
1075
                         $display( "*E (%0t)(%m) TX frame preamble NOT OK!", $time);
1076
`endif
1077
                       if (mtxd_i == 4'h5)
1078
                         tx_sfd_ok <= 1;
1079
                       else
1080
                         tx_sfd_ok <= 0;
1081
                    end
1082
                  if (tx_cnt == 15)
1083
                    begin
1084
                       if ((tx_sfd_ok != 1) || (mtxd_i != 4'hD))
1085
                         tx_sfd_ok <= 0;
1086
                    end
1087
 
1088
                  // control for storing addresses, type/length, data and FCS to TX memory
1089
                  if (tx_cnt > 15)
1090
                    begin
1091
                       if (tx_cnt == 16)
1092
                         begin
1093
`ifdef ETH_PHY_VERBOSE
1094
                            if (tx_sfd_ok == 1)
1095
                              $display( "(%0t)(%m) TX frame SFD OK!", $time);
1096
                            else
1097
                              $display( "*E (%0t)(%m) TX frame SFD NOT OK!", $time);
1098
`endif
1099
                         end
1100
 
1101
                       if (tx_cnt[0] == 0)
1102
                         begin
1103
                            tx_mem_data_in[3:0] <= mtxd_i; // storing LSB nibble
1104
                            tx_byte_aligned_ok <= 0; // if transfer will stop after this, then there was drible nibble
1105
                         end
1106
                       else
1107
                         begin
1108
                            tx_mem[tx_mem_addr_in[21:0]] <= {mtxd_i, tx_mem_data_in[3:0]}; // storing data into tx memory
1109
                            tx_len <= tx_len + 1; // enlarge byte length counter
1110
                            tx_byte_aligned_ok <= 1; // if transfer will stop after this, then transfer is byte alligned
1111
                            tx_mem_addr_in <= tx_mem_addr_in + 1'b1;
1112
                         end
1113
 
1114
                       if (mtxerr_i)
1115
                         tx_len_err <= tx_len;
1116
                    end
1117
               end
1118
          end
1119
 
1120
        // generating CARRIER SENSE for TX with or without delay
1121
        if (!m_rst_n_i)
1122
          begin
1123
             mcrs_tx  <= 0;
1124
             mtxen_d1 <= 0;
1125
             mtxen_d2 <= 0;
1126
             mtxen_d3 <= 0;
1127
             mtxen_d4 <= 0;
1128
             mtxen_d5 <= 0;
1129
             mtxen_d6 <= 0;
1130
          end
1131
        else
1132
          begin
1133
             mtxen_d1 <= mtxen_i;
1134
             mtxen_d2 <= mtxen_d1;
1135
             mtxen_d3 <= mtxen_d2;
1136
             mtxen_d4 <= mtxen_d3;
1137
             mtxen_d5 <= mtxen_d4;
1138
             mtxen_d6 <= mtxen_d5;
1139
             if (real_carrier_sense)
1140
               mcrs_tx  <= mtxen_d6;
1141
             else
1142
               mcrs_tx  <= mtxen_i;
1143
          end
1144
     end
1145
 
1146
`ifdef ETH_PHY_VERBOSE
1147
   reg             frame_started;
1148
 
1149
   initial
1150
     begin
1151
        frame_started = 0;
1152
     end
1153
   always@(posedge mtxen_i)
1154
     begin
1155
        frame_started <= 1;
1156
     end
1157
   always@(negedge mtxen_i)
1158
     begin
1159
        if (frame_started)
1160
          begin
1161
             $display( "(%0t)(%m) TX frame ended with tx_en reset!", $time);
1162
             frame_started <= 0;
1163
          end
1164
     end
1165
 
1166
   always@(posedge mrxerr_o)
1167
     begin
1168
        $display( "(%0t)(%m) RX frame ERROR signal was set!", $time);
1169
     end
1170
`endif
1171
 
1172
   //////////////////////////////////////////////////////////////////////
1173
   // 
1174
   // Tasks for PHY <-> MAC transactions
1175
   // 
1176
   //////////////////////////////////////////////////////////////////////
1177
 
1178
   initial
1179
     begin
1180
        tx_mem_addr_in = 0;
1181
     end
1182
 
1183
   // setting the address of tx_mem, to set the starting point of tx packet
1184
   task set_tx_mem_addr;
1185
      input [31:0] tx_mem_address;
1186
      begin
1187
         #1 tx_mem_addr_in = tx_mem_address;
1188
      end
1189
   endtask // set_tx_mem_addr
1190
 
1191
   // storage memory for RX data to be transmited to MAC
1192
   //reg     [7:0]  rx_mem [0:4194303]; // 4194304 locations (22 address lines) of 8-bit data width
1193
   reg     [7:0]  rx_mem [0:2000]; // Legal ethernet packet is 1512, so add a bit more for extras
1194
 
1195
   // MAC RX signals
1196
   reg [3:0]       mrxd_o;
1197
   reg            mrxdv_o;
1198
   reg            mrxerr_o;
1199
 
1200
   // SMII signals
1201
   reg            smii_rx_go;
1202
   reg [31:0]      smii_rx_dat_addr;
1203
   reg [10:1]     smii_rx_frame;
1204
   reg [10:1]     smii_sync_state;
1205
   reg [31:0]      smii_rx_len;
1206
 
1207
`define DEFAULT_SMII_RX_FRAME {3'b101,1'b0,1'b1,1'b1,eth_speed,1'b0,1'b0,1'b0}
1208
 
1209
 
1210
   initial
1211
     begin
1212
        mrxd_o = 0;
1213
        mrxdv_o = 0;
1214
        mrxerr_o = 0;
1215
        mcrs_rx = 0;
1216
        smii_rx_go = 0;
1217
        #100
1218
        // For now hardcoded to 100Mbps
1219
        smii_rx_frame = `DEFAULT_SMII_RX_FRAME;
1220
     end
1221
 
1222
 
1223
   always @(posedge smii_clk_i or negedge m_rst_n_i)
1224
        if (!m_rst_n_i)
1225
       smii_sync_state <= 10'b00000_00000;
1226
     else if (smii_sync_i)
1227
       smii_sync_state <= 10'b00000_00010;
1228
     else
1229
       smii_sync_state <= {smii_sync_state[9:1], smii_sync_state[10]};
1230
 
1231
   assign #2 smii_rx_o = |(smii_rx_frame & smii_sync_state);
1232
 
1233
   integer smii_frame_counter;
1234
 
1235
   // Update the SMII frame we'll put out next
1236
   task smii_rx_new_frame;
1237
      input [10:1] frame;
1238
      begin
1239
         while (~smii_sync_state[10]) // Wait for state before sync to output data
1240
           @(posedge smii_clk_i);
1241
         #2;
1242
 
1243
         // Set the frame out
1244
         smii_rx_frame = frame;
1245
 
1246
         if (eth_speed == 0)
1247
           begin
1248
              // is 10Mbps mode, so repeat the frame 10 times
1249
              smii_frame_counter = 0;
1250
              while (smii_frame_counter < 10)
1251
                begin
1252
                   @(posedge smii_sync_state[10]);
1253
                   smii_frame_counter  = smii_frame_counter + 1;
1254
                end
1255
           end
1256
      end
1257
   endtask // smii_rx_new_frame
1258
 
1259
   always @(eth_speed)
1260
     // Update frame
1261
     smii_rx_new_frame(`DEFAULT_SMII_RX_FRAME);
1262
 
1263
   integer smii_rx_cnt;
1264
 
1265
   // SMII RX functions
1266
   always @(posedge smii_rx_go)
1267
     begin
1268
        // SFD
1269
        smii_rx_new_frame({8'h55,2'b10});
1270
        smii_rx_new_frame({8'h55,2'b10});
1271
        smii_rx_new_frame({8'h55,2'b10});
1272
        smii_rx_new_frame({8'h55,2'b10});
1273
        smii_rx_new_frame({8'h55,2'b10});
1274
        smii_rx_new_frame({8'h55,2'b10});
1275
        smii_rx_new_frame({8'h55,2'b10});
1276
        smii_rx_new_frame({8'hd5,2'b10});
1277
 
1278
        // send packet's addresses, type/length, data and FCS
1279
         for (smii_rx_cnt = 0; smii_rx_cnt < smii_rx_len; smii_rx_cnt = smii_rx_cnt + 1)
1280
           begin
1281
              smii_rx_new_frame({rx_mem[smii_rx_dat_addr[21:0]],2'b10});
1282
              smii_rx_dat_addr = smii_rx_dat_addr + 1;
1283
           end
1284
        // Set frame back to original
1285
        smii_rx_new_frame(`DEFAULT_SMII_RX_FRAME);
1286
 
1287
        smii_rx_go = 0;
1288
 
1289
     end
1290
 
1291
 
1292
   task send_rx_packet;
1293
      input  [(8*8)-1:0] preamble_data; // preamble data to be sent - 
1294
                                        // correct is 64'h0055_5555_5555_5555
1295
      input [3:0]         preamble_len; // length of preamble in bytes - 
1296
                                       // max is 4'h8, correct is 4'h7 
1297
      input [7:0]         sfd_data; // SFD data to be sent - correct is 8'hD5
1298
      input [31:0]        start_addr; // start address
1299
      input [31:0]        len; // length of frame in Bytes (without preamble
1300
                              // and SFD)
1301
      input              plus_drible_nibble; // if length is longer for one 
1302
                                             // nibble
1303
      input              assert_rx_err; // Set rxerr during transmit
1304
      begin
1305
         smii_rx_dat_addr = start_addr;
1306
         smii_rx_len = len;
1307
         smii_rx_go = 1;
1308
 
1309
         send_mii_rx_packet(preamble_data, preamble_len, sfd_data, start_addr, len, plus_drible_nibble,
1310
                            assert_rx_err);
1311
         while(smii_rx_go)
1312
           @(posedge smii_clk_i);
1313
 
1314
      end
1315
   endtask // send_rx_packet
1316
 
1317
   task send_mii_rx_packet;
1318
      input  [(8*8)-1:0] preamble_data; // preamble data to be sent - 
1319
                                        // correct is 64'h0055_5555_5555_5555
1320
      input [3:0]         preamble_len; // length of preamble in bytes - 
1321
                                       // max is 4'h8, correct is 4'h7 
1322
      input [7:0]         sfd_data; // SFD data to be sent - correct is 8'hD5
1323
      input [31:0]        start_addr; // start address
1324
      input [31:0]        len; // length of frame in Bytes (without preamble
1325
                              // and SFD)
1326
      input              plus_drible_nibble; // if length is longer for one 
1327
                                             // nibble
1328
      input              assert_rx_err; // Set rxerr during transmit
1329
 
1330
      integer            rx_cnt;
1331
      reg [31:0]          rx_mem_addr_in; // address for reading from RX memory
1332
      reg [7:0]   rx_mem_data_out; // data for reading from RX memory
1333
      begin
1334
         @(posedge mrx_clk_o);
1335
         // generating CARRIER SENSE for TX with or without delay
1336
         if (real_carrier_sense)
1337
           #1 mcrs_rx = 1;
1338
         else
1339
           #1 mcrs_rx = 0;
1340
         @(posedge mrx_clk_o);
1341
         #1 mcrs_rx = 1;
1342
         #1 mrxdv_o = 1;
1343
`ifdef ETH_PHY_VERBOSE
1344
         $display( "(%0t)(%m) RX frame started with rx_dv set!", $time);
1345
`endif
1346
         // set initial rx memory address
1347
         rx_mem_addr_in = start_addr;
1348
 
1349
         // send preamble
1350
         for (rx_cnt = 0; (rx_cnt < (preamble_len << 1)) && (rx_cnt < 16); rx_cnt = rx_cnt + 1)
1351
           begin
1352
              #1 mrxd_o = preamble_data[3:0];
1353
              #1 preamble_data = preamble_data >> 4;
1354
              @(posedge mrx_clk_o);
1355
           end
1356
 
1357
         // send SFD
1358
         for (rx_cnt = 0; rx_cnt < 2; rx_cnt = rx_cnt + 1)
1359
           begin
1360
              #1 mrxd_o = sfd_data[3:0];
1361
              #1 sfd_data = sfd_data >> 4;
1362
              @(posedge mrx_clk_o);
1363
           end
1364
`ifdef ETH_PHY_VERBOSE
1365
         $display( "(%0t)(%m) RX frame preamble and SFD sent!", $time);
1366
`endif
1367
         // send packet's addresses, type/length, data and FCS
1368
         for (rx_cnt = 0; rx_cnt < len; rx_cnt = rx_cnt + 1)
1369
           begin
1370
              #1;
1371
              rx_mem_data_out = rx_mem[rx_mem_addr_in[21:0]];
1372
              mrxd_o = rx_mem_data_out[3:0];
1373
              @(posedge mrx_clk_o);
1374
              #1;
1375
 
1376
              // Assert error if told to .... TODO: make this occur at random time
1377
              // jb
1378
              if (rx_cnt > 18) rx_err(assert_rx_err);
1379
 
1380
              mrxd_o = rx_mem_data_out[7:4];
1381
              rx_mem_addr_in = rx_mem_addr_in + 1;
1382
              @(posedge mrx_clk_o);
1383
              #1;
1384
           end
1385
         if (plus_drible_nibble)
1386
           begin
1387
              rx_mem_data_out = rx_mem[rx_mem_addr_in[21:0]];
1388
              mrxd_o = rx_mem_data_out[3:0];
1389
              @(posedge mrx_clk_o);
1390
           end
1391
`ifdef ETH_PHY_VERBOSE
1392
         $display( "(%0t)(%m) RX frame addresses, type/length, data and FCS sent!", $time);
1393
`endif
1394
         #1 mcrs_rx = 0;
1395
         #1 mrxdv_o = 0;
1396
         @(posedge mrx_clk_o);
1397
`ifdef ETH_PHY_VERBOSE
1398
         $display( "(%0t)(%m) RX frame ended with rx_dv reset!", $time);
1399
`endif
1400
      end
1401
   endtask // send_rx_packet
1402
 
1403
 
1404
 
1405
   task GetDataOnMRxD;
1406
      input [15:0] Len;
1407
      input [31:0] TransferType;
1408
      integer      tt;
1409
 
1410
      begin
1411
         @ (posedge mrx_clk_o);
1412
         #1 mrxdv_o=1'b1;
1413
 
1414
         for(tt=0; tt<15; tt=tt+1)
1415
           begin
1416
              mrxd_o=4'h5;              // preamble
1417
              @ (posedge mrx_clk_o);
1418
              #1;
1419
           end
1420
 
1421
         mrxd_o=4'hd;                // SFD
1422
 
1423
         for(tt=1; tt<(Len+1); tt=tt+1)
1424
           begin
1425
              @ (posedge mrx_clk_o);
1426
              #1;
1427
              if(TransferType == `UNICAST_XFR && tt == 1)
1428
                mrxd_o = 4'h0;   // Unicast transfer
1429
              else if(TransferType == `BROADCAST_XFR && tt < 7)
1430
                mrxd_o = 4'hf;
1431
              else
1432
                mrxd_o = tt[3:0]; // Multicast transfer
1433
 
1434
              @ (posedge mrx_clk_o);
1435
              #1;
1436
 
1437
              if(TransferType == `BROADCAST_XFR && tt == 6)
1438
                mrxd_o = 4'he;
1439
              else
1440
 
1441
                if(TransferType == `BROADCAST_XFR && tt < 7)
1442
                  mrxd_o = 4'hf;
1443
                else
1444
                  mrxd_o = tt[7:4];
1445
           end
1446
 
1447
         @ (posedge mrx_clk_o);
1448
         #1;
1449
         mrxdv_o = 1'b0;
1450
      end
1451
   endtask // GetDataOnMRxD
1452
 
1453
 
1454
   //////////////////////////////////////////////////////////////////////
1455
   //
1456
   // Tastks for controling PHY statuses and rx error
1457
   //
1458
   //////////////////////////////////////////////////////////////////////
1459
 
1460
   // Link control tasks
1461
   task link_up_down;
1462
      input   test_op;
1463
      begin
1464
         #1 status_bit6_0[2] = test_op; // 1 - link up; 0 - link down
1465
      end
1466
   endtask
1467
 
1468
   // RX error
1469
   task rx_err;
1470
      input   test_op;
1471
      begin
1472
         #1 mrxerr_o = test_op; // 1 - RX error set; 0 - RX error reset
1473
      end
1474
   endtask
1475
 
1476
   //////////////////////////////////////////////////////////////////////
1477
   //
1478
   // Tastks for controling PHY carrier sense and collision
1479
   //
1480
   //////////////////////////////////////////////////////////////////////
1481
 
1482
   // Collision
1483
   task collision;
1484
      input   test_op;
1485
      begin
1486
         #1 task_mcoll = test_op;
1487
      end
1488
   endtask
1489
 
1490
   // Carrier sense
1491
   task carrier_sense;
1492
      input   test_op;
1493
      begin
1494
         #1 task_mcrs = test_op;
1495
      end
1496
   endtask
1497
 
1498
   // Carrier sense lost - higher priority than Carrier sense task
1499
   task carrier_sense_lost;
1500
      input   test_op;
1501
      begin
1502
         #1 task_mcrs_lost = test_op;
1503
      end
1504
   endtask
1505
 
1506
   // No collision detection in half duplex
1507
   task no_collision_hd_detect;
1508
      input   test_op;
1509
      begin
1510
         #1 no_collision_in_half_duplex = test_op;
1511
      end
1512
   endtask
1513
 
1514
   // Collision detection in full duplex also
1515
   task collision_fd_detect;
1516
      input   test_op;
1517
      begin
1518
         #1 collision_in_full_duplex = test_op;
1519
      end
1520
   endtask
1521
 
1522
   // No carrier sense detection at TX in half duplex
1523
   task no_carrier_sense_tx_hd_detect;
1524
      input   test_op;
1525
      begin
1526
         #1 no_carrier_sense_in_tx_half_duplex = test_op;
1527
      end
1528
   endtask
1529
 
1530
   // No carrier sense detection at RX in half duplex
1531
   task no_carrier_sense_rx_hd_detect;
1532
      input   test_op;
1533
      begin
1534
         #1 no_carrier_sense_in_rx_half_duplex = test_op;
1535
      end
1536
   endtask
1537
 
1538
   // Carrier sense detection at TX in full duplex also
1539
   task carrier_sense_tx_fd_detect;
1540
      input   test_op;
1541
      begin
1542
         #1 carrier_sense_in_tx_full_duplex = test_op;
1543
      end
1544
   endtask
1545
 
1546
   // No carrier sense detection at RX in full duplex
1547
   task no_carrier_sense_rx_fd_detect;
1548
      input   test_op;
1549
      begin
1550
         #1 no_carrier_sense_in_rx_full_duplex = test_op;
1551
      end
1552
   endtask
1553
 
1554
   // Set real delay on carrier sense signal (and therefor collision signal)
1555
   task carrier_sense_real_delay;
1556
      input   test_op;
1557
      begin
1558
         #1 real_carrier_sense = test_op;
1559
      end
1560
   endtask
1561
 
1562
   //////////////////////////////////////////////////////////////////////
1563
   //
1564
   // Tastks for controling PHY management test operation
1565
   //
1566
   //////////////////////////////////////////////////////////////////////
1567
 
1568
   // Set registers to test operation and respond to all phy addresses
1569
   task test_regs;
1570
      input   test_op;
1571
      begin
1572
         #1 registers_addr_data_test_operation = test_op;
1573
         respond_to_all_phy_addr = test_op;
1574
      end
1575
   endtask
1576
 
1577
   // Clears data memory for testing the MII
1578
   task clear_test_regs;
1579
      integer i;
1580
      begin
1581
         for (i = 0; i < 32; i = i + 1)
1582
           begin
1583
              #1 data_mem[i] = 16'h0;
1584
           end
1585
      end
1586
   endtask
1587
 
1588
   // Accept frames with preamble suppresed
1589
   task preamble_suppresed;
1590
      input   test_op;
1591
      begin
1592
         #1 no_preamble = test_op;
1593
         md_transfer_cnt_reset = 1'b1;
1594
         @(posedge mdc_i);
1595
         #1 md_transfer_cnt_reset = 1'b0;
1596
      end
1597
   endtask
1598
 
1599
 
1600
 
1601
   // Sideband signals for external SMII converter --jb
1602
   assign link_o = status_bit6_0[2];
1603
 
1604
   assign speed_o = eth_speed;
1605
 
1606
   assign duplex_o = control_bit8_0[8];
1607
 
1608
 
1609
 
1610
 
1611
endmodule
1612
 

powered by: WebSVN 2.1.0

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