Commit | Line | Data |
---|---|---|
86530b38 AT |
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 |