| 1 | // ========== Copyright Header Begin ========================================== |
| 2 | // |
| 3 | // OpenSPARC T2 Processor File: pcs_decoder.v |
| 4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved |
| 5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
| 6 | // |
| 7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 8 | // |
| 9 | // This program is free software; you can redistribute it and/or modify |
| 10 | // it under the terms of the GNU General Public License as published by |
| 11 | // the Free Software Foundation; version 2 of the License. |
| 12 | // |
| 13 | // This program is distributed in the hope that it will be useful, |
| 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | // GNU General Public License for more details. |
| 17 | // |
| 18 | // You should have received a copy of the GNU General Public License |
| 19 | // along with this program; if not, write to the Free Software |
| 20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | // |
| 22 | // For the avoidance of doubt, and except that if any non-GPL license |
| 23 | // choice is available it will apply instead, Sun elects to use only |
| 24 | // the General Public License version 2 (GPLv2) at this time for any |
| 25 | // software where a choice of GPL license versions is made |
| 26 | // available with the language indicating that GPLv2 or any later version |
| 27 | // may be used, or where a choice of which version of the GPL is applied is |
| 28 | // otherwise unspecified. |
| 29 | // |
| 30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 31 | // CA 95054 USA or visit www.sun.com if you need additional information or |
| 32 | // have any questions. |
| 33 | // |
| 34 | // ========== Copyright Header End ============================================ |
| 35 | // @(#)pcs_decoder.v 1.3G |
| 36 | /**********************************************************************/ |
| 37 | /* Project Name : CASSINI */ |
| 38 | /* Module Name : PCS Decoder Block */ |
| 39 | /* Description : This block decodes an incoming data stream of */ |
| 40 | /* 10 bits to 8 bits of data as well as special */ |
| 41 | /* characters. The Fibre channel special characters */ |
| 42 | /* are called K characters. They go along with */ |
| 43 | /* special data symbols to mark an "ordered set". */ |
| 44 | /* The K characters are flagged with kchar and the */ |
| 45 | /* the special data characters are flagged also. */ |
| 46 | /* Running disparity is calculated on a per clock */ |
| 47 | /* regardless of disparity errors. Running disparity */ |
| 48 | /* and decode errors are flagged. Kchar and special */ |
| 49 | /* chararacter flags are not asserted when a decode */ |
| 50 | /* error occurs. */ |
| 51 | /* */ |
| 52 | /* Assumptions : none. */ |
| 53 | /* */ |
| 54 | /* Parent module : pcs_rx_dpath.v */ |
| 55 | /* Child modules : pcs_rx_disparity.v */ |
| 56 | /* Author Name : Linda Chen */ |
| 57 | /* Date Created : 10/21/96 */ |
| 58 | /* */ |
| 59 | /* Copyright (c) 1994, Sun Microsystems, Inc. */ |
| 60 | /* Sun Proprietary and Confidential */ |
| 61 | /* */ |
| 62 | /* Modifications : */ |
| 63 | /* 7/22/97 : removed flag got_d_idle_pp, not needed */ |
| 64 | /* 11/14/97: removed if else check for I1 and I2 */ |
| 65 | /* 11/14/97: added decode check for reserved K chars */ |
| 66 | /* 11/14/97: marked unknown kchar as none of the known */ |
| 67 | /* ones */ |
| 68 | /* 12/9/98 : added detection for characters within 1 */ |
| 69 | /* bit of K28.5 of correct disparity for */ |
| 70 | /* carrier detect generation */ |
| 71 | /* Synthesis Notes : none yet */ |
| 72 | /**********************************************************************/ |
| 73 | |
| 74 | module pcs_decoder(rx_10bdec_in,rxclk, // inputs |
| 75 | |
| 76 | rx_8bdec_out,dec_err_pp,disp_err_pp, // outputs |
| 77 | kchar_pp,got_d_linkconf_pp,comma_pp,k285w1_pp); |
| 78 | |
| 79 | input [9:0] rx_10bdec_in; // receive encoded 10 bit data |
| 80 | input rxclk; // rxclk, 125 MHz |
| 81 | |
| 82 | output [7:0] rx_8bdec_out; // decoded data byte |
| 83 | output dec_err_pp, // flag to mark decoding error |
| 84 | disp_err_pp; // flag to mark running disparity error |
| 85 | output kchar_pp; // flag to mark k character |
| 86 | output got_d_linkconf_pp; // flag to mark special char for link conf |
| 87 | output comma_pp; // flag to mark comma characters |
| 88 | output k285w1_pp; // flag to mark all chars within 1 bit |
| 89 | // the same as k28.5 |
| 90 | |
| 91 | wire dec_err1,dec_err2, // decode error flags for most/least sig bits |
| 92 | rderr1, rderr2, // running disp. flags for most/least sig bits |
| 93 | RDreg, newRD; // running disparity signals |
| 94 | wire k285w1_p_match, // find characters within one bit of k28.5 |
| 95 | k285w1_n_match; // of the right disparity for carrier detect |
| 96 | |
| 97 | wire pos_disp; |
| 98 | |
| 99 | /* |
| 100 | ** Running disparity calculator |
| 101 | */ |
| 102 | pcs_rx_disparity pcs_rx_disparity (rx_10bdec_in, RDreg, newRD, pos_disp); |
| 103 | |
| 104 | /* |
| 105 | ** Call of functions to decode most and least significant bits of data |
| 106 | */ |
| 107 | assign {rx_8bdec_out[4:0],dec_err1,kchar_pp,//got_d_idle_pp, |
| 108 | got_d_linkconf_pp,comma_pp,rderr1} = |
| 109 | deco1_fcn(rx_10bdec_in,RDreg), |
| 110 | {rx_8bdec_out[7:5],dec_err2,rderr2} = |
| 111 | deco2_fcn(rx_10bdec_in[3:0],newRD,kchar_pp); |
| 112 | |
| 113 | |
| 114 | assign dec_err_pp = dec_err1 | dec_err2, |
| 115 | disp_err_pp = rderr1 | rderr2, |
| 116 | k285w1_p_match = ((rx_10bdec_in == 10'b110000_0101) || |
| 117 | (rx_10bdec_in == 10'b010000_0101) || |
| 118 | (rx_10bdec_in == 10'b100000_0101) || |
| 119 | (rx_10bdec_in == 10'b111000_0101) || |
| 120 | (rx_10bdec_in == 10'b110100_0101) || |
| 121 | (rx_10bdec_in == 10'b110010_0101) || |
| 122 | (rx_10bdec_in == 10'b110001_0101) || |
| 123 | (rx_10bdec_in == 10'b110000_1101) || |
| 124 | (rx_10bdec_in == 10'b110000_0001) || |
| 125 | (rx_10bdec_in == 10'b110000_0111) || |
| 126 | (rx_10bdec_in == 10'b110000_0100) ), |
| 127 | k285w1_n_match = ((rx_10bdec_in == 10'b001111_1010) || |
| 128 | (rx_10bdec_in == 10'b101111_1010) || |
| 129 | (rx_10bdec_in == 10'b011111_1010) || |
| 130 | (rx_10bdec_in == 10'b000111_1010) || |
| 131 | (rx_10bdec_in == 10'b001011_1010) || |
| 132 | (rx_10bdec_in == 10'b001101_1010) || |
| 133 | (rx_10bdec_in == 10'b001110_1010) || |
| 134 | (rx_10bdec_in == 10'b001111_0010) || |
| 135 | (rx_10bdec_in == 10'b001111_1110) || |
| 136 | (rx_10bdec_in == 10'b001111_1000) || |
| 137 | (rx_10bdec_in == 10'b001111_1011)), |
| 138 | k285w1_pp = ((k285w1_n_match & ~RDreg) || (k285w1_p_match & RDreg)); |
| 139 | |
| 140 | |
| 141 | /* |
| 142 | ** Register to hold running disparity |
| 143 | */ |
| 144 | REG #(1) r_run_disp ( .din(pos_disp), .clk(rxclk), .qout(RDreg) ); |
| 145 | |
| 146 | /* |
| 147 | ** Function to do 6b5b decode on most significant bits of rx_10bdata |
| 148 | ** ~RDreg means that you can only get this code if the beginning |
| 149 | ** running disparity is one. So if zero, error is flagged. |
| 150 | ** RDreg means that you can only get this code if the beginning |
| 151 | ** running disparity is zero. So if one, error is flagged. |
| 152 | ** 1'b0 means that this code can be received whether the |
| 153 | ** running disparity is zero or one. So no check is done. |
| 154 | ** |
| 155 | ** The function output is: |
| 156 | ** {decodata[4:0],dec_err1,kchar,got_d_linkconf_pp,rderr} |
| 157 | */ |
| 158 | function [9:0] deco1_fcn; |
| 159 | input [9:0] rx_data; |
| 160 | input RDreg; |
| 161 | |
| 162 | case (rx_data[9:4]) //synopsys parallel_case |
| 163 | 6'b011000: deco1_fcn = {5'b00000,2'b00,1'b0,1'b0,~RDreg}; |
| 164 | 6'b100111: deco1_fcn = {5'b00000,2'b00,1'b0,1'b0,RDreg}; |
| 165 | 6'b100010: deco1_fcn = {5'b00001,2'b00,1'b0,1'b0,~RDreg}; |
| 166 | 6'b011101: deco1_fcn = {5'b00001,2'b00,1'b0,1'b0,RDreg}; |
| 167 | /* D2 */ 6'b010010: if (rx_data[3:0]==4'b0101) // ConfigB |
| 168 | deco1_fcn = {5'b00010,2'b00,1'b1,1'b0,~RDreg}; |
| 169 | else deco1_fcn = {5'b00010,2'b00,1'b0,1'b0,~RDreg}; |
| 170 | /* D2 */ 6'b101101: if (rx_data[3:0]==4'b0101) // ConfigB |
| 171 | deco1_fcn = {5'b00010,2'b00,1'b1,1'b0,RDreg}; |
| 172 | else deco1_fcn = {5'b00010,2'b00,1'b0,1'b0,RDreg}; |
| 173 | 6'b110001: deco1_fcn = {5'b00011,2'b00,1'b0,1'b0,1'b0}; |
| 174 | 6'b001010: deco1_fcn = {5'b00100,2'b00,1'b0,1'b0,~RDreg}; |
| 175 | 6'b110101: deco1_fcn = {5'b00100,2'b00,1'b0,1'b0,RDreg}; |
| 176 | /* D5 */ 6'b101001: deco1_fcn = {5'b00101,2'b00,1'b0,1'b0,1'b0}; // I1 |
| 177 | 6'b011001: deco1_fcn = {5'b00110,2'b00,1'b0,1'b0,1'b0}; |
| 178 | 6'b000111: deco1_fcn = {5'b00111,2'b00,1'b0,1'b0,~RDreg}; |
| 179 | 6'b111000: deco1_fcn = {5'b00111,2'b00,1'b0,1'b0,RDreg}; |
| 180 | 6'b000110: deco1_fcn = {5'b01000,2'b00,1'b0,1'b0,~RDreg}; |
| 181 | 6'b111001: deco1_fcn = {5'b01000,2'b00,1'b0,1'b0,RDreg}; |
| 182 | 6'b100101: deco1_fcn = {5'b01001,2'b00,1'b0,1'b0,1'b0}; |
| 183 | 6'b010101: deco1_fcn = {5'b01010,2'b00,1'b0,1'b0,1'b0}; |
| 184 | 6'b110100: deco1_fcn = {5'b01011,2'b00,1'b0,1'b0,1'b0}; |
| 185 | 6'b001101: deco1_fcn = {5'b01100,2'b00,1'b0,1'b0,1'b0}; |
| 186 | 6'b101100: deco1_fcn = {5'b01101,2'b00,1'b0,1'b0,1'b0}; |
| 187 | 6'b011100: deco1_fcn = {5'b01110,2'b00,1'b0,1'b0,1'b0}; |
| 188 | 6'b101000: deco1_fcn = {5'b01111,2'b00,1'b0,1'b0,~RDreg}; |
| 189 | 6'b010111: deco1_fcn = {5'b01111,2'b00,1'b0,1'b0,RDreg}; |
| 190 | /* D16 */ 6'b100100: deco1_fcn = {5'b10000,2'b00,1'b0,1'b0,~RDreg}; // I2 |
| 191 | /* D16 */ 6'b011011: deco1_fcn = {5'b10000,2'b00,1'b0,1'b0,RDreg}; // I2 |
| 192 | 6'b100011: deco1_fcn = {5'b10001,2'b00,1'b0,1'b0,1'b0}; |
| 193 | 6'b010011: deco1_fcn = {5'b10010,2'b00,1'b0,1'b0,1'b0}; |
| 194 | 6'b110010: deco1_fcn = {5'b10011,2'b00,1'b0,1'b0,1'b0}; |
| 195 | 6'b001011: deco1_fcn = {5'b10100,2'b00,1'b0,1'b0,1'b0}; |
| 196 | /* D21 */ 6'b101010: if (rx_data[3:0]==4'b1010) // ConfigA |
| 197 | deco1_fcn = {5'b10101,2'b00,1'b1,1'b0,1'b0}; |
| 198 | else deco1_fcn = {5'b10101,2'b00,1'b0,1'b0,1'b0}; |
| 199 | 6'b011010: deco1_fcn = {5'b10110,2'b00,1'b0,1'b0,1'b0}; |
| 200 | /* D23 */ 6'b000101: if (rx_data[3:0]==4'b0111) // R |
| 201 | deco1_fcn = {5'b00001,2'b01,1'b0,1'b0,~RDreg}; |
| 202 | else deco1_fcn = {5'b10111,2'b00,1'b0,1'b0,~RDreg}; |
| 203 | /* D23 */ 6'b111010: if (rx_data[3:0]==4'b1000) // R |
| 204 | deco1_fcn = {5'b00001,2'b01,1'b0,1'b0,RDreg}; |
| 205 | else deco1_fcn = {5'b10111,2'b00,1'b0,1'b0,RDreg}; |
| 206 | 6'b001100: deco1_fcn = {5'b11000,2'b00,1'b0,1'b0,~RDreg}; |
| 207 | 6'b110011: deco1_fcn = {5'b11000,2'b00,1'b0,1'b0,RDreg}; |
| 208 | 6'b100110: deco1_fcn = {5'b11001,2'b00,1'b0,1'b0,1'b0}; |
| 209 | 6'b010110: deco1_fcn = {5'b11010,2'b00,1'b0,1'b0,1'b0}; |
| 210 | /* D27 */ 6'b001001: if (rx_data[3:0]==4'b0111) // S |
| 211 | deco1_fcn = {5'b00010,2'b01,1'b0,1'b0,~RDreg}; |
| 212 | else deco1_fcn = {5'b11011,2'b00,1'b0,1'b0,~RDreg}; |
| 213 | /* D27 */ 6'b110110: if (rx_data[3:0]==4'b1000) // S |
| 214 | deco1_fcn = {5'b00010,2'b01,1'b0,1'b0,RDreg}; |
| 215 | else deco1_fcn = {5'b11011,2'b00,1'b0,1'b0,RDreg}; |
| 216 | 6'b001110: deco1_fcn = {5'b11100,2'b00,1'b0,1'b0,1'b0}; |
| 217 | /* D29 */ 6'b010001: if (rx_data[3:0]==4'b0111) // T |
| 218 | deco1_fcn = {5'b00100,2'b01,1'b0,1'b0,~RDreg}; |
| 219 | else deco1_fcn = {5'b11101,2'b00,1'b0,1'b0,~RDreg}; |
| 220 | /* D29 */ 6'b101110: if (rx_data[3:0]==4'b1000) // T |
| 221 | deco1_fcn = {5'b00100,2'b01,1'b0,1'b0,RDreg}; |
| 222 | else deco1_fcn = {5'b11101,2'b00,1'b0,1'b0,RDreg}; |
| 223 | /* D30 */ 6'b100001: if (rx_data[3:0]==4'b0111) // H |
| 224 | deco1_fcn = {5'b01000,2'b01,1'b0,1'b0,~RDreg}; |
| 225 | else deco1_fcn = {5'b11110,2'b00,1'b0,1'b0,~RDreg}; |
| 226 | /* D30 */ 6'b011110: if (rx_data[3:0]==4'b1000) // H |
| 227 | deco1_fcn = {5'b01000,2'b01,1'b0,1'b0,RDreg}; |
| 228 | else deco1_fcn = {5'b11110,2'b00,1'b0,1'b0,RDreg}; |
| 229 | 6'b010100: deco1_fcn = {5'b11111,2'b00,1'b0,1'b0,~RDreg}; |
| 230 | 6'b101011: deco1_fcn = {5'b11111,2'b00,1'b0,1'b0,RDreg}; |
| 231 | /* K28 */ 6'b001111: if (rx_data[3:0]==4'b1010) |
| 232 | deco1_fcn = {5'b10000,2'b01,1'b0,1'b1,RDreg}; |
| 233 | else if (rx_data[3:0]==4'b1001) |
| 234 | deco1_fcn = {5'b00000,2'b01,1'b0,1'b1,RDreg}; |
| 235 | else if (rx_data[3:0]==4'b1000) |
| 236 | deco1_fcn = {5'b00000,2'b01,1'b0,1'b1,RDreg}; |
| 237 | else deco1_fcn = {5'h0,2'b01,1'b0,1'b0,RDreg}; |
| 238 | /* K28 */ 6'b110000: if (rx_data[3:0]==4'b0101) |
| 239 | deco1_fcn = {5'b10000,2'b01,1'b0,1'b1,~RDreg}; |
| 240 | else deco1_fcn = {5'h0,2'b01,1'b0,1'b0,RDreg}; |
| 241 | default: |
| 242 | deco1_fcn = {5'h0,2'b10,1'b0,1'b0,1'b0}; // dec_err1 |
| 243 | endcase |
| 244 | endfunction |
| 245 | |
| 246 | /* |
| 247 | ** Function to do 4b3b decode on least significant bits of rx_10bdata |
| 248 | ** This decodes and checks K characters properly also. |
| 249 | */ |
| 250 | function [4:0] deco2_fcn; //{decodata[7:5],dec_err2,rderr2} |
| 251 | input [3:0] rx_data; |
| 252 | input newRD, kchar; |
| 253 | if (kchar) |
| 254 | deco2_fcn = {3'b111,1'b0,(rx_data[3]^newRD)}; |
| 255 | else |
| 256 | case (rx_data[3:0]) //synopsys parallel_case |
| 257 | 4'b1011: deco2_fcn = {3'b000,1'b0,newRD}; |
| 258 | 4'b0100: deco2_fcn = {3'b000,1'b0,~newRD}; |
| 259 | 4'b1001: deco2_fcn = {3'b001,2'b0}; |
| 260 | 4'b0101: deco2_fcn = {3'b010,2'b0}; |
| 261 | 4'b1100: deco2_fcn = {3'b011,1'b0,newRD}; |
| 262 | 4'b0011: deco2_fcn = {3'b011,1'b0,~newRD}; |
| 263 | 4'b1101: deco2_fcn = {3'b100,1'b0,newRD}; |
| 264 | 4'b0010: deco2_fcn = {3'b100,1'b0,~newRD}; |
| 265 | 4'b1010: deco2_fcn = {3'b101,2'b0}; |
| 266 | 4'b0110: deco2_fcn = {3'b110,2'b0}; |
| 267 | 4'b1110: deco2_fcn = {3'b111,1'b0,newRD}; |
| 268 | 4'b0001: deco2_fcn = {3'b111,1'b0,~newRD}; |
| 269 | 4'b1000: deco2_fcn = {3'b111,1'b0,~newRD}; |
| 270 | 4'b0111: deco2_fcn = {3'b111,1'b0,newRD}; |
| 271 | default : deco2_fcn[4:0] = 5'b00010; |
| 272 | endcase |
| 273 | endfunction |
| 274 | |
| 275 | endmodule |