Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / pcs_tx_ctrl.v
// ========== 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
// have any questions.
//
// ========== Copyright Header End ============================================
// @(#)pcs_tx_ctrl.v 1.5G
/**********************************************************************/
/* Project Name : GEM */
/* 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 */
/* domain. */
/* */
/* 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 */
/* */
/* Modifications : */
/* 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 */
/**********************************************************************/
`include "pcs_define.h"
module pcs_tx_ctrl (txclk,reset_tx,enable_pci, // inputs
odd_tx,tx_en_d,tx_er_d,pos_disp_tx_p,
crs_rx,txd_eq_crs_ext,
col_test_pci,link_up_tx,
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 tx_err; //
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
reg tx_err_at_sop;
wire tx_err_at_sop_d1;
parameter K285 = 4'h0,
D_IDLE = 4'h1,
START_OF_STREAM = 4'h2,
TRANSMIT_STREAM = 4'h3,
CRS_EXT = 4'h4,
END_R = 4'h7,
CHECK_DISP = 4'h9,
FLIP_DISP = 4'hA;
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)
begin
transmitting = 1'h0;
tx_enc_ctrl_sel = `PCS_ENC_K285;
inc_pkt_cnt = 1'h0;
tx_err_at_sop = 1'b0;
nxt_tx_state_tx = K285;
case (tx_state_tx) // synopsys parallel_case full_case
K285 : // 0
if (reset_tx | odd_tx)
nxt_tx_state_tx = K285;
else if (tx_en_d & link_up_tx & enable_tx)
begin
transmitting = 1'h1;
tx_enc_ctrl_sel = `PCS_ENC_SOP;
tx_err_at_sop = tx_er_d; // loj
nxt_tx_state_tx = TRANSMIT_STREAM;
inc_pkt_cnt = 1'h1;
end
else
nxt_tx_state_tx = D_IDLE;
D_IDLE : // 1
begin
tx_enc_ctrl_sel = `PCS_ENC_IDLE2;
if (tx_en_d & link_up_tx)
begin
inc_pkt_cnt = 1'h1;
nxt_tx_state_tx = START_OF_STREAM;
end
else
nxt_tx_state_tx = K285;
end
START_OF_STREAM : // 2
begin
transmitting = 1'h1;
tx_enc_ctrl_sel = `PCS_ENC_SOP;
tx_err_at_sop = tx_er_d; // loj
nxt_tx_state_tx = TRANSMIT_STREAM;
end
TRANSMIT_STREAM : // 3
if (tx_en_d)
begin
transmitting = 1'h1;
if (tx_err)
tx_enc_ctrl_sel = `PCS_ENC_H_CHAR;
else
tx_enc_ctrl_sel = `PCS_ENC_DATA;
nxt_tx_state_tx = TRANSMIT_STREAM;
end
else
begin
transmitting = 1'h1;
tx_enc_ctrl_sel = `PCS_ENC_T_CHAR;
nxt_tx_state_tx = TRANSMIT_STREAM;
if (txd_eq_crs_ext)
nxt_tx_state_tx = CRS_EXT;
else if (tx_err)
begin
tx_enc_ctrl_sel = `PCS_ENC_H_CHAR;
nxt_tx_state_tx = CRS_EXT;
end
else
begin
nxt_tx_state_tx = END_R;
transmitting = odd_tx; // if odd, 3rd byte from end
end
end
CRS_EXT : // 4
begin // add extra R's
transmitting = 1'h1;
tx_enc_ctrl_sel = `PCS_ENC_R_CHAR;
if (txd_eq_crs_ext)
nxt_tx_state_tx = CRS_EXT;
else if (tx_err) // includes carrier extension error
begin
nxt_tx_state_tx = CRS_EXT;
tx_enc_ctrl_sel = `PCS_ENC_H_CHAR;
end
else if (tx_en_d)
begin
tx_enc_ctrl_sel = `PCS_ENC_SOP;
nxt_tx_state_tx = TRANSMIT_STREAM;
end
else
nxt_tx_state_tx = END_R;
end
END_R : // 7
begin
tx_enc_ctrl_sel = `PCS_ENC_R_CHAR;
if (!odd_tx)
nxt_tx_state_tx = END_R;
else
nxt_tx_state_tx = CHECK_DISP;
end
CHECK_DISP : // 9
if (pos_disp_tx_p)
nxt_tx_state_tx = FLIP_DISP;
else
nxt_tx_state_tx = D_IDLE;
FLIP_DISP : // A
begin
tx_enc_ctrl_sel = `PCS_ENC_IDLE1;
nxt_tx_state_tx = K285;
end // case: FLIP_DISP
default:nxt_tx_state_tx = K285;
endcase
end
// state registers
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);
endmodule // pcs_tx_ctrl