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

Subversion Repositories ethmac

[/] [ethmac/] [branches/] [unneback/] [bench/] [verilog/] [eth_phy.v] - Blame information for rev 364

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

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

powered by: WebSVN 2.1.0

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