[6] | 1 | // ========== Copyright Header Begin ========================================== |
---|
| 2 | // |
---|
| 3 | // OpenSPARC T1 Processor File: bw_rf_16x81.v |
---|
| 4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. |
---|
| 5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. |
---|
| 6 | // |
---|
| 7 | // The above named program is free software; you can redistribute it and/or |
---|
| 8 | // modify it under the terms of the GNU General Public |
---|
| 9 | // License version 2 as published by the Free Software Foundation. |
---|
| 10 | // |
---|
| 11 | // The above named program is distributed in the hope that it will be |
---|
| 12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
| 14 | // General Public License for more details. |
---|
| 15 | // |
---|
| 16 | // You should have received a copy of the GNU General Public |
---|
| 17 | // License along with this work; if not, write to the Free Software |
---|
| 18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
---|
| 19 | // |
---|
| 20 | // ========== Copyright Header End ============================================ |
---|
| 21 | module bw_rf_16x81( |
---|
| 22 | rd_clk, // read clock |
---|
| 23 | wr_clk, // read clock |
---|
| 24 | csn_rd, // read enable -- active low |
---|
| 25 | csn_wr, // write enable -- active low |
---|
| 26 | hold, // hold signal -- unflopped -- hold =1 holds input data |
---|
| 27 | testmux_sel, // bypass signal -- unflopped -- testmux_sel = 1 bypasses di to do |
---|
| 28 | scan_en, // Scan enable unflopped |
---|
| 29 | margin, // Delay for the circuits--- set to 01010101 |
---|
| 30 | rd_a, // read address |
---|
| 31 | wr_a, // Write address |
---|
| 32 | di, // Data input |
---|
| 33 | si, // scan in |
---|
| 34 | so, // scan out |
---|
| 35 | listen_out, // Listening flop-- |
---|
| 36 | do // Data out |
---|
| 37 | |
---|
| 38 | ); |
---|
| 39 | |
---|
| 40 | input rd_clk; |
---|
| 41 | input wr_clk; |
---|
| 42 | input csn_rd; |
---|
| 43 | input csn_wr; |
---|
| 44 | input hold; |
---|
| 45 | input testmux_sel; |
---|
| 46 | input scan_en; |
---|
| 47 | input [4:0] margin; |
---|
| 48 | input [3:0] rd_a; |
---|
| 49 | input [3:0] wr_a; |
---|
| 50 | input [80:0] di; |
---|
| 51 | input si; |
---|
| 52 | output so; |
---|
| 53 | output [80:0] do; |
---|
| 54 | output [80:0] listen_out; |
---|
| 55 | |
---|
| 56 | parameter SYNC_CLOCK_CHK1 = 1; |
---|
| 57 | parameter SYNC_CLOCK_CHK2 = 1; |
---|
| 58 | parameter SYNC_CLOCK_CHK3 = 1; |
---|
| 59 | parameter MARGIN_WARNING = 1; // margin warning is on by default |
---|
| 60 | |
---|
| 61 | |
---|
| 62 | |
---|
| 63 | |
---|
| 64 | // Start code |
---|
| 65 | reg [80:0] memarray[15:0] ; |
---|
| 66 | reg [80:0] array_out ; |
---|
| 67 | |
---|
| 68 | reg [80:0] array_out_latch ; |
---|
| 69 | |
---|
| 70 | |
---|
| 71 | |
---|
| 72 | reg [3:0] rd_a_ff ; |
---|
| 73 | wire [3:0] rd_a_ff_so; |
---|
| 74 | wire [3:0] rd_a_ff_si ; |
---|
| 75 | |
---|
| 76 | reg [3:0] wr_a_ff ; |
---|
| 77 | wire [3:0] wr_a_ff_so; |
---|
| 78 | wire [3:0] wr_a_ff_si ; |
---|
| 79 | |
---|
| 80 | reg [80:0] di_ff ; |
---|
| 81 | wire [80:0] di_ff_so; |
---|
| 82 | wire [80:0] di_ff_si; |
---|
| 83 | |
---|
| 84 | wire [80:0] listen_out_so; |
---|
| 85 | wire [80:0] listen_out_si ; |
---|
| 86 | reg [80:0] listen_out ; |
---|
| 87 | |
---|
| 88 | |
---|
| 89 | reg csn_rd_ff ; |
---|
| 90 | wire csn_rd_ff_si ; |
---|
| 91 | wire csn_rd_ff_so ; |
---|
| 92 | |
---|
| 93 | reg csn_wr_ff ; |
---|
| 94 | wire csn_wr_ff_si ; |
---|
| 95 | wire csn_wr_ff_so ; |
---|
| 96 | |
---|
| 97 | reg di_ff_latch_so ; |
---|
| 98 | /////////////////////////////////////// |
---|
| 99 | // Scan chain connections // |
---|
| 100 | /////////////////////////////////////// |
---|
| 101 | assign wr_a_ff_si[3:0] = {si , wr_a_ff_so[3:1]} ; |
---|
| 102 | assign csn_wr_ff_si = wr_a_ff_so[0] ; |
---|
| 103 | assign di_ff_si = {csn_wr_ff_so, di_ff_so[80:1]}; |
---|
| 104 | assign listen_out_si = {listen_out_so[79:0], di_ff_latch_so} ; |
---|
| 105 | assign csn_rd_ff_si = listen_out_so[80] ; |
---|
| 106 | assign rd_a_ff_si[3:0] = {rd_a_ff_so[2:0], csn_rd_ff_so} ; |
---|
| 107 | assign so = rd_a_ff_so[3] ; |
---|
| 108 | /////////////////////////////////////// |
---|
| 109 | // Instantiate a clock headers // |
---|
| 110 | /////////////////////////////////////// |
---|
| 111 | |
---|
| 112 | wire rd_ssclk = rd_clk ; // clk_en & rd_clk ; |
---|
| 113 | wire rd_local_clk = rd_ssclk | scan_en | hold ; |
---|
| 114 | wire rd_smclk = rd_ssclk | ~(scan_en | hold) ; |
---|
| 115 | |
---|
| 116 | wire wr_ssclk = wr_clk ; // clk_en & wr_clk ; |
---|
| 117 | wire wr_local_clk = wr_ssclk | scan_en | hold ; |
---|
| 118 | wire wr_smclk = wr_ssclk | ~(scan_en | hold) ; |
---|
| 119 | |
---|
| 120 | |
---|
| 121 | ///////////////////////////////////////////////////// |
---|
| 122 | // csn_rd Flop // |
---|
| 123 | ///////////////////////////////////////////////////// |
---|
| 124 | |
---|
| 125 | reg csn_rd_ff_inst_mdata ; |
---|
| 126 | wire csn_rd_ff_inst_smin ; |
---|
| 127 | reg csn_rd_ff_scan_out ; |
---|
| 128 | |
---|
| 129 | assign csn_rd_ff_inst_smin = hold ? csn_rd_ff_scan_out : csn_rd_ff_si ; |
---|
| 130 | always @(rd_smclk or rd_local_clk or csn_rd or csn_rd_ff_inst_smin ) begin |
---|
| 131 | if (!rd_local_clk) begin |
---|
| 132 | csn_rd_ff_inst_mdata = csn_rd ; |
---|
| 133 | end |
---|
| 134 | if (!rd_smclk) begin |
---|
| 135 | csn_rd_ff_inst_mdata = csn_rd_ff_inst_smin; |
---|
| 136 | end |
---|
| 137 | end |
---|
| 138 | always @(posedge rd_ssclk) begin |
---|
| 139 | csn_rd_ff_scan_out <= csn_rd_ff_inst_mdata ; |
---|
| 140 | end |
---|
| 141 | always @(rd_local_clk or csn_rd_ff_inst_mdata) begin |
---|
| 142 | if (rd_local_clk ) begin |
---|
| 143 | csn_rd_ff <= csn_rd_ff_inst_mdata ; |
---|
| 144 | end |
---|
| 145 | end |
---|
| 146 | assign csn_rd_ff_so = csn_rd_ff_scan_out; |
---|
| 147 | |
---|
| 148 | ///////////////////////////////////////////////////// |
---|
| 149 | |
---|
| 150 | ///////////////////////////////////////////////////// |
---|
| 151 | // rd_a Flop // |
---|
| 152 | ///////////////////////////////////////////////////// |
---|
| 153 | reg [3:0] rd_a_ff_inst_mdata ; |
---|
| 154 | wire [3:0] rd_a_ff_inst_smin ; |
---|
| 155 | reg [3:0] rd_a_ff_scan_out ; |
---|
| 156 | |
---|
| 157 | assign rd_a_ff_inst_smin[3:0] = hold ? rd_a_ff_scan_out[3:0] : rd_a_ff_si[3:0] ; |
---|
| 158 | always @(rd_smclk or rd_local_clk or rd_a or rd_a_ff_inst_smin ) begin |
---|
| 159 | if (!rd_local_clk) begin |
---|
| 160 | rd_a_ff_inst_mdata = rd_a[3:0] ; |
---|
| 161 | end |
---|
| 162 | if (!rd_smclk) begin |
---|
| 163 | rd_a_ff_inst_mdata = rd_a_ff_inst_smin; |
---|
| 164 | end |
---|
| 165 | end |
---|
| 166 | always @(posedge rd_ssclk) begin |
---|
| 167 | rd_a_ff_scan_out[3:0] <= rd_a_ff_inst_mdata ; |
---|
| 168 | end |
---|
| 169 | always @(rd_local_clk or rd_a_ff_inst_mdata) begin |
---|
| 170 | if (rd_local_clk) begin |
---|
| 171 | rd_a_ff[3:0] <= rd_a_ff_inst_mdata ; |
---|
| 172 | end |
---|
| 173 | end |
---|
| 174 | assign rd_a_ff_so[3:0] = rd_a_ff_scan_out[3:0] ; |
---|
| 175 | ///////////////////////////////////////////////////// |
---|
| 176 | |
---|
| 177 | ///////////////////////////////////////////////////// |
---|
| 178 | // csn_wr Flop // |
---|
| 179 | ///////////////////////////////////////////////////// |
---|
| 180 | reg csn_wr_ff_inst_mdata ; |
---|
| 181 | wire csn_wr_ff_inst_smin ; |
---|
| 182 | |
---|
| 183 | assign csn_wr_ff_inst_smin = hold ? csn_wr_ff : csn_wr_ff_si ; |
---|
| 184 | always @(wr_smclk or wr_local_clk or csn_wr or csn_wr_ff_inst_smin ) begin |
---|
| 185 | if (!wr_local_clk) begin |
---|
| 186 | csn_wr_ff_inst_mdata = csn_wr ; |
---|
| 187 | end |
---|
| 188 | if (!wr_smclk) begin |
---|
| 189 | csn_wr_ff_inst_mdata = csn_wr_ff_inst_smin; |
---|
| 190 | end |
---|
| 191 | end |
---|
| 192 | always @(posedge wr_ssclk) begin |
---|
| 193 | csn_wr_ff <= csn_wr_ff_inst_mdata ; |
---|
| 194 | end |
---|
| 195 | assign csn_wr_ff_so = csn_wr_ff; |
---|
| 196 | ///////////////////////////////////////////////////// |
---|
| 197 | |
---|
| 198 | ///////////////////////////////////////////////////// |
---|
| 199 | // wr_a Flop // |
---|
| 200 | ///////////////////////////////////////////////////// |
---|
| 201 | reg [3:0] wr_a_ff_inst_mdata ; |
---|
| 202 | wire [3:0] wr_a_ff_inst_smin ; |
---|
| 203 | |
---|
| 204 | assign wr_a_ff_inst_smin[3:0] = hold ? wr_a_ff[3:0] : wr_a_ff_si[3:0] ; |
---|
| 205 | always @(wr_smclk or wr_local_clk or wr_a or wr_a_ff_inst_smin ) begin |
---|
| 206 | if (!wr_local_clk) begin |
---|
| 207 | wr_a_ff_inst_mdata = wr_a[3:0] ; |
---|
| 208 | end |
---|
| 209 | if (!wr_smclk) begin |
---|
| 210 | wr_a_ff_inst_mdata = wr_a_ff_inst_smin; |
---|
| 211 | end |
---|
| 212 | end |
---|
| 213 | always @(posedge wr_ssclk) begin |
---|
| 214 | wr_a_ff[3:0] <= wr_a_ff_inst_mdata ; |
---|
| 215 | end |
---|
| 216 | assign wr_a_ff_so[3:0] = wr_a_ff[3:0] ; |
---|
| 217 | ///////////////////////////////////////////////////// |
---|
| 218 | |
---|
| 219 | ///////////////////////////////////////////////////// |
---|
| 220 | // di Flop // |
---|
| 221 | ///////////////////////////////////////////////////// |
---|
| 222 | reg [80:0] di_ff_inst_mdata ; |
---|
| 223 | wire [80:0] di_ff_inst_smin ; |
---|
| 224 | |
---|
| 225 | assign di_ff_inst_smin[80:0] = hold ? di_ff[80:0] : di_ff_si[80:0] ; |
---|
| 226 | always @(wr_smclk or wr_local_clk or di or di_ff_inst_smin ) begin |
---|
| 227 | if (!wr_local_clk) begin |
---|
| 228 | di_ff_inst_mdata = di[80:0] ; |
---|
| 229 | end |
---|
| 230 | if (!wr_smclk) begin |
---|
| 231 | di_ff_inst_mdata = di_ff_inst_smin; |
---|
| 232 | end |
---|
| 233 | end |
---|
| 234 | always @(posedge wr_ssclk) begin |
---|
| 235 | di_ff[80:0] <= di_ff_inst_mdata ; |
---|
| 236 | end |
---|
| 237 | assign di_ff_so[80:0] = di_ff[80:0] ; |
---|
| 238 | ///////////////////////////////////////////////////// |
---|
| 239 | |
---|
| 240 | wire wr_enable_l = csn_wr_ff | scan_en ; |
---|
| 241 | wire rd_enable_l = csn_rd_ff | scan_en ; |
---|
| 242 | |
---|
| 243 | // wire wr_clk_qual = wr_ssclk & ~scan_en ; |
---|
| 244 | always @(wr_ssclk or wr_a_ff or wr_enable_l or di_ff ) begin |
---|
| 245 | if (!wr_ssclk) begin |
---|
| 246 | if (!wr_enable_l) begin |
---|
| 247 | memarray[wr_a_ff] <= di_ff[80:0] ; |
---|
| 248 | end |
---|
| 249 | end |
---|
| 250 | end |
---|
| 251 | |
---|
| 252 | // wire rd_clk_qual = (rd_ssclk & ~scan_en) ; |
---|
| 253 | always @(rd_ssclk or rd_a_ff or rd_enable_l) begin |
---|
| 254 | if (rd_ssclk) begin |
---|
| 255 | if (rd_enable_l == 1'b0) begin |
---|
| 256 | array_out[80:0] <= memarray[rd_a_ff] ; |
---|
| 257 | end else if (rd_enable_l == 1'b1) begin |
---|
| 258 | array_out[80:0] <= 81'h1FFFFFFFFFFFFFFFFFFFF; |
---|
| 259 | end else begin |
---|
| 260 | array_out[80:0] <= 81'hXXXXXXXXXXXXXXXXXXXXX; |
---|
| 261 | end |
---|
| 262 | end |
---|
| 263 | end |
---|
| 264 | |
---|
| 265 | |
---|
| 266 | // synopsys translate_off |
---|
| 267 | |
---|
| 268 | `ifdef INNO_MUXEX |
---|
| 269 | `else |
---|
| 270 | always @(csn_rd_ff or csn_wr_ff or rd_a_ff or wr_a_ff) begin |
---|
| 271 | if ((SYNC_CLOCK_CHK1 == 0) & !csn_rd_ff & !csn_wr_ff & (rd_a_ff == wr_a_ff)) begin |
---|
| 272 | array_out <= 81'hxxxxxxxxxxxxxxxxxxxxx; |
---|
| 273 | `ifdef MODELSIM |
---|
| 274 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers", rd_a_ff, wr_a_ff); |
---|
| 275 | `else |
---|
| 276 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers", rd_a_ff, wr_a_ff); |
---|
| 277 | `endif |
---|
| 278 | end |
---|
| 279 | end |
---|
| 280 | `endif |
---|
| 281 | |
---|
| 282 | /////////////////////////////////////////////////////////////// |
---|
| 283 | // Purely ERROR checking code. // |
---|
| 284 | /////////////////////////////////////////////////////////////// |
---|
| 285 | reg [3:0] rd_a_ff_del ; |
---|
| 286 | reg csn_rd_ff_del ; |
---|
| 287 | reg rd_clk_del ; |
---|
| 288 | always @(rd_local_clk) begin |
---|
| 289 | if (rd_local_clk) rd_clk_del = #300 rd_local_clk; |
---|
| 290 | else rd_clk_del = #300 rd_local_clk; |
---|
| 291 | end |
---|
| 292 | always @(posedge rd_clk_del) begin |
---|
| 293 | rd_a_ff_del <= rd_a_ff ; |
---|
| 294 | csn_rd_ff_del <= csn_rd_ff ; |
---|
| 295 | end |
---|
| 296 | |
---|
| 297 | `ifdef INNO_MUXEX |
---|
| 298 | `else |
---|
| 299 | always @(csn_rd_ff_del or csn_wr_ff or rd_a_ff_del or wr_a_ff or rd_clk_del or wr_ssclk) begin |
---|
| 300 | if (SYNC_CLOCK_CHK2 == 0) begin |
---|
| 301 | if (rd_clk_del & !wr_ssclk & !csn_rd_ff_del & !csn_wr_ff & (rd_a_ff_del == wr_a_ff)) begin |
---|
| 302 | `ifdef MODELSIM |
---|
| 303 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff_del, wr_a_ff); |
---|
| 304 | `else |
---|
| 305 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff_del, wr_a_ff); |
---|
| 306 | `endif |
---|
| 307 | end |
---|
| 308 | end |
---|
| 309 | end |
---|
| 310 | `endif |
---|
| 311 | |
---|
| 312 | reg [3:0] wr_a_ff_del ; |
---|
| 313 | reg csn_wr_ff_del ; |
---|
| 314 | reg wr_clk_del ; |
---|
| 315 | always @(wr_ssclk) begin |
---|
| 316 | if (wr_ssclk) wr_clk_del = #300 wr_ssclk; |
---|
| 317 | else wr_clk_del = #300 wr_ssclk; |
---|
| 318 | end |
---|
| 319 | always @(posedge wr_clk_del) begin |
---|
| 320 | wr_a_ff_del <= wr_a_ff ; |
---|
| 321 | csn_wr_ff_del <= csn_wr_ff ; |
---|
| 322 | end |
---|
| 323 | |
---|
| 324 | `ifdef INNO_MUXEX |
---|
| 325 | `else |
---|
| 326 | always @(csn_rd_ff or csn_wr_ff_del or rd_a_ff or wr_a_ff_del or rd_local_clk or wr_clk_del) begin |
---|
| 327 | if (SYNC_CLOCK_CHK3 == 0) begin |
---|
| 328 | if (rd_local_clk & !wr_clk_del & !csn_rd_ff & !csn_wr_ff_del & (rd_a_ff == wr_a_ff_del)) begin |
---|
| 329 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff, wr_a_ff_del); |
---|
| 330 | end |
---|
| 331 | end |
---|
| 332 | end |
---|
| 333 | `endif |
---|
| 334 | |
---|
| 335 | /////////////////////////////////////////////////////////////// |
---|
| 336 | // end the ERROR checking code. // |
---|
| 337 | /////////////////////////////////////////////////////////////// |
---|
| 338 | /////////////////////////////////////// |
---|
| 339 | |
---|
| 340 | |
---|
| 341 | // synopsys translate_on |
---|
| 342 | |
---|
| 343 | /////////////////////////////////// |
---|
| 344 | // Transparent latch with reset |
---|
| 345 | /////////////////////////////////// |
---|
| 346 | |
---|
| 347 | always @(array_out or rd_ssclk) begin |
---|
| 348 | if (rd_ssclk) begin |
---|
| 349 | array_out_latch <= array_out ; |
---|
| 350 | end |
---|
| 351 | end |
---|
| 352 | |
---|
| 353 | always @(di_ff_so[0] or wr_ssclk) begin |
---|
| 354 | if (!wr_ssclk) begin |
---|
| 355 | di_ff_latch_so <= di_ff_so[0] ; |
---|
| 356 | end |
---|
| 357 | end |
---|
| 358 | |
---|
| 359 | |
---|
| 360 | assign do = testmux_sel ? di_ff : array_out_latch ; |
---|
| 361 | |
---|
| 362 | ///////////////////////////////////////////////////// |
---|
| 363 | // listen_out Flop // |
---|
| 364 | ///////////////////////////////////////////////////// |
---|
| 365 | reg [80:0] listen_out_ff_inst_mdata ; |
---|
| 366 | wire [80:0] listen_out_ff_inst_smin ; |
---|
| 367 | |
---|
| 368 | assign listen_out_ff_inst_smin[80:0] = hold ? do[80:0] : listen_out_si[80:0] ; |
---|
| 369 | always @(rd_smclk or rd_local_clk or do or listen_out_ff_inst_smin ) begin |
---|
| 370 | if (!rd_local_clk) begin |
---|
| 371 | listen_out_ff_inst_mdata = do[80:0] ; |
---|
| 372 | end |
---|
| 373 | if (!rd_smclk) begin |
---|
| 374 | listen_out_ff_inst_mdata = listen_out_ff_inst_smin; |
---|
| 375 | end |
---|
| 376 | end |
---|
| 377 | always @(posedge rd_ssclk) begin |
---|
| 378 | listen_out[80:0] <= listen_out_ff_inst_mdata ; |
---|
| 379 | end |
---|
| 380 | assign listen_out_so[80:0] = listen_out[80:0] ; |
---|
| 381 | |
---|
| 382 | // synopsys translate_off |
---|
| 383 | |
---|
| 384 | `ifdef INNO_MUXEX |
---|
| 385 | `else |
---|
| 386 | always @(posedge rd_clk) begin |
---|
| 387 | if ((MARGIN_WARNING == 0) & margin != 5'b10101) begin |
---|
| 388 | `ifdef MODELSIM |
---|
| 389 | $display ("sram_margin", "margin is not set to the default value") ; |
---|
| 390 | `else |
---|
| 391 | $error ("sram_margin", "margin is not set to the default value") ; |
---|
| 392 | `endif |
---|
| 393 | end |
---|
| 394 | end |
---|
| 395 | `endif |
---|
| 396 | |
---|
| 397 | // synopsys translate_on |
---|
| 398 | |
---|
| 399 | endmodule |
---|