// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: xpcs_tx.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
/**********************************************************************/
/* Project Name : Vega */
/* Module Name : xpcs_tx */
/* Description : XPCS transmit top level. Ranmomizer and tx state */
/* machine (clause 48.2.6.2.1 ieee802.3ae). */
/* When xpcs receiver asserts local fault to XGMII */
/* due to link loss, the xpcs transmiter transmits */
/* remote faults and idles. */
/* When the receiver gets remote faults, the XPCS */
/* passes it on to the XGMII. The MAC then generates */
/* idles for XPCS to transmit to assist the remote */
/* node regain link. (clause 46.3.4 p285). */
/* Assumptions : none. */
/* Parent module : xpcs_tx.v */
/* Child modules : none. */
/* Author Name : Carlos Castil */
/* Date Created : 11/10/02 */
/* Copyright (c) 2002, Sun Microsystems, Inc. */
/* Sun Proprietary and Confidential */
/**********************************************************************/
input csr_tx_test_enable;
input [1:0] csr_test_pattern_sel;
output inc_tx_pkt_count_ref;
output csr_transmit_fault_ref;
output [7:0] tx_byte_0_enc;
output [7:0] tx_byte_1_enc;
output [7:0] tx_byte_2_enc;
output [7:0] tx_byte_3_enc;
parameter SEND_DATA = 4'h0;
parameter SEND_SDP = 4'h1;
parameter SEND_RANDOM_R = 4'h5;
parameter SEND_RANDOM_A = 4'h6;
parameter SEND_RANDOM_K = 4'h7;
parameter SEND_RANDOM_Q = 4'h8;
parameter UNDERRUN = 4'h9;
wire [7:0] tx_byte_0_mux;
wire [7:0] tx_byte_1_mux;
wire [7:0] tx_byte_2_mux;
wire [7:0] tx_byte_3_mux;
wire sel_d, sel_k, sel_a, sel_r, sel_q;
wire csr_transmit_fault_ref;
wire [1:0] test_pattern_sel;
/* ********************************************************** */
/* ********************************************************** */
SYNC_CELL u_sync_link_status (
.D (csr_link_status), // unsynchronized
.Q (link_status_tx)); // synchronized
SYNC_CELL u_sync_test_enable (
.D (csr_tx_test_enable), // unsynchronized
.Q (tx_test_enable)); // synchronized
SYNC_CELL u_sync_test_pattern_sel_0 (
.D (csr_test_pattern_sel[0]), // unsynchronized
.Q (test_pattern_sel[0])); // synchronized
SYNC_CELL u_sync_test_pattern_sel_1 (
.D (csr_test_pattern_sel[1]), // unsynchronized
.Q (test_pattern_sel[1])); // synchronized
// *******************************************************
// q_det function per clause 48.2.6.1.4 ieee 802.3ae
// *******************************************************
assign q_detect_local = tx_special_0_in & (tx_byte_0_in == `XPCS_ENC_SEQ) &
(tx_byte_1_in == `XPCS_ENC_D00) &
(tx_byte_2_in == `XPCS_ENC_D00) &
(tx_byte_3_in == `XPCS_ENC_D10) ;
always @ (posedge tx_clk)
q_det_local <= (q_detect_local) ? 1'b1 : (clr_q_det) ? 1'b0 : q_det_local;
assign q_detect_remote = tx_special_0_in & (tx_byte_0_in == `XPCS_ENC_SEQ) &
(tx_byte_1_in == `XPCS_ENC_D00) &
(tx_byte_2_in == `XPCS_ENC_D00) &
(tx_byte_3_in == `XPCS_ENC_D20) ;
always @ (posedge tx_clk)
q_det_remote <= ((!link_status_tx) | q_detect_remote) ? 1'b1 :
(clr_q_det) ? 1'b0 : q_det_remote;
assign q_detect = q_det_local | q_det_remote;
assign csr_transmit_fault_ref = q_detect;
// *******************************************************
// *******************************************************
assign xgmii_s_detect = tx_special_0_in & (tx_byte_0_in == `XPCS_ENC_SDP);
// *******************************************************
// *******************************************************
assign xgmii_d_detect = (!tx_special_0_in) |
( link_status_tx & !xgmii_s_detect );
// ***************************************************************
// ***************************************************************
assign term_det_0 = tx_special_0_mux & (tx_byte_0_mux == `XPCS_ENC_EGP) &
tx_special_1_mux & (tx_byte_1_mux == `XPCS_ENC_IDL) &
tx_special_2_mux & (tx_byte_2_mux == `XPCS_ENC_IDL) &
tx_special_3_mux & (tx_byte_3_mux == `XPCS_ENC_IDL);
assign term_det_1 = tx_special_1_mux & (tx_byte_1_mux == `XPCS_ENC_EGP) &
tx_special_2_mux & (tx_byte_2_mux == `XPCS_ENC_IDL) &
tx_special_3_mux & (tx_byte_3_mux == `XPCS_ENC_IDL);
assign term_det_2 = tx_special_2_mux & (tx_byte_2_mux == `XPCS_ENC_EGP) &
tx_special_3_mux & (tx_byte_3_mux == `XPCS_ENC_IDL);
assign term_det_3 = tx_special_3_mux & (tx_byte_3_mux == `XPCS_ENC_EGP);
assign inc_tx_pkt_count_ref = term_det_0 | term_det_1 | term_det_2 | term_det_3 ;
// ***************************************************************
// ***************************************************************
assign idle_det_0 = tx_special_0_in & (tx_byte_0_in == `XPCS_ENC_IDL);
assign idle_det_1 = tx_special_1_in & (tx_byte_1_in == `XPCS_ENC_IDL);
assign idle_det_2 = tx_special_2_in & (tx_byte_2_in == `XPCS_ENC_IDL);
assign idle_det_3 = tx_special_3_in & (tx_byte_3_in == `XPCS_ENC_IDL);
assign i_detect = idle_det_0 & idle_det_1 & idle_det_2 & idle_det_3;
// ***************************************************************
// State Machine 48.2.6.2.1 ieee 802.3ae
// ***************************************************************
/* *************************************************************************
{n_state, n_clr_a_cnt, n_clr_q_det, n_sel_s
n_sel_d, n_sel_r, n_sel_k, n_sel_a, n_sel_q};
** *************************************************************************/
sel_q} = transmit_fn (reset,
function [11:0] transmit_fn;
n_state = SEND_K; // send K
else if (!nxt_ifg | !a_cnt)
nxt_ifg = 1'b0; // select K next instead of A
nxt_ifg = 1'b1; // select A next instead of K
else if (code_sel & !a_cnt)
else if ((!code_sel) & !a_cnt)
else if (code_sel & !q_det)
else if ((!code_sel) & !q_det)
else if (code_sel & !a_cnt)
else if ((!code_sel) & !a_cnt)
transmit_fn = {n_state, n_clr_a_cnt, n_clr_q_det, n_sel_s,
n_sel_d, n_sel_r, n_sel_k, n_sel_a, n_sel_q};
// State machine register
always @ (posedge tx_clk)
// *******************************************************
// *******************************************************
always @ (posedge tx_clk)
tx_byte_0_in <= tx_byte_0;
tx_byte_1_in <= tx_byte_1;
tx_byte_2_in <= tx_byte_2;
tx_byte_3_in <= tx_byte_3;
always @ (posedge tx_clk)
tx_special_0_in <= tx_special_0;
tx_special_1_in <= tx_special_1;
tx_special_2_in <= tx_special_2;
tx_special_3_in <= tx_special_3;
always @ (posedge tx_clk)
tx_byte_0_int <= tx_byte_0_in;
tx_byte_1_int <= tx_byte_1_in;
tx_byte_2_int <= tx_byte_2_in;
tx_byte_3_int <= tx_byte_3_in;
always @ (posedge tx_clk)
tx_special_0_int <= tx_special_0_in;
tx_special_1_int <= tx_special_1_in;
tx_special_2_int <= tx_special_2_in;
tx_special_3_int <= tx_special_3_in;
// *******************************************************
// Data Path MUX and output register to Decoder
// *******************************************************
assign {tx_special_0_mux} = (sel_r | sel_k | sel_a) ? 1'b1 :
sel_q ? 1'b1 : {tx_special_0_int};
assign {tx_special_1_mux} = (sel_r | sel_k | sel_a) ? 1'b1 :
sel_q ? 1'b0 : {tx_special_1_int};
assign {tx_special_2_mux} = (sel_r | sel_k | sel_a) ? 1'b1 :
sel_q ? 1'b0 : {tx_special_2_int};
assign {tx_special_3_mux} = (sel_r | sel_k | sel_a) ? 1'b1 :
sel_q ? 1'b0 : {tx_special_3_int};
assign tx_byte_0_mux = sel_s ? `XPCS_ENC_SDP :
assign tx_byte_1_mux = sel_s ? tx_byte_1_int :
assign tx_byte_2_mux = sel_s ? tx_byte_2_int :
assign tx_byte_3_mux = sel_s ? tx_byte_3_int :
sel_q & q_det_remote ? `XPCS_ENC_D20 :
sel_q & q_det_local ? `XPCS_ENC_D10 :
always @ (posedge tx_clk)
tx_byte_0_enc <= tx_test_enable ? test_byte : term_det_0 ? `XPCS_ENC_EGP : tx_byte_0_mux ;
tx_byte_1_enc <= tx_test_enable ? test_byte : term_det_0 ? `XPCS_ENC_COM :
term_det_1 ? `XPCS_ENC_EGP : tx_byte_1_mux ;
tx_byte_2_enc <= tx_test_enable ? test_byte : term_det_0 ? `XPCS_ENC_COM :
term_det_1 ? `XPCS_ENC_COM :
term_det_2 ? `XPCS_ENC_EGP : tx_byte_2_mux ;
tx_byte_3_enc <= tx_test_enable ? test_byte : term_det_0 ? `XPCS_ENC_COM :
term_det_1 ? `XPCS_ENC_COM :
term_det_2 ? `XPCS_ENC_COM :
term_det_3 ? `XPCS_ENC_EGP : tx_byte_3_mux ;
always @ (posedge tx_clk)
tx_special_0_enc <= tx_test_enable ? test_special : (term_det_0) ? 1'b1 : tx_special_0_mux ;
tx_special_1_enc <= tx_test_enable ? test_special : (term_det_0 | term_det_1) ? 1'b1 : tx_special_1_mux;
tx_special_2_enc <= tx_test_enable ? test_special : (term_det_0 | term_det_1 | term_det_2) ? 1'b1 : tx_special_2_mux;
tx_special_3_enc <= tx_test_enable ? test_special :
(term_det_0 | term_det_1 | term_det_2 | term_det_3) ? 1'b1 : tx_special_3_mux;
// ***************************************************************
// ***************************************************************
xpcs_tx_randomizer xpcs_tx_randomizer_l (.tx_clk(tx_clk),
.align_count_exp(align_count_exp),
.clr_align_count(clr_a_cnt),
.code_sel(code_sel_random) );
// ****************************************************************
// Test mode logic high/low/mixed frequency patterns per Annex 48A
// 00 high freq, 01 low freq, 10 mixed freq.
// ****************************************************************
assign test_byte = (test_pattern_sel == 2'b00) ? `XPCS_ENC_TTH :
(test_pattern_sel == 2'b01) ? `XPCS_ENC_TTL :
(test_pattern_sel == 2'b10) ? `XPCS_ENC_COM : `XPCS_ENC_COM;
assign test_special = (test_pattern_sel == 2'b00) ? 1'b0 : // D21.5
(test_pattern_sel == 2'b01) ? 1'b1 : // K28.7
(test_pattern_sel == 2'b10) ? 1'b1 : 1'b1 ; // K28.5
// 0in state -var state -val SEND_DATA -next SEND_A SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_SDP -next SEND_DATA UNDERRUN SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_A -next SEND_RANDOM_R SEND_Q SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_K -next SEND_RANDOM_R SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_Q -next SEND_RANDOM_R SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_RANDOM_R -next SEND_RANDOM_A SEND_RANDOM_K SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_RANDOM_K -next SEND_RANDOM_A SEND_RANDOM_R SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_RANDOM_Q -next SEND_RANDOM_K SEND_RANDOM_R SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val SEND_RANDOM_A -next SEND_RANDOM_Q SEND_RANDOM_R SEND_RANDOM_K SEND_SDP SEND_K -clock tx_clk -reset reset
// 0in state -var state -val UNDERRUN -next SEND_A SEND_K -clock tx_clk -reset reset