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

Subversion Repositories ethmac

[/] [ethmac/] [tags/] [rel_11/] [bench/] [verilog/] [eth_phy.v] - Blame information for rev 338

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

powered by: WebSVN 2.1.0

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