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

Subversion Repositories 1000base-x

[/] [1000base-x/] [trunk/] [rtl/] [verilog/] [ge_1000baseX_an.v] - Rev 3

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  File name "ge_1000baseX_an.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 37" Auto-Negotiation function,    ////
//// type 1000BASE-X"; see :                                      ////
////                                                              ////
//// http://standards.ieee.org/about/get/802/802.3.html           ////
//// and                                                          ////
//// doc/802.3-2008_section3.pdf, Clause 37.                      ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
 
`include "ge_1000baseX_constants.v"
`include "timescale.v"
 
module ge_1000baseX_an (
 
   // --- clocks and reset ---
   input               ck, 
   input               reset,
 
   // --- Startup interface. ---
   input               startup_enable,
 
   // --- Auto-negotiation ctrl parameter ---
   output reg [2:0]    xmit,
   output reg [15:0]   tx_config,
   input      [15:0]   rx_config,
   input               rx_config_set,
   input               ability_match,
   input               acknowledge_match,
   input               consistency_match,
   input               idle_match,
 
   // --- RX_UNITDATA.indicate messages from RX state machine ---
   input      [2:0]    rudi,
 
 
   // --- Synchronisation Status ---
   input               sync_status,
   input               signal_detect,
 
   // --- GMII Register 0 - AN Basic Control register ---
   input               mr_main_reset,
   input               mr_loopback,
   input               mr_restart_an,
   input               mr_an_enable,
 
   // --- GMII Register 1 - AN Basic Status register ---		    
   output reg          mr_an_complete,
 
   // --- GMII register 4 - AN Advertisement		    
   input [15:0]         mr_adv_ability,
 
   // --- GMII register 5 - AN Link Partner Ability
   output reg [15:0]	mr_lp_adv_ability,
 
   // --- GMII register 6 - AN Expansion
   output reg           mr_np_abl,
   output reg           mr_page_rx,    	   
 
   // --- GMII register 7 - AN Next Page
   input [15:0]         mr_np_tx,
 
   // --- GMII register 8 - AN Link Partner Next Page
   output reg [15:0]    mr_lp_np_rx	    
 );
 
   //////////////////////////////////////////////////////////////////////////////
   //
   //////////////////////////////////////////////////////////////////////////////
 
   reg 			mr_np_loaded;
 
   //////////////////////////////////////////////////////////////////////////////
   //
   //////////////////////////////////////////////////////////////////////////////
 
`ifdef MODEL_TECH
  enum logic [3:0] {
`else
  localparam
`endif
		    S_PCS_AN_STARTUP_RUN          = 0,
		    S_PCS_AN_ENABLE               = 1,
		    S_PCS_AN_RESTART              = 2,
		    S_PCS_AN_DISABLE_LINK_OK      = 3,
		    S_PCS_AN_ABILITY_DETECT       = 4,
		    S_PCS_AN_ACKNOWLEDGE_DETECT   = 5,
		    S_PCS_AN_COMPLETE_ACKNOWLEDGE = 6,
		    S_PCS_AN_IDLE_DETECT          = 7,
		    S_PCS_AN_LINK_OK              = 8,
		    S_PCS_AN_NEXT_PAGE_WAIT       = 9
`ifdef MODEL_TECH
  } pcs_an_present, pcs_an_next;
`else
   ; reg [3:0] pcs_an_present, pcs_an_next;
`endif
 
   //////////////////////////////////////////////////////////////////////////////
   // rx configuration
   //////////////////////////////////////////////////////////////////////////////
 
   wire rx_config_clr = ~rx_config_set;
 
   //////////////////////////////////////////////////////////////////////////////
   //  Link timer
   //////////////////////////////////////////////////////////////////////////////  
 
