// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: pcs_tx_ctrl.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 ============================================
// @(#)pcs_tx_ctrl.v 1.5G
/**********************************************************************/
/* Module Name : PCS Tx Control Block */
/* Description : This block sends control signals to the Encoder */
/* block which indicates which characters should go */
/* on the media. When link is down, the link config */
/* block takes control over the media so the Tx */
/* Control block controls are irrelevant at that */
/* time. The controls are deasserted. */
/* If the disparity is positive at the end of the */
/* packet, disparity is flipped to negative. The */
/* Start of Frame character always resides in an */
/* even byte location. One or two bytes of the */
/* preamble are replaced by the Tx Control block */
/* depending on if the last character of Idle needs */
/* to be sent out. One byte may be replaced with */
/* the last portion of Idle, and one byte replaced */
/* with the Start of Frame character. */
/* CRS and COL of the GMII interface are generated */
/* here. They are asynchronous because they are *//* generated in part from crs_rx from the rx clock */
/* Assumptions : none. */
/* Parent module : pcs.v */
/* Child modules : none. */
/* Author Name : Linda Chen */
/* Date Created : 10/18/96 */
/* Copyright (c) 1994, Sun Microsystems, Inc. */
/* Sun Proprietary and Confidential */
/* 11/17/97 : removed tx_eq_crs_err signal */
/* : deassert transmitting two bytes before idle */
/* conditionally with odd lookahead */
/* 12/9/98 : disabled crs upon ~enable_tx */
/* Synthesis Notes : none yet */
/**********************************************************************/
module pcs_tx_ctrl (txclk,reset_tx,enable_pci, // inputs
odd_tx,tx_en_d,tx_er_d,pos_disp_tx_p,
tx_enc_ctrl_sel,crs,col,tx_state_tx,
tx_pkt_cnt_tx); // outputs
input txclk; // Tx Clk 125 MHz
input reset_tx; // hw and sw reset OR'ed
input enable_pci; // enable for PCS
input odd_tx; // byte polarity on media
input tx_en_d; // GMII transmit enable from Mac
input tx_er_d; // GMII transmit error from Mac
input pos_disp_tx_p; // disparity of data tx_8b_enc_in
input crs_rx; // activity on receive media
input txd_eq_crs_ext; // incoming txd maps to crs extension code
input col_test_pci; // collision test enable
input link_up_tx; // used to disable gmii inputs
output [3:0] tx_enc_ctrl_sel; // control inputs for encoder
output crs; // async carrier sense signal over GMII
output col; // async collision signal over GMII
output [3:0] tx_state_tx; // tx control state bits to slave
output [10:0] tx_pkt_cnt_tx; // packet counter
wire crs, col; // GMII signals to MAC
wire [10:0] nxt_pkt_cnt; // next packet count value
wire enable_tx; // enable for PCS in tx clock domain
wire [3:0] tx_state_tx; // tx control state bits to slave
reg transmitting; // tx is actively transmitting
reg [3:0] tx_enc_ctrl_sel;// tx mux control
reg inc_pkt_cnt; // increment packet count
reg [3:0] nxt_tx_state_tx;// next state
assign crs = enable_tx & (crs_rx | transmitting),
col = (col_test_pci | crs_rx) & transmitting,
nxt_pkt_cnt = (inc_pkt_cnt)? tx_pkt_cnt_tx + 1'h1 : tx_pkt_cnt_tx;
FD1 tx_err_at_sop_d1_FD1(.CP(txclk), .D(tx_err_at_sop), .Q(tx_err_at_sop_d1));
assign tx_err = tx_err_at_sop_d1 | tx_er_d;
/* Tx Control state machine */
always @ (tx_state_tx or reset_tx or odd_tx or
tx_en_d or link_up_tx or enable_tx or
tx_err or tx_er_d or txd_eq_crs_ext or pos_disp_tx_p)
tx_enc_ctrl_sel = `PCS_ENC_K285;
case (tx_state_tx) // synopsys parallel_case full_case
else if (tx_en_d & link_up_tx & enable_tx)
tx_enc_ctrl_sel = `PCS_ENC_SOP;
tx_err_at_sop = tx_er_d; // loj
nxt_tx_state_tx = TRANSMIT_STREAM;
nxt_tx_state_tx = D_IDLE;
tx_enc_ctrl_sel = `PCS_ENC_IDLE2;
if (tx_en_d & link_up_tx)
nxt_tx_state_tx = START_OF_STREAM;
tx_enc_ctrl_sel = `PCS_ENC_SOP;
tx_err_at_sop = tx_er_d; // loj
nxt_tx_state_tx = TRANSMIT_STREAM;
tx_enc_ctrl_sel = `PCS_ENC_H_CHAR;
tx_enc_ctrl_sel = `PCS_ENC_DATA;
nxt_tx_state_tx = TRANSMIT_STREAM;
tx_enc_ctrl_sel = `PCS_ENC_T_CHAR;
nxt_tx_state_tx = TRANSMIT_STREAM;
nxt_tx_state_tx = CRS_EXT;
tx_enc_ctrl_sel = `PCS_ENC_H_CHAR;
nxt_tx_state_tx = CRS_EXT;
transmitting = odd_tx; // if odd, 3rd byte from end
tx_enc_ctrl_sel = `PCS_ENC_R_CHAR;
nxt_tx_state_tx = CRS_EXT;
else if (tx_err) // includes carrier extension error
nxt_tx_state_tx = CRS_EXT;
tx_enc_ctrl_sel = `PCS_ENC_H_CHAR;
tx_enc_ctrl_sel = `PCS_ENC_SOP;
nxt_tx_state_tx = TRANSMIT_STREAM;
tx_enc_ctrl_sel = `PCS_ENC_R_CHAR;
nxt_tx_state_tx = CHECK_DISP;
nxt_tx_state_tx = FLIP_DISP;
nxt_tx_state_tx = D_IDLE;
tx_enc_ctrl_sel = `PCS_ENC_IDLE1;
default:nxt_tx_state_tx = K285;
RREG #(4) tx_state_tx_RREG (tx_state_tx, txclk, reset_tx, nxt_tx_state_tx);
RREG #(11) pkt_cnt_tx_RREG(tx_pkt_cnt_tx, txclk, reset_tx, nxt_pkt_cnt);
SYNCREG enable_tx_SYNCREG(enable_tx,txclk,enable_pci);