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

Subversion Repositories ethmac

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

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

powered by: WebSVN 2.1.0

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