`ifdef MODEL_TECH
`define LINK_TIMER_DONE 1250
`else
`define LINK_TIMER_DONE 1250000
`endif
 
   reg [20:0] link_timer_cnt;
   reg 	      link_timer_m_start, link_timer_m_inc;
   wire       link_timer_done;
 
   always @(posedge ck, posedge reset)
    if (reset)
      begin
         link_timer_cnt <= 0;
      end
    else
      begin
	 if      (link_timer_m_start) link_timer_cnt <= 0;
	 else if (link_timer_m_inc) link_timer_cnt <= link_timer_cnt + 1;
      end
 
      assign link_timer_done = (link_timer_cnt >= `LINK_TIMER_DONE);
 
   //////////////////////////////////////////////////////////////////////////////
   // xmit -  set to tell TX state machine state of AN
   //////////////////////////////////////////////////////////////////////////////
 
   reg 	    xmit_CONFIGURATION_m_set, xmit_DATA_m_set, xmit_IDLE_m_set;
 
   always @(posedge ck, posedge reset)
     if (reset)
       xmit <= `XMIT_IDLE;
     else
       begin  
	  if      (~mr_an_enable & rudi != `RUDI_INVALID) xmit <= `XMIT_DATA;         
	  else if (xmit_CONFIGURATION_m_set)              xmit <= `XMIT_CONFIGURATION; 
	  else if (xmit_DATA_m_set)                       xmit <= `XMIT_DATA;
	  else if (xmit_IDLE_m_set)                       xmit <= `XMIT_IDLE;
       end
 
   //////////////////////////////////////////////////////////////////////////////
   //  mr_lp_adv_ability - variable to store Link partner capabilities
   //////////////////////////////////////////////////////////////////////////////
 
   reg 	    mr_lp_adv_ability_set, mr_lp_adv_ability_clr;
 
     always @(posedge ck, posedge reset)
       if (reset)
	 mr_lp_adv_ability <= 16'h0;
       else
	 begin
	    if      (mr_lp_adv_ability_set) mr_lp_adv_ability <= rx_config;
	    else if (mr_lp_adv_ability_clr) mr_lp_adv_ability <= 16'h00;
	 end
 
   //////////////////////////////////////////////////////////////////////////////
   //  mr_np_loaded - variable to indicate if the next page has been loaded
   //////////////////////////////////////////////////////////////////////////////   
 
   reg      mr_np_loaded_m_set, mr_np_loaded_m_clr;
 
    always @(posedge ck, posedge reset)
     if (reset)
       mr_np_loaded <= 0;
     else
       begin
	  if       (mr_np_loaded_m_set) mr_np_loaded <= 1;
	  else if  (mr_np_loaded_m_clr) mr_np_loaded <= 0;
       end
 
   //////////////////////////////////////////////////////////////////////////////
   // mr_page_rx_m_clr 
   //////////////////////////////////////////////////////////////////////////////  
 
   reg 	    mr_page_rx_m_set, mr_page_rx_m_clr; 	    
 
   always @(posedge ck, posedge reset)
    if (reset)
      mr_page_rx <= 0;
    else 
      begin
	 if       (mr_page_rx_m_set) mr_page_rx <= 1;
  	 else if  (mr_page_rx_m_clr) mr_page_rx <= 0;
      end
 
   //////////////////////////////////////////////////////////////////////////////
   //  mr_an_complete
   //////////////////////////////////////////////////////////////////////////////
 
   reg       mr_an_complete_m_set, mr_an_complete_m_clr;
 
   always @(posedge ck, posedge reset)
     if (reset)
	mr_an_complete <= 0;
     else
       begin
	  if      (mr_an_complete_m_set) mr_an_complete <= 1;
	  else if (mr_an_complete_m_clr) mr_an_complete <= 0;
       end
 
   //////////////////////////////////////////////////////////////////////////////
   // toggle_tx
   //////////////////////////////////////////////////////////////////////////////
 
   reg toggle_tx, toggle_tx_adv_m_set, toggle_tx_toggle_m_set;
 
   always @(posedge ck, posedge reset)
     if (reset)
       toggle_tx <= 0;
     else
       begin
	  if      (toggle_tx_adv_m_set)    toggle_tx <= mr_adv_ability[12];
	  else if (toggle_tx_toggle_m_set) toggle_tx <= ~toggle_tx;
       end
 
   //////////////////////////////////////////////////////////////////////////////
   // toggle_rx
   //////////////////////////////////////////////////////////////////////////////   
 
   reg toggle_rx, toggle_rx_m_set;
 
   always @(posedge ck, posedge reset)
     if (reset)
       toggle_rx <= 0;
     else
       begin
	  if (toggle_rx_m_set) toggle_rx <= rx_config[11];
       end
 
   //////////////////////////////////////////////////////////////////////////////
   // tx_config register ctrl
   //////////////////////////////////////////////////////////////////////////////  
 
   reg 	    tx_config_m_clr, tx_config_ABILITY_m_set, tx_config_ACK_m_set, tx_config_NP_m_set;
 
   always @(posedge ck, posedge reset)
     if (reset)
       tx_config <= 0;
     else
       begin
	  if      (tx_config_m_clr)         tx_config     <= 0;
	  else if (tx_config_ACK_m_set)     tx_config[14] <= 1;
	  else if (tx_config_ABILITY_m_set) tx_config     <= { mr_adv_ability[15],1'b0, mr_adv_ability[13:0]                          };
   	  else if (tx_config_NP_m_set)      tx_config     <= { mr_np_tx[15],      1'b0, mr_np_tx[13:12],     toggle_tx,mr_np_tx[10:0] };
       end
 
   //////////////////////////////////////////////////////////////////////////////
   // np_rx
   //////////////////////////////////////////////////////////////////////////////
 
   reg  np_rx, np_rx_m_set;
 
    always @(posedge ck, posedge reset)
      if (reset)
	np_rx <= 0;
      else
	begin
	   if (np_rx_m_set) np_rx <= rx_config[15];
	end 
 
   //////////////////////////////////////////////////////////////////////////////
   //  mr_lp_np_rx
   //////////////////////////////////////////////////////////////////////////////   
 
   reg  mr_lp_np_rx_m_set;
 
    always @(posedge ck, posedge reset)
      if (reset)
	mr_lp_np_rx <= 0;
      else
	begin
	   if (mr_lp_np_rx_m_set) mr_lp_np_rx <= rx_config[15];
	end 
 
   //////////////////////////////////////////////////////////////////////////////
   // np_page_rx
   //////////////////////////////////////////////////////////////////////////////
 
   reg        np_page_rx, np_page_rx_m_set;
 
   always @(posedge ck, posedge reset)
     if (reset)
       np_page_rx <= 0;
     else
       begin
	  if (np_page_rx_m_set) np_page_rx <= 1;
       end 
 
   //////////////////////////////////////////////////////////////////////////////
   // resolve_priority
   //////////////////////////////////////////////////////////////////////////////
 
   reg        resolve_priority, resolve_priority_m_set;
 
   always @(posedge ck, posedge reset)
     if (reset)
       resolve_priority <= 0;
     else
       begin
	  if (resolve_priority_m_set) resolve_priority <= 1;
       end 
 
   //////////////////////////////////////////////////////////////////////////////
   // autonegotiation state machine registered part
   //////////////////////////////////////////////////////////////////////////////    
 
   always @(posedge ck, posedge reset)
 
     pcs_an_present <= (reset) ? S_PCS_AN_STARTUP_RUN :  pcs_an_next;
 
   //////////////////////////////////////////////////////////////////////////////
   // autonegotiation state machine - IEEE 802.3-2008 Clause 36
   //////////////////////////////////////////////////////////////////////////////
 
   always @*
     begin
	pcs_an_next = pcs_an_present;
 
	xmit_CONFIGURATION_m_set = 0; xmit_DATA_m_set = 0; xmit_IDLE_m_set = 0;
 
	mr_np_loaded_m_set = 0; mr_np_loaded_m_clr = 0;
 
	mr_page_rx_m_set = 0;  mr_page_rx_m_clr = 0;
 
	mr_an_complete_m_set = 0;  mr_an_complete_m_clr = 0;
 
	mr_lp_adv_ability_set = 0;  mr_lp_adv_ability_clr = 0;
 
	tx_config_m_clr = 0; tx_config_ABILITY_m_set = 0;tx_config_ACK_m_set = 0;tx_config_NP_m_set = 0;
 
	link_timer_m_start = 0; link_timer_m_inc = 0;
 
	toggle_tx_adv_m_set = 0; toggle_tx_toggle_m_set = 0;
 
	toggle_rx_m_set = 0; mr_lp_np_rx_m_set = 0; np_rx_m_set = 0; np_page_rx_m_set = 0;
 
	resolve_priority_m_set = 0;
 
	case (pcs_an_present)
 
	  S_PCS_AN_STARTUP_RUN:
	    begin
	       pcs_an_next = startup_enable ? S_PCS_AN_ENABLE: S_PCS_AN_STARTUP_RUN;
	    end
 
 
	  S_PCS_AN_ENABLE:
	    begin
	       mr_page_rx_m_clr = 1;  mr_lp_adv_ability_clr = 1; mr_an_complete_m_clr = 1;
 
	       if (mr_an_enable)  
		 begin
		    xmit_CONFIGURATION_m_set = 1; tx_config_m_clr = 1;  
		 end
	       else xmit_IDLE_m_set = 1;
 
	       pcs_an_next = (mr_an_enable) ? S_PCS_AN_RESTART  : S_PCS_AN_DISABLE_LINK_OK; 
 
	       link_timer_m_start = mr_an_enable;
	    end
 
	  S_PCS_AN_RESTART:
	    begin
	       mr_np_loaded_m_clr = 1; tx_config_m_clr = 1; xmit_CONFIGURATION_m_set = 1;
 
	       pcs_an_next = (link_timer_done) ? S_PCS_AN_ABILITY_DETECT : S_PCS_AN_RESTART;
 
	       link_timer_m_inc = ~link_timer_done;
	    end
 
	  S_PCS_AN_DISABLE_LINK_OK:
	    begin
	       xmit_DATA_m_set = 1;
 
               pcs_an_next = S_PCS_AN_DISABLE_LINK_OK;
             end
 
	  S_PCS_AN_ABILITY_DETECT:
	    begin
	       toggle_tx_adv_m_set = 1; tx_config_ABILITY_m_set = 1;
 
	       pcs_an_next = (ability_match & rx_config_set) ? S_PCS_AN_ACKNOWLEDGE_DETECT : S_PCS_AN_ABILITY_DETECT;
 
	       mr_lp_adv_ability_set = (ability_match & rx_config_set);
 
	    end
 
	  S_PCS_AN_ACKNOWLEDGE_DETECT:
	    begin
	       tx_config_ACK_m_set = 1;
 
	       pcs_an_next = (acknowledge_match & consistency_match)  ? S_PCS_AN_COMPLETE_ACKNOWLEDGE : 
			     (acknowledge_match & ~consistency_match) ? S_PCS_AN_ENABLE               :
			     (ability_match & rx_config_clr)          ? S_PCS_AN_ENABLE               : S_PCS_AN_ACKNOWLEDGE_DETECT;
 
	       link_timer_m_start = (acknowledge_match & consistency_match);
	    end
 
	  S_PCS_AN_COMPLETE_ACKNOWLEDGE:
	    begin
	       toggle_tx_toggle_m_set = 1; toggle_rx_m_set = 1; np_rx_m_set = 1; mr_page_rx_m_set = 1;
 
	       if (ability_match & rx_config_clr)  pcs_an_next = S_PCS_AN_ENABLE;
 
	       else if (link_timer_done & (~ability_match | rx_config_set)) 
		 begin
		    link_timer_m_start = 1;  pcs_an_next = S_PCS_AN_IDLE_DETECT;
		 end
 
	       else link_timer_m_inc = ~link_timer_done;
	    end
 
	  S_PCS_AN_IDLE_DETECT:
	    begin
	       xmit_IDLE_m_set = 1; resolve_priority_m_set = 1;
 
	       pcs_an_next = (ability_match & rx_config_clr) ? S_PCS_AN_ENABLE : 
			     (idle_match & link_timer_done)  ? S_PCS_AN_LINK_OK : S_PCS_AN_IDLE_DETECT;
 
	       link_timer_m_inc = ~link_timer_done;
	    end
 
	  S_PCS_AN_LINK_OK:
	    begin
	       xmit_DATA_m_set = 1; mr_an_complete_m_set = 1; resolve_priority_m_set = 1;
 
	       pcs_an_next = (ability_match | mr_restart_an) ? S_PCS_AN_ENABLE : S_PCS_AN_LINK_OK;	       
	    end
	endcase 
 
	if      (~sync_status)          pcs_an_next = S_PCS_AN_ENABLE;
	else if (mr_main_reset)         pcs_an_next = S_PCS_AN_ENABLE;
        else if (mr_restart_an)   	pcs_an_next = S_PCS_AN_ENABLE;
        else if (rudi == `RUDI_INVALID) pcs_an_next = S_PCS_AN_ENABLE;
     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.