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] - Rev 4

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  File name "encoder_8b_tx_model.v"                           ////
////                                                              ////
////  This file is part of the :                                  ////
////                                                              ////
//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project"         ////
////                                                              ////
////  http://opencores.org/project,1000base-x                     ////
////                                                              ////
////  Author(s):                                                  ////
////      - D.W.Pegler Cambridge Broadband Networks Ltd           ////
////                                                              ////
////      { peglerd@gmail.com, dwp@cambridgebroadand.com }        ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 AUTHORS. All rights reserved.             ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// This module is based on the coding method described in       ////
//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) ////
//// and Physical Medium Attachment (PMA) sublayer, type          ////
//// 1000BASE-X"; see :                                           ////
////                                                              ////
//// http://standards.ieee.org/about/get/802/802.3.html           ////
//// and                                                          ////
//// doc/802.3-2008_section3.pdf, Clause/Section 36.              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
`include "timescale_tb.v"
 
module encoder_8b_tx_model #(
  parameter DEBUG       = 0,
  parameter out_delay   = 5,
  parameter in_delay    = 2
)(
  interface send_intf,
 
   // --- Clocks
   input SBYTECLK,
 
   input disparity_in,
 
   // --- Eight bit input bus	  
   output [7:0] ebi,
 
 
   output K
);
 
   import ethernet_frame::EthernetFrame;
 
   reg [7:0] 	tmp_ebi;
   reg          tmp_K;
   reg 		disparity;
 
   assign #out_delay ebi = tmp_ebi;
   assign #out_delay K   = tmp_K;
 
   // Single transmit data queue
   reg [7:0] encoder_8b_data_queue[$];
 
   // Config data queue
   reg [15:0] encoder_8b_config_queue[$];
 
   // Single transmit queue
   EthernetFrame transmit_queue[$];
 
   //----------------------------------------------------------------------------
  // Send interface functions
  //----------------------------------------------------------------------------
 
   function automatic string send_intf.whoami();
      string buffer;
      $sformat(buffer, "%m");
      return buffer.substr(0, buffer.len()-17);
   endfunction
 
   function automatic void send_intf.push_8B_symbol(reg [7:0] symbol);
 
      encoder_8b_data_queue.push_back(symbol);
 
   endfunction // automatic
 
 
   function automatic void send_intf.push_config(reg [15:0] config_reg);
 
      encoder_8b_config_queue.push_back(config_reg);
 
   endfunction // automatic
 
 
   // Queue frame for transmission.
   function automatic void send_intf.queue_frame(EthernetFrame frame);
 
      EthernetFrame f = frame;
 
      transmit_queue.push_back(f);
 
  endfunction // automatic
 
 
  // Wait for all frames to be transmitted.
   task automatic send_intf.sleep(time timeout);
      time start_time = $time;
      time end_time = start_time + timeout;
 
      while(1)
      begin
         @(posedge SBYTECLK);
 
         if ($time > end_time)  break;
      end
  endtask
 
   //----------------------------------------------------------------------------
   //
   //----------------------------------------------------------------------------
 
`define K28_5 8'b10111100   
 
   task automatic encoder_8b_push_symbol(input K, input [7:0] ebi);
      tmp_K = K; tmp_ebi = ebi;
      @(posedge SBYTECLK);
   endtask
 
 
   //----------------------------------------------------------------------------
   // Test Sequence Functions
   //----------------------------------------------------------------------------
 
   task automatic encoder_8b_push_test_sequence();
 
      encoder_8b_push_symbol(1'b1, `K28_5);
   endtask
 
   //----------------------------------------------------------------------------
   // IDLE Sequence Functions
   //----------------------------------------------------------------------------
 
`define D5_6  8'b11000101
`define D16_2 8'b01010000
 
   reg [7:0] I1[2] = '{ `K28_5, `D5_6  };
   reg [7:0] I2[2] = '{ `K28_5, `D16_2 };
 
   task automatic encoder_8b_push_idle_sequence();
 
      for (int x=0; x<2; x++)
	encoder_8b_push_symbol(~x, (disparity_in) ? I1[x] : I2[x]);
 
   endtask // automatic
 
 
   //----------------------------------------------------------------------------
   // Config Sequence Functions
   //----------------------------------------------------------------------------
 
`define D21_5 8'b10110101
`define D2_2  8'b01000010
 
   reg [7:0] C1[2] = '{ `K28_5, `D21_5 };
   reg [7:0] C2[2] = '{ `K28_5, `D2_2  };
 
   reg 	     c_toggle = 0;
 
   task automatic encoder_8b_push_config_sequence(reg [15:0] config_reg);
 
      //$display("%m: pushing config_reg: %016b", config_reg);
 
      for (int x=0; x<2; x++)
 
	// If disparity after K28.5 is +ve then choose
	// D2.2 to flip disparity
	// If disparity after K28.5 is -ve then choose
	// D31.5 to leave the disparity as -ve.: +(--+-)+
	// Doing this ensures that in a burst of /C/ sequences,
	// The disparity on before K28_5 is -ve so +comma is
	// always chosen!
	encoder_8b_push_symbol(~x, (c_toggle) ? C2[x] : C1[x]);
 
      // Push Config Register value
      encoder_8b_push_symbol(1'b0, config_reg[7:0]);
 
      // Push Config Register value
      encoder_8b_push_symbol(1'b0, config_reg[15:8]);
 
      c_toggle = ~c_toggle;
 
   endtask // automatic
 
   //----------------------------------------------------------------------------
   // Frame transmit Functions
   //----------------------------------------------------------------------------
 
`define K23_7  8'b11110111
`define K27_7  8'b11111011
`define K29_7  8'b11111101
 
   task automatic encoder_8b_transmit_frame();
 
      EthernetFrame frame;
 
      integer burst_size = transmit_queue.size;
 
      integer burst_count = 0;
 
      while (transmit_queue.size())
	begin
	   // Select frame at front of the queue
	   frame = transmit_queue[0];
 
	   // If this a burst insert /R/ before /S/
	   if ((burst_size > 1) && (burst_count))
	     encoder_8b_push_symbol(1'b1, `K23_7);
 
	     // Transmit SFD
	   encoder_8b_push_symbol(1'b1, `K27_7);
 
	   // Push frame
	   for (int index=0; index<frame.len(); index++)
	     encoder_8b_push_symbol(1'b0, frame.raw[index]);
 
	   // Push EPD
	   encoder_8b_push_symbol(1'b1, `K29_7);
 
	   // Keep track of the number of frames transmitted in a burst.
	   burst_count += 1;
 
	   void'(transmit_queue.pop_front());
	end
   endtask // automatic
 
   //----------------------------------------------------------------------------
   // Transmit Process.
   //----------------------------------------------------------------------------
   task automatic encoder_8b_push();
 
      // Is there any ctrl data to bus
      if (encoder_8b_config_queue.size())     
 
	// Push sequence C1/C2/Config_Reg
	encoder_8b_push_config_sequence(encoder_8b_config_queue.pop_front());
 
      // Are there any frames to transmit ?
      else if (transmit_queue.size())
 
	// Push SPD + frame + EFD
	encoder_8b_transmit_frame();
 
      // Is there any Data to push
      else if (encoder_8b_data_queue.size()) 
 
	// Push data 
	encoder_8b_push_symbol(1'b0, encoder_8b_data_queue.pop_front());
 
      else
	// Otherwise push the Idle sequence I1 or I2
	encoder_8b_push_idle_sequence();
 
   endtask // automatic
 
 
   //----------------------------------------------------------------------------
   //----------------------------------------------------------------------------
 
  initial
    begin
       tmp_ebi = 8'h00; tmp_K = 0;
 
       // Get initial disparity
       disparity = disparity_in;
 
       /// Obtain initial sync...
       @(posedge SBYTECLK);
 
       while(1)
	 begin
	    encoder_8b_push();
 
	    // Get disparity at end of every symbol push
	    disparity = disparity_in;
	 end
 
    end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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