| 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 |