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

Subversion Repositories ethmac

[/] [ethmac/] [trunk/] [bench/] [verilog/] [eth_phy.v] - Blame information for rev 188

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

powered by: WebSVN 2.1.0

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