OpenCores
URL https://opencores.org/ocsvn/1000base-x/1000base-x/trunk

Subversion Repositories 1000base-x

[/] [1000base-x/] [trunk/] [testbench/] [rtl/] [verilog/] [encoder_8b_tx_model.v] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 dwp
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "encoder_8b_tx_model.v"                           ////
4
////                                                              ////
5
////  This file is part of the :                                  ////
6
////                                                              ////
7
//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project"         ////
8
////                                                              ////
9
////  http://opencores.org/project,1000base-x                     ////
10
////                                                              ////
11
////  Author(s):                                                  ////
12
////      - D.W.Pegler Cambridge Broadband Networks Ltd           ////
13
////                                                              ////
14
////      { peglerd@gmail.com, dwp@cambridgebroadand.com }        ////
15
////                                                              ////
16
//////////////////////////////////////////////////////////////////////
17
////                                                              ////
18
//// Copyright (C) 2009 AUTHORS. All rights reserved.             ////
19
////                                                              ////
20
//// This source file may be used and distributed without         ////
21
//// restriction provided that this copyright statement is not    ////
22
//// removed from the file and that any derivative work contains  ////
23
//// the original copyright notice and the associated disclaimer. ////
24
////                                                              ////
25
//// This source file is free software; you can redistribute it   ////
26
//// and/or modify it under the terms of the GNU Lesser General   ////
27
//// Public License as published by the Free Software Foundation; ////
28
//// either version 2.1 of the License, or (at your option) any   ////
29
//// later version.                                               ////
30
////                                                              ////
31
//// This source is distributed in the hope that it will be       ////
32
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
33
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
34
//// PURPOSE.  See the GNU Lesser General Public License for more ////
35
//// details.                                                     ////
36
////                                                              ////
37
//// You should have received a copy of the GNU Lesser General    ////
38
//// Public License along with this source; if not, download it   ////
39
//// from http://www.opencores.org/lgpl.shtml                     ////
40
////                                                              ////
41
//////////////////////////////////////////////////////////////////////
42
////                                                              ////
43
//// This module is based on the coding method described in       ////
44
//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) ////
45
//// and Physical Medium Attachment (PMA) sublayer, type          ////
46
//// 1000BASE-X"; see :                                           ////
47
////                                                              ////
48
//// http://standards.ieee.org/about/get/802/802.3.html           ////
49
//// and                                                          ////
50
//// doc/802.3-2008_section3.pdf, Clause/Section 36.              ////
51
////                                                              ////
52
//////////////////////////////////////////////////////////////////////
53
 
54
`include "timescale_tb.v"
55
 
56
module encoder_8b_tx_model #(
57
  parameter DEBUG       = 0,
58
  parameter out_delay   = 5,
59
  parameter in_delay    = 2
60
)(
61
  interface send_intf,
62
 
63
   // --- Clocks
64
   input SBYTECLK,
65
 
66
   input disparity_in,
67
 
68
   // --- Eight bit input bus     
69
   output [7:0] ebi,
70
 
71
 
72
   output K
73
);
74
 
75
   import ethernet_frame::EthernetFrame;
76
 
77
   reg [7:0]     tmp_ebi;
78
   reg          tmp_K;
79
   reg          disparity;
80
 
81
   assign #out_delay ebi = tmp_ebi;
82
   assign #out_delay K   = tmp_K;
83
 
84
   // Single transmit data queue
85
   reg [7:0] encoder_8b_data_queue[$];
86
 
87
   // Config data queue
88
   reg [15:0] encoder_8b_config_queue[$];
89
 
90
   // Single transmit queue
91
   EthernetFrame transmit_queue[$];
92
 
93
   //----------------------------------------------------------------------------
94
  // Send interface functions
95
  //----------------------------------------------------------------------------
96
 
97
   function automatic string send_intf.whoami();
98
      string buffer;
99
      $sformat(buffer, "%m");
100
      return buffer.substr(0, buffer.len()-17);
101
   endfunction
102
 
103
   function automatic void send_intf.push_8B_symbol(reg [7:0] symbol);
104
 
105
      encoder_8b_data_queue.push_back(symbol);
106
 
107
   endfunction // automatic
108
 
109
 
110
   function automatic void send_intf.push_config(reg [15:0] config_reg);
111
 
112
      encoder_8b_config_queue.push_back(config_reg);
113
 
114
   endfunction // automatic
115
 
116
 
117
   // Queue frame for transmission.
118
   function automatic void send_intf.queue_frame(EthernetFrame frame);
119
 
120
      EthernetFrame f = frame;
121
 
122
      transmit_queue.push_back(f);
123
 
124
  endfunction // automatic
125
 
126
 
127
  // Wait for all frames to be transmitted.
128
   task automatic send_intf.sleep(time timeout);
129
      time start_time = $time;
130
      time end_time = start_time + timeout;
131
 
132
      while(1)
133
      begin
134
         @(posedge SBYTECLK);
135
 
136
         if ($time > end_time)  break;
137
      end
138
  endtask
139
 
140
   //----------------------------------------------------------------------------
141
   //
142
   //----------------------------------------------------------------------------
143
 
144
`define K28_5 8'b10111100
145
 
146
   task automatic encoder_8b_push_symbol(input K, input [7:0] ebi);
147
      tmp_K = K; tmp_ebi = ebi;
148
      @(posedge SBYTECLK);
149
   endtask
150
 
151
 
152
   //----------------------------------------------------------------------------
153
   // Test Sequence Functions
