Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / pcs_decoder.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: pcs_decoder.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_decoder.v 1.3G
/**********************************************************************/
/* Project Name : CASSINI */
/* Module Name : PCS Decoder Block */
/* Description : This block decodes an incoming data stream of */
/* 10 bits to 8 bits of data as well as special */
/* characters. The Fibre channel special characters */
/* are called K characters. They go along with */
/* special data symbols to mark an "ordered set". */
/* The K characters are flagged with kchar and the */
/* the special data characters are flagged also. */
/* Running disparity is calculated on a per clock */
/* regardless of disparity errors. Running disparity */
/* and decode errors are flagged. Kchar and special */
/* chararacter flags are not asserted when a decode */
/* error occurs. */
/* */
/* Assumptions : none. */
/* */
/* Parent module : pcs_rx_dpath.v */
/* Child modules : pcs_rx_disparity.v */
/* Author Name : Linda Chen */
/* Date Created : 10/21/96 */
/* */
/* Copyright (c) 1994, Sun Microsystems, Inc. */
/* Sun Proprietary and Confidential */
/* */
/* Modifications : */
/* 7/22/97 : removed flag got_d_idle_pp, not needed */
/* 11/14/97: removed if else check for I1 and I2 */
/* 11/14/97: added decode check for reserved K chars */
/* 11/14/97: marked unknown kchar as none of the known */
/* ones */
/* 12/9/98 : added detection for characters within 1 */
/* bit of K28.5 of correct disparity for */
/* carrier detect generation */
/* Synthesis Notes : none yet */
/**********************************************************************/
module pcs_decoder(rx_10bdec_in,rxclk, // inputs
rx_8bdec_out,dec_err_pp,disp_err_pp, // outputs
kchar_pp,got_d_linkconf_pp,comma_pp,k285w1_pp);
input [9:0] rx_10bdec_in; // receive encoded 10 bit data
input rxclk; // rxclk, 125 MHz
output [7:0] rx_8bdec_out; // decoded data byte
output dec_err_pp, // flag to mark decoding error
disp_err_pp; // flag to mark running disparity error
output kchar_pp; // flag to mark k character
output got_d_linkconf_pp; // flag to mark special char for link conf
output comma_pp; // flag to mark comma characters
output k285w1_pp; // flag to mark all chars within 1 bit
// the same as k28.5
wire dec_err1,dec_err2, // decode error flags for most/least sig bits
rderr1, rderr2, // running disp. flags for most/least sig bits
RDreg, newRD; // running disparity signals
wire k285w1_p_match, // find characters within one bit of k28.5
k285w1_n_match; // of the right disparity for carrier detect
wire pos_disp;
/*
** Running disparity calculator
*/
pcs_rx_disparity pcs_rx_disparity (rx_10bdec_in, RDreg, newRD, pos_disp);
/*
** Call of functions to decode most and least significant bits of data
*/
assign {rx_8bdec_out[4:0],dec_err1,kchar_pp,//got_d_idle_pp,
got_d_linkconf_pp,comma_pp,rderr1} =
deco1_fcn(rx_10bdec_in,RDreg),
{rx_8bdec_out[7:5],dec_err2,rderr2} =
deco2_fcn(rx_10bdec_in[3:0],newRD,kchar_pp);
assign dec_err_pp = dec_err1 | dec_err2,
disp_err_pp = rderr1 | rderr2,
k285w1_p_match = ((rx_10bdec_in == 10'b110000_0101) ||
(rx_10bdec_in == 10'b010000_0101) ||
(rx_10bdec_in == 10'b100000_0101) ||
(rx_10bdec_in == 10'b111000_0101) ||
(rx_10bdec_in == 10'b110100_0101) ||
(rx_10bdec_in == 10'b110010_0101) ||
(rx_10bdec_in == 10'b110001_0101) ||
(rx_10bdec_in == 10'b110000_1101) ||
(rx_10bdec_in == 10'b110000_0001) ||
(rx_10bdec_in == 10'b110000_0111) ||
(rx_10bdec_in == 10'b110000_0100) ),
k285w1_n_match = ((rx_10bdec_in == 10'b001111_1010) ||
(rx_10bdec_in == 10'b101111_1010) ||
(rx_10bdec_in == 10'b011111_1010) ||
(rx_10bdec_in == 10'b000111_1010) ||
(rx_10bdec_in == 10'b001011_1010) ||
(rx_10bdec_in == 10'b001101_1010) ||
(rx_10bdec_in == 10'b001110_1010) ||
(rx_10bdec_in == 10'b001111_0010) ||
(rx_10bdec_in == 10'b001111_1110) ||
(rx_10bdec_in == 10'b001111_1000) ||
(rx_10bdec_in == 10'b001111_1011)),
k285w1_pp = ((k285w1_n_match & ~RDreg) || (k285w1_p_match & RDreg));
/*
** Register to hold running disparity
*/
REG #(1) r_run_disp ( .din(pos_disp), .clk(rxclk), .qout(RDreg) );
/*
** Function to do 6b5b decode on most significant bits of rx_10bdata
** ~RDreg means that you can only get this code if the beginning
** running disparity is one. So if zero, error is flagged.
** RDreg means that you can only get this code if the beginning
** running disparity is zero. So if one, error is flagged.
** 1'b0 means that this code can be received whether the
** running disparity is zero or one. So no check is done.
**
** The function output is:
** {decodata[4:0],dec_err1,kchar,got_d_linkconf_pp,rderr}
*/
function [9:0] deco1_fcn;
input [9:0] rx_data;
input RDreg;
case (rx_data[9:4]) //synopsys parallel_case
6'b011000: deco1_fcn = {5'b00000,2'b00,1'b0,1'b0,~RDreg};
6'b100111: deco1_fcn = {5'b00000,2'b00,1'b0,1'b0,RDreg};
6'b100010: deco1_fcn = {5'b00001,2'b00,1'b0,1'b0,~RDreg};
6'b011101: deco1_fcn = {5'b00001,2'b00,1'b0,1'b0,RDreg};
/* D2 */ 6'b010010: if (rx_data[3:0]==4'b0101) // ConfigB
deco1_fcn = {5'b00010,2'b00,1'b1,1'b0,~RDreg};
else deco1_fcn = {5'b00010,2'b00,1'b0,1'b0,~RDreg};
/* D2 */ 6'b101101: if (rx_data[3:0]==4'b0101) // ConfigB
deco1_fcn = {5'b00010,2'b00,1'b1,1'b0,RDreg};
else deco1_fcn = {5'b00010,2'b00,1'b0,1'b0,RDreg};
6'b110001: deco1_fcn = {5'b00011,2'b00,1'b0,1'b0,1'b0};
6'b001010: deco1_fcn = {5'b00100,2'b00,1'b0,1'b0,~RDreg};
6'b110101: deco1_fcn = {5'b00100,2'b00,1'b0,1'b0,RDreg};
/* D5 */ 6'b101001: deco1_fcn = {5'b00101,2'b00,1'b0,1'b0,1'b0}; // I1
6'b011001: deco1_fcn = {5'b00110,2'b00,1'b0,1'b0,1'b0};
6'b000111: deco1_fcn = {5'b00111,2'b00,1'b0,1'b0,~RDreg};
6'b111000: deco1_fcn = {5'b00111,2'b00,1'b0,1'b0,RDreg};
6'b000110: deco1_fcn = {5'b01000,2'b00,1'b0,1'b0,~RDreg};
6'b111001: deco1_fcn = {5'b01000,2'b00,1'b0,1'b0,RDreg};
6'b100101: deco1_fcn = {5'b01001,2'b00,1'b0,1'b0,1'b0};
6'b010101: deco1_fcn = {5'b01010,2'b00,1'b0,1'b0,1'b0};
6'b110100: deco1_fcn = {5'b01011,2'b00,1'b0,1'b0,1'b0};
6'b001101: deco1_fcn = {5'b01100,2'b00,1'b0,1'b0,1'b0};
6'b101100: deco1_fcn = {5'b01101,2'b00,1'b0,1'b0,1'b0};
6'b011100: deco1_fcn = {5'b01110,2'b00,1'b0,1'b0,1'b0};
6'b101000: deco1_fcn = {5'b01111,2'b00,1'b0,1'b0,~RDreg};
6'b010111: deco1_fcn = {5'b01111,2'b00,1'b0,1'b0,RDreg};
/* D16 */ 6'b100100: deco1_fcn = {5'b10000,2'b00,1'b0,1'b0,~RDreg}; // I2
/* D16 */ 6'b011011: deco1_fcn = {5'b10000,2'b00,1'b0,1'b0,RDreg}; // I2
6'b100011: deco1_fcn = {5'b10001,2'b00,1'b0,1'b0,1'b0};
6'b010011: deco1_fcn = {5'b10010,2'b00,1'b0,1'b0,1'b0};
6'b110010: deco1_fcn = {5'b10011,2'b00,1'b0,1'b0,1'b0};
6'b001011: deco1_fcn = {5'b10100,2'b00,1'b0,1'b0,1'b0};
/* D21 */ 6'b101010: if (rx_data[3:0]==4'b1010) // ConfigA
deco1_fcn = {5'b10101,2'b00,1'b1,1'b0,1'b0};
else deco1_fcn = {5'b10101,2'b00,1'b0,1'b0,1'b0};
6'b011010: deco1_fcn = {5'b10110,2'b00,1'b0,1'b0,1'b0};
/* D23 */ 6'b000101: if (rx_data[3:0]==4'b0111) // R
deco1_fcn = {5'b00001,2'b01,1'b0,1'b0,~RDreg};
else deco1_fcn = {5'b10111,2'b00,1'b0,1'b0,~RDreg};
/* D23 */ 6'b111010: if (rx_data[3:0]==4'b1000) // R
deco1_fcn = {5'b00001,2'b01,1'b0,1'b0,RDreg};
else deco1_fcn = {5'b10111,2'b00,1'b0,1'b0,RDreg};
6'b001100: deco1_fcn = {5'b11000,2'b00,1'b0,1'b0,~RDreg};
6'b110011: deco1_fcn = {5'b11000,2'b00,1'b0,1'b0,RDreg};
6'b100110: deco1_fcn = {5'b11001,2'b00,1'b0,1'b0,1'b0};
6'b010110: deco1_fcn = {5'b11010,2'b00,1'b0,1'b0,1'b0};
/* D27 */ 6'b001001: if (rx_data[3:0]==4'b0111) // S
deco1_fcn = {5'b00010,2'b01,1'b0,1'b0,~RDreg};
else deco1_fcn = {5'b11011,2'b00,1'b0,1'b0,~RDreg};
/* D27 */ 6'b110110: if (rx_data[3:0]==4'b1000) // S
deco1_fcn = {5'b00010,2'b01,1'b0,1'b0,RDreg};
else deco1_fcn = {5'b11011,2'b00,1'b0,1'b0,RDreg};
6'b001110: deco1_fcn = {5'b11100,2'b00,1'b0,1'b0,1'b0};
/* D29 */ 6'b010001: if (rx_data[3:0]==4'b0111) // T
deco1_fcn = {5'b00100,2'b01,1'b0,1'b0,~RDreg};
else deco1_fcn = {5'b11101,2'b00,1'b0,1'b0,~RDreg};
/* D29 */ 6'b101110: if (rx_data[3:0]==4'b1000) // T
deco1_fcn = {5'b00100,2'b01,1'b0,1'b0,RDreg};
else deco1_fcn = {5'b11101,2'b00,1'b0,1'b0,RDreg};
/* D30 */ 6'b100001: if (rx_data[3:0]==4'b0111) // H
deco1_fcn = {5'b01000,2'b01,1'b0,1'b0,~RDreg};
else deco1_fcn = {5'b11110,2'b00,1'b0,1'b0,~RDreg};
/* D30 */ 6'b011110: if (rx_data[3:0]==4'b1000) // H
deco1_fcn = {5'b01000,2'b01,1'b0,1'b0,RDreg};
else deco1_fcn = {5'b11110,2'b00,1'b0,1'b0,RDreg};
6'b010100: deco1_fcn = {5'b11111,2'b00,1'b0,1'b0,~RDreg};
6'b101011: deco1_fcn = {5'b11111,2'b00,1'b0,1'b0,RDreg};
/* K28 */ 6'b001111: if (rx_data[3:0]==4'b1010)
deco1_fcn = {5'b10000,2'b01,1'b0,1'b1,RDreg};
else if (rx_data[3:0]==4'b1001)
deco1_fcn = {5'b00000,2'b01,1'b0,1'b1,RDreg};
else if (rx_data[3:0]==4'b1000)
deco1_fcn = {5'b00000,2'b01,1'b0,1'b1,RDreg};
else deco1_fcn = {5'h0,2'b01,1'b0,1'b0,RDreg};
/* K28 */ 6'b110000: if (rx_data[3:0]==4'b0101)
deco1_fcn = {5'b10000,2'b01,1'b0,1'b1,~RDreg};
else deco1_fcn = {5'h0,2'b01,1'b0,1'b0,RDreg};
default:
deco1_fcn = {5'h0,2'b10,1'b0,1'b0,1'b0}; // dec_err1
endcase
endfunction
/*
** Function to do 4b3b decode on least significant bits of rx_10bdata
** This decodes and checks K characters properly also.
*/
function [4:0] deco2_fcn; //{decodata[7:5],dec_err2,rderr2}
input [3:0] rx_data;
input newRD, kchar;
if (kchar)
deco2_fcn = {3'b111,1'b0,(rx_data[3]^newRD)};
else
case (rx_data[3:0]) //synopsys parallel_case
4'b1011: deco2_fcn = {3'b000,1'b0,newRD};
4'b0100: deco2_fcn = {3'b000,1'b0,~newRD};
4'b1001: deco2_fcn = {3'b001,2'b0};
4'b0101: deco2_fcn = {3'b010,2'b0};
4'b1100: deco2_fcn = {3'b011,1'b0,newRD};
4'b0011: deco2_fcn = {3'b011,1'b0,~newRD};
4'b1101: deco2_fcn = {3'b100,1'b0,newRD};
4'b0010: deco2_fcn = {3'b100,1'b0,~newRD};
4'b1010: deco2_fcn = {3'b101,2'b0};
4'b0110: deco2_fcn = {3'b110,2'b0};
4'b1110: deco2_fcn = {3'b111,1'b0,newRD};
4'b0001: deco2_fcn = {3'b111,1'b0,~newRD};
4'b1000: deco2_fcn = {3'b111,1'b0,~newRD};
4'b0111: deco2_fcn = {3'b111,1'b0,newRD};
default : deco2_fcn[4:0] = 5'b00010;
endcase
endfunction
endmodule