]>
Commit | Line | Data |
---|---|---|
1 | ////////////////////////////////////////////////////////////////////// | |
2 | //// //// | |
3 | //// File name "pci_parity_check.v" //// | |
4 | //// //// | |
5 | //// This file is part of the "PCI bridge" project //// | |
6 | //// http://www.opencores.org/cores/pci/ //// | |
7 | //// //// | |
8 | //// Author(s): //// | |
9 | //// - Miha Dolenc (mihad@opencores.org) //// | |
10 | //// //// | |
11 | //// All additional information is avaliable in the README //// | |
12 | //// file. //// | |
13 | //// //// | |
14 | //// //// | |
15 | ////////////////////////////////////////////////////////////////////// | |
16 | //// //// | |
17 | //// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org //// | |
18 | //// //// | |
19 | //// This source file may be used and distributed without //// | |
20 | //// restriction provided that this copyright statement is not //// | |
21 | //// removed from the file and that any derivative work contains //// | |
22 | //// the original copyright notice and the associated disclaimer. //// | |
23 | //// //// | |
24 | //// This source file is free software; you can redistribute it //// | |
25 | //// and/or modify it under the terms of the GNU Lesser General //// | |
26 | //// Public License as published by the Free Software Foundation; //// | |
27 | //// either version 2.1 of the License, or (at your option) any //// | |
28 | //// later version. //// | |
29 | //// //// | |
30 | //// This source is distributed in the hope that it will be //// | |
31 | //// useful, but WITHOUT ANY WARRANTY; without even the implied //// | |
32 | //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// | |
33 | //// PURPOSE. See the GNU Lesser General Public License for more //// | |
34 | //// details. //// | |
35 | //// //// | |
36 | //// You should have received a copy of the GNU Lesser General //// | |
37 | //// Public License along with this source; if not, download it //// | |
38 | //// from http://www.opencores.org/lgpl.shtml //// | |
39 | //// //// | |
40 | ////////////////////////////////////////////////////////////////////// | |
41 | // | |
42 | // CVS Revision History | |
43 | // | |
44 | // $Log: pci_parity_check.v,v $ | |
45 | // Revision 1.1 2007-03-20 17:50:56 sithglan | |
46 | // add shit | |
47 | // | |
48 | // Revision 1.6 2003/02/13 18:26:33 mihad | |
49 | // Cleaned up the code. No functional changes. | |
50 | // | |
51 | // Revision 1.5 2003/01/27 16:49:31 mihad | |
52 | // Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. | |
53 | // | |
54 | // Revision 1.4 2002/08/13 11:03:53 mihad | |
55 | // Added a few testcases. Repaired wrong reset value for PCI_AM5 register. Repaired Parity Error Detected bit setting. Changed PCI_AM0 to always enabled(regardles of PCI_AM0 define), if image 0 is used as configuration image | |
56 | // | |
57 | // Revision 1.3 2002/02/01 15:25:12 mihad | |
58 | // Repaired a few bugs, updated specification, added test bench files and design document | |
59 | // | |
60 | // Revision 1.2 2001/10/05 08:14:30 mihad | |
61 | // Updated all files with inclusion of timescale file for simulation purposes. | |
62 | // | |
63 | // Revision 1.1.1.1 2001/10/02 15:33:47 mihad | |
64 | // New project directory structure | |
65 | // | |
66 | // | |
67 | ||
68 | // synopsys translate_off | |
69 | `include "timescale.v" | |
70 | // synopsys translate_on | |
71 | `include "pci_constants.v" | |
72 | `include "bus_commands.v" | |
73 | ||
74 | module pci_parity_check | |
75 | ( | |
76 | reset_in, | |
77 | clk_in, | |
78 | pci_par_in, | |
79 | pci_par_out, | |
80 | pci_par_en_out, | |
81 | pci_perr_in, | |
82 | pci_perr_out, | |
83 | pci_perr_out_in, | |
84 | pci_perr_en_out, | |
85 | pci_serr_en_in, | |
86 | pci_serr_out, | |
87 | pci_serr_out_in, | |
88 | pci_serr_en_out, | |
89 | pci_frame_reg_in, | |
90 | pci_frame_en_in, | |
91 | pci_irdy_en_in, | |
92 | pci_irdy_reg_in, | |
93 | pci_trdy_reg_in, | |
94 | pci_trdy_en_in, | |
95 | pci_par_en_in, | |
96 | pci_ad_out_in, | |
97 | pci_ad_reg_in, | |
98 | pci_cbe_in_in, | |
99 | pci_cbe_reg_in, | |
100 | pci_cbe_out_in, | |
101 | pci_cbe_en_in, | |
102 | pci_ad_en_in, | |
103 | par_err_response_in, | |
104 | par_err_detect_out, | |
105 | perr_mas_detect_out, | |
106 | ||
107 | serr_enable_in, | |
108 | sig_serr_out | |
109 | ||
110 | ); | |
111 | ||
112 | // system inputs | |
113 | input reset_in ; | |
114 | input clk_in ; | |
115 | ||
116 | // pci signals that are monitored or generated by parity error checker | |
117 | input pci_par_in ; // pci PAR input | |
118 | output pci_par_out ; // pci_PAR output | |
119 | output pci_par_en_out ; // pci PAR enable output | |
120 | input pci_perr_in ; // PERR# input | |
121 | output pci_perr_out ; // PERR# output | |
122 | output pci_perr_en_out ; // PERR# buffer enable output | |
123 | input pci_serr_en_in ; // SERR enable input | |
124 | output pci_serr_out ; // SERR# output | |
125 | input pci_serr_out_in ; // SERR# output value input | |
126 | input pci_perr_out_in ; // PERR# output value input | |
127 | output pci_serr_en_out ; // SERR# buffer enable output | |
128 | input pci_frame_reg_in ; // frame from pci bus input | |
129 | input pci_frame_en_in ; // frame enable driven by master state machine | |
130 | input pci_irdy_en_in ; // irdy enable input from PCI master | |
131 | input pci_irdy_reg_in ; // irdy from PCI bus | |
132 | input pci_trdy_reg_in ; // target ready from PCI bus | |
133 | input pci_trdy_en_in ; // target ready output enable | |
134 | input pci_par_en_in ; // par enable input | |
135 | input [31:0] pci_ad_out_in ; // data driven by bridge to PCI | |
136 | input [31:0] pci_ad_reg_in ; // data driven by other agents on PCI | |
137 | input [3:0] pci_cbe_in_in ; // cbe driven by outside agents | |
138 | input [3:0] pci_cbe_reg_in ; // registered cbe driven by outside agents | |
139 | input [3:0] pci_cbe_out_in ; // cbe driven by pci master state machine | |
140 | input pci_ad_en_in ; // ad enable input | |
141 | input par_err_response_in ; // parity error response bit from conf.space | |
142 | output par_err_detect_out ; // parity error detected signal out | |
143 | output perr_mas_detect_out ; // master asserted PERR or sampled PERR asserted | |
144 | input serr_enable_in ; // system error enable bit from conf.space | |
145 | output sig_serr_out ; // signalled system error output for configuration space | |
146 | input pci_cbe_en_in ; | |
147 | ||
148 | // FFs for frame input - used for determining whether PAR is sampled for address phase or for data phase | |
149 | reg frame_dec2 ; | |
150 | reg check_perr ; | |
151 | ||
152 | /*======================================================================================================================= | |
153 | CBE lines' parity is needed for overall parity calculation | |
154 | =======================================================================================================================*/ | |
155 | wire par_cbe_out = pci_cbe_out_in[3] ^ pci_cbe_out_in[2] ^ pci_cbe_out_in[1] ^ pci_cbe_out_in[0] ; | |
156 | wire par_cbe_in = pci_cbe_reg_in[3] ^ pci_cbe_reg_in[2] ^ pci_cbe_reg_in[1] ^ pci_cbe_reg_in[0] ; | |
157 | ||
158 | /*======================================================================================================================= | |
159 | Parity generator - parity is generated and assigned to output on every clock edge. PAR output enable is active | |
160 | one clock cycle after data output enable. Depending on whether master is performing access or target is responding, | |
161 | apropriate cbe data is included in parity generation. Non - registered CBE is used during reads through target SM | |
162 | =======================================================================================================================*/ | |
163 | ||
164 | // generate appropriate par signal | |
165 | wire data_par = (pci_ad_out_in[31] ^ pci_ad_out_in[30] ^ pci_ad_out_in[29] ^ pci_ad_out_in[28]) ^ | |
166 | (pci_ad_out_in[27] ^ pci_ad_out_in[26] ^ pci_ad_out_in[25] ^ pci_ad_out_in[24]) ^ | |
167 | (pci_ad_out_in[23] ^ pci_ad_out_in[22] ^ pci_ad_out_in[21] ^ pci_ad_out_in[20]) ^ | |
168 | (pci_ad_out_in[19] ^ pci_ad_out_in[18] ^ pci_ad_out_in[17] ^ pci_ad_out_in[16]) ^ | |
169 | (pci_ad_out_in[15] ^ pci_ad_out_in[14] ^ pci_ad_out_in[13] ^ pci_ad_out_in[12]) ^ | |
170 | (pci_ad_out_in[11] ^ pci_ad_out_in[10] ^ pci_ad_out_in[9] ^ pci_ad_out_in[8]) ^ | |
171 | (pci_ad_out_in[7] ^ pci_ad_out_in[6] ^ pci_ad_out_in[5] ^ pci_ad_out_in[4]) ^ | |
172 | (pci_ad_out_in[3] ^ pci_ad_out_in[2] ^ pci_ad_out_in[1] ^ pci_ad_out_in[0]) ; | |
173 | ||
174 | wire par_out_only = data_par ^ par_cbe_out ; | |
175 | ||
176 | pci_par_crit par_gen | |
177 | ( | |
178 | .par_out (pci_par_out), | |
179 | .par_out_in (par_out_only), | |
180 | .pci_cbe_en_in (pci_cbe_en_in), | |
181 | .data_par_in (data_par), | |
182 | .pci_cbe_in (pci_cbe_in_in) | |
183 | ) ; | |
184 | ||
185 | // PAR enable = ad output enable delayed by one clock | |
186 | assign pci_par_en_out = pci_ad_en_in ; | |
187 | ||
188 | /*======================================================================================================================= | |
189 | Parity checker - parity is checked on every clock cycle. When parity error is detected, appropriate action is taken | |
190 | to signal address parity errors on SERR if enabled and data parity errors on PERR# if enabled. Logic also drives | |
191 | outputs to configuration space to set appropriate status bits if parity error is detected. PAR signal is checked on | |
192 | master read operations or writes through pci target. Master read is performed when master drives irdy output and | |
193 | doesn't drive ad lines. Writes through target are performed when target is driving trdy and doesn't drive ad lines. | |
194 | =======================================================================================================================*/ | |
195 | ||
196 | // equation indicating whether to check and generate or not PERR# signal on next cycle | |
197 | wire perr_generate = ~pci_par_en_in && ~pci_ad_en_in // par was not generated on this cycle, so it should be checked | |
198 | && ((pci_irdy_en_in && ~pci_trdy_reg_in) || // and master is driving irdy and target is signaling ready | |
199 | (pci_trdy_en_in && ~pci_irdy_reg_in)) ; // or target is driving trdy and master is signaling ready | |
200 | ||
201 | wire data_in_par = (pci_ad_reg_in[31] ^ pci_ad_reg_in[30] ^ pci_ad_reg_in[29] ^ pci_ad_reg_in[28]) ^ | |
202 | (pci_ad_reg_in[27] ^ pci_ad_reg_in[26] ^ pci_ad_reg_in[25] ^ pci_ad_reg_in[24]) ^ | |
203 | (pci_ad_reg_in[23] ^ pci_ad_reg_in[22] ^ pci_ad_reg_in[21] ^ pci_ad_reg_in[20]) ^ | |
204 | (pci_ad_reg_in[19] ^ pci_ad_reg_in[18] ^ pci_ad_reg_in[17] ^ pci_ad_reg_in[16]) ^ | |
205 | (pci_ad_reg_in[15] ^ pci_ad_reg_in[14] ^ pci_ad_reg_in[13] ^ pci_ad_reg_in[12]) ^ | |
206 | (pci_ad_reg_in[11] ^ pci_ad_reg_in[10] ^ pci_ad_reg_in[9] ^ pci_ad_reg_in[8]) ^ | |
207 | (pci_ad_reg_in[7] ^ pci_ad_reg_in[6] ^ pci_ad_reg_in[5] ^ pci_ad_reg_in[4]) ^ | |
208 | (pci_ad_reg_in[3] ^ pci_ad_reg_in[2] ^ pci_ad_reg_in[1] ^ pci_ad_reg_in[0]) ; | |
209 | ||
210 | //wire perr = (cbe_par_reg ^ pci_par_in ^ data_in_par) ; | |
211 | wire perr ; | |
212 | wire perr_n ; | |
213 | wire perr_en ; | |
214 | ||
215 | assign pci_perr_out = perr_n ; | |
216 | ||
217 | // parity error output assignment | |
218 | //assign pci_perr_out = ~(perr && perr_generate) ; | |
219 | ||
220 | wire non_critical_par = par_cbe_in ^ data_in_par ; | |
221 | ||
222 | pci_perr_crit perr_crit_gen | |
223 | ( | |
224 | .perr_out (perr), | |
225 | .perr_n_out (perr_n), | |
226 | .non_critical_par_in(non_critical_par), | |
227 | .pci_par_in (pci_par_in), | |
228 | .perr_generate_in (perr_generate) | |
229 | ) ; | |
230 | ||
231 | // PERR# enable | |
232 | wire pci_perr_en_reg ; | |
233 | pci_perr_en_crit perr_en_crit_gen | |
234 | ( | |
235 | .reset_in (reset_in), | |
236 | .clk_in (clk_in), | |
237 | .perr_en_out (pci_perr_en_out), | |
238 | .perr_en_reg_out (pci_perr_en_reg), | |
239 | .non_critical_par_in (non_critical_par), | |
240 | .pci_par_in (pci_par_in), | |
241 | .perr_generate_in (perr_generate), | |
242 | .par_err_response_in (par_err_response_in) | |
243 | ) ; | |
244 | ||
245 | // address phase decoding | |
246 | always@(posedge reset_in or posedge clk_in) | |
247 | begin | |
248 | if (reset_in) | |
249 | frame_dec2 <= #`FF_DELAY 1'b0 ; | |
250 | else | |
251 | frame_dec2 <= #`FF_DELAY pci_frame_reg_in ; | |
252 | end | |
253 | ||
254 | // address phase parity error checking - done after address phase is detected - which is - when bridge's master is not driving frame, | |
255 | // frame was asserted on previous cycle and was not asserted two cycles before. | |
256 | wire check_for_serr_on_first = ~pci_frame_reg_in && frame_dec2 && ~pci_frame_en_in ; | |
257 | ||
258 | reg check_for_serr_on_second ; | |
259 | always@(posedge reset_in or posedge clk_in) | |
260 | begin | |
261 | if ( reset_in ) | |
262 | check_for_serr_on_second <= #`FF_DELAY 1'b0 ; | |
263 | else | |
264 | check_for_serr_on_second <= #`FF_DELAY check_for_serr_on_first && ( pci_cbe_reg_in == `BC_DUAL_ADDR_CYC ) ; | |
265 | end | |
266 | ||
267 | wire check_for_serr = check_for_serr_on_first || check_for_serr_on_second ; | |
268 | ||
269 | wire serr_generate = check_for_serr && serr_enable_in && par_err_response_in ; | |
270 | ||
271 | pci_serr_en_crit serr_en_crit_gen | |
272 | ( | |
273 | .serr_en_out (pci_serr_en_out), | |
274 | .pci_par_in (pci_par_in), | |
275 | .non_critical_par_in(non_critical_par), | |
276 | .serr_generate_in (serr_generate) | |
277 | ); | |
278 | ||
279 | ||
280 | // serr is enabled only for reporting errors - route this signal to configuration space | |
281 | assign sig_serr_out = pci_serr_en_in ; | |
282 | ||
283 | // SERR# output is always 0, just enable is driven apropriately | |
284 | pci_serr_crit serr_crit_gen | |
285 | ( | |
286 | .serr_out (pci_serr_out), | |
287 | .non_critical_par_in (non_critical_par), | |
288 | .pci_par_in (pci_par_in), | |
289 | .serr_check_in (check_for_serr) | |
290 | ); | |
291 | ||
292 | /*======================================================================================================================================= | |
293 | Synchronizing mechanism detecting what is supposed to be done - PERR# generation or PERR# checking | |
294 | =======================================================================================================================================*/ | |
295 | // perr should be checked one clock after PAR is generated | |
296 | always@(posedge reset_in or posedge clk_in) | |
297 | begin | |
298 | if ( reset_in ) | |
299 | check_perr <= #`FF_DELAY 1'b0 ; | |
300 | else | |
301 | check_perr <= #`FF_DELAY pci_par_en_in ; | |
302 | end | |
303 | ||
304 | wire perr_sampled_in = ~pci_perr_in && check_perr ; | |
305 | reg perr_sampled ; | |
306 | always@(posedge reset_in or posedge clk_in) | |
307 | begin | |
308 | if (reset_in) | |
309 | perr_sampled <= #`FF_DELAY 1'b0 ; | |
310 | else | |
311 | perr_sampled <= #`FF_DELAY perr_sampled_in ; | |
312 | end | |
313 | ||
314 | // assign output for parity error detected bit | |
315 | assign par_err_detect_out = ~pci_serr_out_in || ~pci_perr_out_in ;//|| perr_sampled ; MihaD - removed - detected parity error is set only during Master Reads or Target Writes | |
316 | ||
317 | // FF indicating that that last operation was done as bus master | |
318 | reg frame_and_irdy_en_prev ; | |
319 | reg frame_and_irdy_en_prev_prev ; | |
320 | reg master_perr_report ; | |
321 | always@(posedge reset_in or posedge clk_in) | |
322 | begin | |
323 | if ( reset_in ) | |
324 | begin | |
325 | master_perr_report <= #`FF_DELAY 1'b0 ; | |
326 | frame_and_irdy_en_prev <= #`FF_DELAY 1'b0 ; | |
327 | frame_and_irdy_en_prev_prev <= #`FF_DELAY 1'b0 ; | |
328 | end | |
329 | else | |
330 | begin | |
331 | master_perr_report <= #`FF_DELAY frame_and_irdy_en_prev_prev ; | |
332 | frame_and_irdy_en_prev <= #`FF_DELAY pci_irdy_en_in && pci_frame_en_in ; | |
333 | frame_and_irdy_en_prev_prev <= #`FF_DELAY frame_and_irdy_en_prev ; | |
334 | end | |
335 | end | |
336 | ||
337 | assign perr_mas_detect_out = master_perr_report && ( (par_err_response_in && perr_sampled) || pci_perr_en_reg ) ; | |
338 | ||
339 | endmodule |