154
   //----------------------------------------------------------------------------
155
 
156
   task automatic encoder_8b_push_test_sequence();
157
 
158
      encoder_8b_push_symbol(1'b1, `K28_5);
159
   endtask
160
 
161
   //----------------------------------------------------------------------------
162
   // IDLE Sequence Functions
163
   //----------------------------------------------------------------------------
164
 
165
`define D5_6  8'b11000101
166
`define D16_2 8'b01010000
167
 
168
   reg [7:0] I1[2] = '{ `K28_5, `D5_6  };
169
   reg [7:0] I2[2] = '{ `K28_5, `D16_2 };
170
 
171
   task automatic encoder_8b_push_idle_sequence();
172
 
173
      for (int x=0; x<2; x++)
174
        encoder_8b_push_symbol(~x, (disparity_in) ? I1[x] : I2[x]);
175
 
176
   endtask // automatic
177
 
178
 
179
   //----------------------------------------------------------------------------
180
   // Config Sequence Functions
181
   //----------------------------------------------------------------------------
182
 
183
`define D21_5 8'b10110101
184
`define D2_2  8'b01000010
185
 
186
   reg [7:0] C1[2] = '{ `K28_5, `D21_5 };
187
   reg [7:0] C2[2] = '{ `K28_5, `D2_2  };
188
 
189
   reg       c_toggle = 0;
190
 
191
   task automatic encoder_8b_push_config_sequence(reg [15:0] config_reg);
192
 
193
      //$display("%m: pushing config_reg: %016b", config_reg);
194
 
195
      for (int x=0; x<2; x++)
196
 
197
        // If disparity after K28.5 is +ve then choose
198
        // D2.2 to flip disparity
199
        // If disparity after K28.5 is -ve then choose
200
        // D31.5 to leave the disparity as -ve.: +(--+-)+
201
        // Doing this ensures that in a burst of /C/ sequences,
202
        // The disparity on before K28_5 is -ve so +comma is
203
        // always chosen!
204
        encoder_8b_push_symbol(~x, (c_toggle) ? C2[x] : C1[x]);
205
 
206
      // Push Config Register value
207
      encoder_8b_push_symbol(1'b0, config_reg[7:0]);
208
 
209
      // Push Config Register value
210
      encoder_8b_push_symbol(1'b0, config_reg[15:8]);
211
 
212
      c_toggle = ~c_toggle;
213
 
214
   endtask // automatic
215
 
216
   //----------------------------------------------------------------------------
217
   // Frame transmit Functions
218
   //----------------------------------------------------------------------------
219
 
220
`define K23_7  8'b11110111
221
`define K27_7  8'b11111011
222
`define K29_7  8'b11111101
223
 
224
   task automatic encoder_8b_transmit_frame();
225
 
226
      EthernetFrame frame;
227
 
228
      integer burst_size = transmit_queue.size;
229
 
230
      integer burst_count = 0;
231
 
232
      while (transmit_queue.size())
233
        begin
234
           // Select frame at front of the queue
235
           frame = transmit_queue[0];
236
 
237
           // If this a burst insert /R/ before /S/
238
           if ((burst_size > 1) && (burst_count))
239
             encoder_8b_push_symbol(1'b1, `K23_7);
240
 
241
             // Transmit SFD
242
           encoder_8b_push_symbol(1'b1, `K27_7);
243
 
244
           // Push frame
245
           for (int index=0; index<frame.len(); index++)
246
             encoder_8b_push_symbol(1'b0, frame.raw[index]);
247
 
248
           // Push EPD
249
           encoder_8b_push_symbol(1'b1, `K29_7);
250
 
251
           // Keep track of the number of frames transmitted in a burst.
252
           burst_count += 1;
253
 
254
           void'(transmit_queue.pop_front());
255
        end
256
   endtask // automatic
257
 
258
   //----------------------------------------------------------------------------
259
   // Transmit Process.
260
   //----------------------------------------------------------------------------
261
   task automatic encoder_8b_push();
262
 
263
      // Is there any ctrl data to bus
264
      if (encoder_8b_config_queue.size())
265
 
266
        // Push sequence C1/C2/Config_Reg
267
        encoder_8b_push_config_sequence(encoder_8b_config_queue.pop_front());
268
 
269
      // Are there any frames to transmit ?
270
      else if (transmit_queue.size())
271
 
272
        // Push SPD + frame + EFD
273
        encoder_8b_transmit_frame();
274
 
275
      // Is there any Data to push
276
      else if (encoder_8b_data_queue.size())
277
 
278
        // Push data 
279
        encoder_8b_push_symbol(1'b0, encoder_8b_data_queue.pop_front());
280
 
281
      else
282
        // Otherwise push the Idle sequence I1 or I2
283
        encoder_8b_push_idle_sequence();
284
 
285
   endtask // automatic
286
 
287
 
288
   //----------------------------------------------------------------------------
289
   //----------------------------------------------------------------------------
290
 
291
  initial
292
    begin
293
       tmp_ebi = 8'h00; tmp_K = 0;
294
 
295
       // Get initial disparity
296
       disparity = disparity_in;
297
 
298
       /// Obtain initial sync...
299
       @(posedge SBYTECLK);
300
 
301
       while(1)
302
         begin
303
            encoder_8b_push();
304
 
305
            // Get disparity at end of every symbol push
306
            disparity = disparity_in;
307
         end
308
 
309
    end
310
 
311
endmodule
312
 

powered by: WebSVN 2.1.0

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