[6] | 1 | // ========== Copyright Header Begin ========================================== |
---|
| 2 | // |
---|
| 3 | // OpenSPARC T1 Processor File: bw_rf_16x65.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_16x65( |
---|
| 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 [64:0] di; |
---|
| 51 | input si; |
---|
| 52 | output so; |
---|
| 53 | output [64:0] do; |
---|
| 54 | output [64:0] listen_out; |
---|
| 55 | |
---|
| 56 | parameter SYNC_CLOCK_CHK1 = 0; |
---|
| 57 | parameter SYNC_CLOCK_CHK2 = 0; |
---|
| 58 | parameter SYNC_CLOCK_CHK3 = 0; |
---|
| 59 | parameter MARGIN_WARNING = 0; // margin warning is on by default |
---|
| 60 | |
---|
| 61 | |
---|
| 62 | // Start code |
---|
| 63 | `ifdef DEFINE_0IN |
---|
| 64 | wire [64:0] array_out ; |
---|
| 65 | `else |
---|
| 66 | reg [64:0] memarray[15:0] ; |
---|
| 67 | reg [64:0] array_out ; |
---|
| 68 | `endif |
---|
| 69 | |
---|
| 70 | reg [64:0] array_out_latch ; |
---|
| 71 | |
---|
| 72 | |
---|
| 73 | reg [3:0] rd_a_ff ; |
---|
| 74 | wire [3:0] rd_a_ff_so; |
---|
| 75 | wire [3:0] rd_a_ff_si ; |
---|
| 76 | |
---|
| 77 | reg [3:0] wr_a_ff ; |
---|
| 78 | wire [3:0] wr_a_ff_so; |
---|
| 79 | wire [3:0] wr_a_ff_si ; |
---|
| 80 | |
---|
| 81 | reg [64:0] di_ff ; |
---|
| 82 | wire [64:0] di_ff_so; |
---|
| 83 | wire [64:0] di_ff_si; |
---|
| 84 | |
---|
| 85 | wire [64:0] listen_out_so; |
---|
| 86 | wire [64:0] listen_out_si ; |
---|
| 87 | reg [64:0] listen_out ; |
---|
| 88 | |
---|
| 89 | |
---|
| 90 | reg csn_rd_ff ; |
---|
| 91 | wire csn_rd_ff_si ; |
---|
| 92 | wire csn_rd_ff_so ; |
---|
| 93 | |
---|
| 94 | reg csn_wr_ff ; |
---|
| 95 | wire csn_wr_ff_si ; |
---|
| 96 | wire csn_wr_ff_so ; |
---|
| 97 | |
---|
| 98 | reg di_ff_latch_so ; |
---|
| 99 | /////////////////////////////////////// |
---|
| 100 | // Scan chain connections // |
---|
| 101 | /////////////////////////////////////// |
---|
| 102 | assign wr_a_ff_si[3:0] = {si , wr_a_ff_so[3:1]} ; |
---|
| 103 | assign csn_wr_ff_si = wr_a_ff_so[0] ; |
---|
| 104 | assign di_ff_si = {csn_wr_ff_so, di_ff_so[64:1]}; |
---|
| 105 | assign listen_out_si = {listen_out_so[63:0], di_ff_latch_so} ; |
---|
| 106 | assign csn_rd_ff_si = listen_out_so[64] ; |
---|
| 107 | assign rd_a_ff_si[3:0] = {rd_a_ff_so[2:0], csn_rd_ff_so} ; |
---|
| 108 | assign so = rd_a_ff_so[3] ; |
---|
| 109 | /////////////////////////////////////// |
---|
| 110 | // Instantiate a clock headers // |
---|
| 111 | /////////////////////////////////////// |
---|
| 112 | |
---|
| 113 | wire rd_ssclk = rd_clk ; // clk_en & rd_clk ; |
---|
| 114 | wire rd_local_clk = rd_ssclk | scan_en | hold ; |
---|
| 115 | wire rd_smclk = rd_ssclk | ~(scan_en | hold) ; |
---|
| 116 | |
---|
| 117 | wire wr_ssclk = wr_clk ; // clk_en & wr_clk ; |
---|
| 118 | wire wr_local_clk = wr_ssclk | scan_en | hold ; |
---|
| 119 | wire wr_smclk = wr_ssclk | ~(scan_en | hold) ; |
---|
| 120 | |
---|
| 121 | |
---|
| 122 | ///////////////////////////////////////////////////// |
---|
| 123 | // csn_rd Flop // |
---|
| 124 | ///////////////////////////////////////////////////// |
---|
| 125 | |
---|
| 126 | reg csn_rd_ff_inst_mdata ; |
---|
| 127 | wire csn_rd_ff_inst_smin ; |
---|
| 128 | reg csn_rd_ff_scan_out ; |
---|
| 129 | |
---|
| 130 | assign csn_rd_ff_inst_smin = hold ? csn_rd_ff_scan_out : csn_rd_ff_si ; |
---|
| 131 | always @(rd_smclk or rd_local_clk or csn_rd or csn_rd_ff_inst_smin ) begin |
---|
| 132 | if (!rd_local_clk) begin |
---|
| 133 | csn_rd_ff_inst_mdata = csn_rd ; |
---|
| 134 | end |
---|
| 135 | if (!rd_smclk) begin |
---|
| 136 | csn_rd_ff_inst_mdata = csn_rd_ff_inst_smin; |
---|
| 137 | end |
---|
| 138 | end |
---|
| 139 | always @(posedge rd_ssclk) begin |
---|
| 140 | csn_rd_ff_scan_out <= csn_rd_ff_inst_mdata ; |
---|
| 141 | end |
---|
| 142 | always @(rd_local_clk or csn_rd_ff_inst_mdata) begin |
---|
| 143 | if (rd_local_clk ) begin |
---|
| 144 | csn_rd_ff <= csn_rd_ff_inst_mdata ; |
---|
| 145 | end |
---|
| 146 | end |
---|
| 147 | assign csn_rd_ff_so = csn_rd_ff_scan_out; |
---|
| 148 | |
---|
| 149 | ///////////////////////////////////////////////////// |
---|
| 150 | |
---|
| 151 | ///////////////////////////////////////////////////// |
---|
| 152 | // rd_a Flop // |
---|
| 153 | ///////////////////////////////////////////////////// |
---|
| 154 | reg [3:0] rd_a_ff_inst_mdata ; |
---|
| 155 | wire [3:0] rd_a_ff_inst_smin ; |
---|
| 156 | reg [3:0] rd_a_ff_scan_out ; |
---|
| 157 | |
---|
| 158 | assign rd_a_ff_inst_smin[3:0] = hold ? rd_a_ff_scan_out[3:0] : rd_a_ff_si[3:0] ; |
---|
| 159 | always @(rd_smclk or rd_local_clk or rd_a or rd_a_ff_inst_smin ) begin |
---|
| 160 | if (!rd_local_clk) begin |
---|
| 161 | rd_a_ff_inst_mdata = rd_a[3:0] ; |
---|
| 162 | end |
---|
| 163 | if (!rd_smclk) begin |
---|
| 164 | rd_a_ff_inst_mdata = rd_a_ff_inst_smin; |
---|
| 165 | end |
---|
| 166 | end |
---|
| 167 | always @(posedge rd_ssclk) begin |
---|
| 168 | rd_a_ff_scan_out[3:0] <= rd_a_ff_inst_mdata ; |
---|
| 169 | end |
---|
| 170 | always @(rd_local_clk or rd_a_ff_inst_mdata) begin |
---|
| 171 | if (rd_local_clk) begin |
---|
| 172 | rd_a_ff[3:0] <= rd_a_ff_inst_mdata ; |
---|
| 173 | end |
---|
| 174 | end |
---|
| 175 | assign rd_a_ff_so[3:0] = rd_a_ff_scan_out[3:0] ; |
---|
| 176 | ///////////////////////////////////////////////////// |
---|
| 177 | |
---|
| 178 | ///////////////////////////////////////////////////// |
---|
| 179 | // csn_wr Flop // |
---|
| 180 | ///////////////////////////////////////////////////// |
---|
| 181 | reg csn_wr_ff_inst_mdata ; |
---|
| 182 | wire csn_wr_ff_inst_smin ; |
---|
| 183 | |
---|
| 184 | assign csn_wr_ff_inst_smin = hold ? csn_wr_ff : csn_wr_ff_si ; |
---|
| 185 | always @(wr_smclk or wr_local_clk or csn_wr or csn_wr_ff_inst_smin ) begin |
---|
| 186 | if (!wr_local_clk) begin |
---|
| 187 | csn_wr_ff_inst_mdata = csn_wr ; |
---|
| 188 | end |
---|
| 189 | if (!wr_smclk) begin |
---|
| 190 | csn_wr_ff_inst_mdata = csn_wr_ff_inst_smin; |
---|
| 191 | end |
---|
| 192 | end |
---|
| 193 | always @(posedge wr_ssclk) begin |
---|
| 194 | csn_wr_ff <= csn_wr_ff_inst_mdata ; |
---|
| 195 | end |
---|
| 196 | assign csn_wr_ff_so = csn_wr_ff; |
---|
| 197 | ///////////////////////////////////////////////////// |
---|
| 198 | |
---|
| 199 | ///////////////////////////////////////////////////// |
---|
| 200 | // wr_a Flop // |
---|
| 201 | ///////////////////////////////////////////////////// |
---|
| 202 | reg [3:0] wr_a_ff_inst_mdata ; |
---|
| 203 | wire [3:0] wr_a_ff_inst_smin ; |
---|
| 204 | |
---|
| 205 | assign wr_a_ff_inst_smin[3:0] = hold ? wr_a_ff[3:0] : wr_a_ff_si[3:0] ; |
---|
| 206 | always @(wr_smclk or wr_local_clk or wr_a or wr_a_ff_inst_smin ) begin |
---|
| 207 | if (!wr_local_clk) begin |
---|
| 208 | wr_a_ff_inst_mdata = wr_a[3:0] ; |
---|
| 209 | end |
---|
| 210 | if (!wr_smclk) begin |
---|
| 211 | wr_a_ff_inst_mdata = wr_a_ff_inst_smin; |
---|
| 212 | end |
---|
| 213 | end |
---|
| 214 | always @(posedge wr_ssclk) begin |
---|
| 215 | wr_a_ff[3:0] <= wr_a_ff_inst_mdata ; |
---|
| 216 | end |
---|
| 217 | assign wr_a_ff_so[3:0] = wr_a_ff[3:0] ; |
---|
| 218 | ///////////////////////////////////////////////////// |
---|
| 219 | |
---|
| 220 | ///////////////////////////////////////////////////// |
---|
| 221 | // di Flop // |
---|
| 222 | ///////////////////////////////////////////////////// |
---|
| 223 | reg [64:0] di_ff_inst_mdata ; |
---|
| 224 | wire [64:0] di_ff_inst_smin ; |
---|
| 225 | |
---|
| 226 | assign di_ff_inst_smin[64:0] = hold ? di_ff[64:0] : di_ff_si[64:0] ; |
---|
| 227 | always @(wr_smclk or wr_local_clk or di or di_ff_inst_smin ) begin |
---|
| 228 | if (!wr_local_clk) begin |
---|
| 229 | di_ff_inst_mdata = di[64:0] ; |
---|
| 230 | end |
---|
| 231 | if (!wr_smclk) begin |
---|
| 232 | di_ff_inst_mdata = di_ff_inst_smin; |
---|
| 233 | end |
---|
| 234 | end |
---|
| 235 | always @(posedge wr_ssclk) begin |
---|
| 236 | di_ff[64:0] <= di_ff_inst_mdata ; |
---|
| 237 | end |
---|
| 238 | assign di_ff_so[64:0] = di_ff[64:0] ; |
---|
| 239 | ///////////////////////////////////////////////////// |
---|
| 240 | |
---|
| 241 | wire wr_enable_l = csn_wr_ff | scan_en ; |
---|
| 242 | wire rd_enable_l = csn_rd_ff | scan_en ; |
---|
| 243 | |
---|
| 244 | // wire wr_clk_qual = wr_ssclk & ~scan_en ; |
---|
| 245 | `ifdef DEFINE_0IN |
---|
| 246 | rf16x65 rf16x65 ( .rdclk(rd_ssclk), .wrclk(wr_ssclk), .radr(rd_a_ff), .wadr(wr_a_ff), .ren(!rd_enable_l), |
---|
| 247 | .we(!wr_enable_l), .wm(65'h1FFFFFFFFFFFFFFFF), .din(di_ff), .dout(array_out) ); |
---|
| 248 | `else |
---|
| 249 | always @(wr_ssclk or wr_a_ff or wr_enable_l or di_ff ) begin |
---|
| 250 | if (!wr_ssclk) begin |
---|
| 251 | if (!wr_enable_l) begin |
---|
| 252 | memarray[wr_a_ff] <= di_ff[64:0] ; |
---|
| 253 | end |
---|
| 254 | end |
---|
| 255 | end |
---|
| 256 | |
---|
| 257 | // wire rd_clk_qual = (rd_ssclk & ~scan_en) ; |
---|
| 258 | always @(rd_ssclk or rd_a_ff or rd_enable_l) begin |
---|
| 259 | if (rd_ssclk) begin |
---|
| 260 | if (rd_enable_l == 1'b0) begin |
---|
| 261 | array_out[64:0] <= memarray[rd_a_ff] ; |
---|
| 262 | end else if (rd_enable_l == 1'b1) begin |
---|
| 263 | array_out[64:0] <= 65'h1FFFFFFFFFFFFFFFF; |
---|
| 264 | end else begin |
---|
| 265 | array_out[64:0] <= 65'hXXXXXXXXXXXXXXXXX; |
---|
| 266 | end |
---|
| 267 | end |
---|
| 268 | end |
---|
| 269 | `endif |
---|
| 270 | |
---|
| 271 | // synopsys translate_off |
---|
| 272 | |
---|
| 273 | `ifdef DEFINE_0IN |
---|
| 274 | `else |
---|
| 275 | `ifdef INNO_MUXEX |
---|
| 276 | `else |
---|
| 277 | always @(csn_rd_ff or csn_wr_ff or rd_a_ff or wr_a_ff) begin |
---|
| 278 | if ((SYNC_CLOCK_CHK1 == 0) & !csn_rd_ff & !csn_wr_ff & (rd_a_ff == wr_a_ff)) begin |
---|
| 279 | array_out <= 65'hxxxxxxxxxxxxxxxxx; |
---|
| 280 | `ifdef MODELSIM |
---|
| 281 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers", rd_a_ff, wr_a_ff); |
---|
| 282 | `else |
---|
| 283 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers", rd_a_ff, wr_a_ff); |
---|
| 284 | `endif |
---|
| 285 | end |
---|
| 286 | end |
---|
| 287 | `endif |
---|
| 288 | |
---|
| 289 | /////////////////////////////////////////////////////////////// |
---|
| 290 | // Purely ERROR checking code. // |
---|
| 291 | /////////////////////////////////////////////////////////////// |
---|
| 292 | reg [3:0] rd_a_ff_del ; |
---|
| 293 | reg csn_rd_ff_del ; |
---|
| 294 | reg rd_clk_del ; |
---|
| 295 | always @(rd_local_clk) begin |
---|
| 296 | if (rd_local_clk) rd_clk_del = #300 rd_local_clk; |
---|
| 297 | else rd_clk_del = #300 rd_local_clk; |
---|
| 298 | end |
---|
| 299 | always @(posedge rd_clk_del) begin |
---|
| 300 | rd_a_ff_del <= rd_a_ff ; |
---|
| 301 | csn_rd_ff_del <= csn_rd_ff ; |
---|
| 302 | end |
---|
| 303 | `ifdef INNO_MUXEX |
---|
| 304 | `else |
---|
| 305 | 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 |
---|
| 306 | if (SYNC_CLOCK_CHK2 == 0) begin |
---|
| 307 | if (rd_clk_del & !wr_ssclk & !csn_rd_ff_del & !csn_wr_ff & (rd_a_ff_del == wr_a_ff)) begin |
---|
| 308 | `ifdef MODELSIM |
---|
| 309 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff_del, wr_a_ff); |
---|
| 310 | `else |
---|
| 311 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff_del, wr_a_ff); |
---|
| 312 | `endif |
---|
| 313 | end |
---|
| 314 | end |
---|
| 315 | end |
---|
| 316 | `endif |
---|
| 317 | reg [3:0] wr_a_ff_del ; |
---|
| 318 | reg csn_wr_ff_del ; |
---|
| 319 | reg wr_clk_del ; |
---|
| 320 | always @(wr_ssclk) begin |
---|
| 321 | if (wr_ssclk) wr_clk_del = #300 wr_ssclk; |
---|
| 322 | else wr_clk_del = #300 wr_ssclk; |
---|
| 323 | end |
---|
| 324 | always @(posedge wr_clk_del) begin |
---|
| 325 | wr_a_ff_del <= wr_a_ff ; |
---|
| 326 | csn_wr_ff_del <= csn_wr_ff ; |
---|
| 327 | end |
---|
| 328 | `ifdef INNO_MUXEX |
---|
| 329 | `else |
---|
| 330 | 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 |
---|
| 331 | if (SYNC_CLOCK_CHK3 == 0) begin |
---|
| 332 | if (rd_local_clk & !wr_clk_del & !csn_rd_ff & !csn_wr_ff_del & (rd_a_ff == wr_a_ff_del)) begin |
---|
| 333 | `ifdef MODELSIM |
---|
| 334 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff, wr_a_ff_del); |
---|
| 335 | `else |
---|
| 336 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff, wr_a_ff_del); |
---|
| 337 | `endif |
---|
| 338 | end |
---|
| 339 | end |
---|
| 340 | end |
---|
| 341 | `endif |
---|
| 342 | `endif |
---|
| 343 | /////////////////////////////////////////////////////////////// |
---|
| 344 | // end the ERROR checking code. // |
---|
| 345 | /////////////////////////////////////////////////////////////// |
---|
| 346 | /////////////////////////////////////// |
---|
| 347 | |
---|
| 348 | // synopsys translate_on |
---|
| 349 | |
---|
| 350 | |
---|
| 351 | /////////////////////////////////// |
---|
| 352 | // Transparent latch with reset |
---|
| 353 | /////////////////////////////////// |
---|
| 354 | |
---|
| 355 | always @(array_out or rd_ssclk) begin |
---|
| 356 | if (rd_ssclk) begin |
---|
| 357 | array_out_latch <= array_out ; |
---|
| 358 | end |
---|
| 359 | end |
---|
| 360 | |
---|
| 361 | always @(di_ff_so[0] or wr_ssclk) begin |
---|
| 362 | if (!wr_ssclk) begin |
---|
| 363 | di_ff_latch_so <= di_ff_so[0] ; |
---|
| 364 | end |
---|
| 365 | end |
---|
| 366 | |
---|
| 367 | |
---|
| 368 | assign do = testmux_sel ? di_ff : array_out_latch ; |
---|
| 369 | |
---|
| 370 | ///////////////////////////////////////////////////// |
---|
| 371 | // listen_out Flop // |
---|
| 372 | ///////////////////////////////////////////////////// |
---|
| 373 | reg [64:0] listen_out_ff_inst_mdata ; |
---|
| 374 | wire [64:0] listen_out_ff_inst_smin ; |
---|
| 375 | |
---|
| 376 | assign listen_out_ff_inst_smin[64:0] = hold ? do[64:0] : listen_out_si[64:0] ; |
---|
| 377 | always @(rd_smclk or rd_local_clk or do or listen_out_ff_inst_smin ) begin |
---|
| 378 | if (!rd_local_clk) begin |
---|
| 379 | listen_out_ff_inst_mdata = do[64:0] ; |
---|
| 380 | end |
---|
| 381 | if (!rd_smclk) begin |
---|
| 382 | listen_out_ff_inst_mdata = listen_out_ff_inst_smin; |
---|
| 383 | end |
---|
| 384 | end |
---|
| 385 | always @(posedge rd_ssclk) begin |
---|
| 386 | listen_out[64:0] <= listen_out_ff_inst_mdata ; |
---|
| 387 | end |
---|
| 388 | assign listen_out_so[64:0] = listen_out[64:0] ; |
---|
| 389 | |
---|
| 390 | // synopsys translate_off |
---|
| 391 | |
---|
| 392 | `ifdef DEFINE_0IN |
---|
| 393 | `else |
---|
| 394 | `ifdef INNO_MUXEX |
---|
| 395 | `else |
---|
| 396 | always @(posedge rd_clk) begin |
---|
| 397 | if ((MARGIN_WARNING == 0) & margin != 5'b10101) begin |
---|
| 398 | `ifdef MODELSIM |
---|
| 399 | $display ("sram_margin", "margin is not set to the default value") ; |
---|
| 400 | `else |
---|
| 401 | $error ("sram_margin", "margin is not set to the default value") ; |
---|
| 402 | `endif |
---|
| 403 | end |
---|
| 404 | end |
---|
| 405 | `endif |
---|
| 406 | `endif |
---|
| 407 | |
---|
| 408 | // synopsys translate_on |
---|
| 409 | |
---|
| 410 | endmodule |
---|