Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / mcu / amb_dram_err_inject.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: amb_dram_err_inject.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 ============================================
35module amb_dram_err_inject(
36 clk,
37 int_clk,
38 DRAM_RST_L,
39 DRAM_CS_L,
40 DRAM_BA,
41 DRAM_RAS_L,
42 DRAM_CAS_L,
43 DRAM_WE_L,
44 DRAM_DQ,
45 DRAM_DQS,
46 DRAM_CB,
47 AMB_L0_STATE,
48 CHNL_ERR_ENABLE
49 );
50
51 input clk;
52 input int_clk;
53 input DRAM_RST_L;
54 input [7:0] DRAM_CS_L;
55 input [2:0] DRAM_BA;
56 input DRAM_RAS_L;
57 input DRAM_CAS_L;
58 input DRAM_WE_L;
59 inout [63:0] DRAM_DQ;
60 inout [8:0] DRAM_DQS;
61 input [7:0] DRAM_CB;
62 input AMB_L0_STATE;
63 input CHNL_ERR_ENABLE;
64
65 parameter AUTOREF_PERIOD = 1500;
66 parameter ST_RAS = 2'b00;
67 parameter ST_CAS = 2'b01;
68 parameter ST_DATA = 2'b10;
69 parameter ST_REL = 2'b11;
70
71 integer ref_timer;
72 integer dq_dly;
73 integer stop_dq_dly;
74 reg [1:0] error_st;
75 reg inject_err_s1=0;
76 reg inject_err_s3=0;
77 reg inject_err_s3_d1;
78 reg inject_err_s3_d2;
79 reg inject_err_s3_d3;
80 reg inject_err_s3_d4;
81 reg inject_err_s3_d5;
82 reg inject_err_s3_d6;
83 reg inject_err_s3_d7;
84 reg [63:0] data;
85 reg [7:0] ecc;
86 reg [7:0] inject_enable;
87 reg addr_parity_err=0;
88 reg [2:0] cas_latency;
89 reg dram_enb_error=0;
90 reg one_bit_data_err=0;
91 reg multi_bit_data_err=0;
92 reg random_error=0;
93 reg scrub_mecc_secc_err;
94 reg scrub_secc_mecc_err;
95 reg only_one_mecc_secc_err;
96 reg only_one_secc_mecc_err;
97 reg inject_err_once=0;
98 reg multiple_err_per_burst=0;
99 reg inc_burst=0;
100 reg [7:0] burst_val;
101 wire dqs;
102
103 integer flip;
104
105`ifndef AXIS
106
107`ifdef MCUSAT
108 `include "mcu_dispmonDefines.vh"
109`else
110 `include "defines.vh"
111 `include "dispmonDefines.vh"
112`endif
113
114initial
115begin
116
117
118@(posedge DRAM_RST_L);
119
120 ref_timer = 0;
121 error_st = ST_RAS;
122 dq_dly = 0;
123 inject_err_s3_d1 = 1'b0;
124 inject_err_s3_d2 = 1'b0;
125 inject_err_s3_d3 = 1'b0;
126 inject_err_s3_d4 = 1'b0;
127 inject_err_s3_d5 = 1'b0;
128 inject_err_s3_d6 = 1'b0;
129 inject_err_s3_d7 = 1'b0;
130 data = 64'h0;
131 ecc = 8'h0;
132 flip=0;
133 burst_val = 8'h0;
134
135 if ($test$plusargs("INJECT_ERR_ONCE"))
136 inject_err_once = 1;
137
138 if ($test$plusargs("MULTIPLE_ERROR_PER_BURST"))
139 begin
140 multiple_err_per_burst = 1;
141 if ($test$plusargs("INC_BURST")) //increment the subsequent burst
142 inc_burst = 1;
143
144 if ($value$plusargs("BURST_VAL=%d",burst_val))
145 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: BURST_VAL can be anything between 0 and 255 for SNG channel, or between 0 and 15 for dual channel - currently, user has specified %d",burst_val);
146 end
147
148 inject_enable = burst_val;
149
150 if ($test$plusargs("ADDR_PARITY_ERR"))
151 addr_parity_err = 1;
152
153 if (! $value$plusargs("force_cas_latency=%d", cas_latency))
154 cas_latency = 3 ;
155
156 if (CHNL_ERR_ENABLE)
157 dram_enb_error = 1;
158 else
159 dram_enb_error = 0;
160
161 if ($test$plusargs("1BIT_DATA_ERROR")) begin
162 one_bit_data_err = 1'b1;
163 flip=1;
164 end
165 else if ($test$plusargs("MULTI_BIT_DATA_ERROR")) begin
166 multi_bit_data_err = 1'b1;
167 flip=1;
168 end
169 else if ($test$plusargs("RANDOM_ERROR")) begin
170 random_error = 1;
171 flip=1;
172 end
173
174
175 if ($test$plusargs("ONLY_ONE_MECC_SECC")) begin
176 only_one_mecc_secc_err = 1'b1;
177 one_bit_data_err = 1'b0;
178 multi_bit_data_err = 1'b1;
179 end
180 else if ($test$plusargs("ONLY_ONE_SECC_MECC")) begin
181 only_one_secc_mecc_err = 1'b1;
182 one_bit_data_err = 1'b1;
183 multi_bit_data_err = 1'b0;
184 end
185 else if ($test$plusargs("SCRUB_MECC_SECC_ERROR")) begin
186 scrub_mecc_secc_err = 1'b1;
187 one_bit_data_err = 1'b0;
188 multi_bit_data_err = 1'b1;
189 end
190 else if ($test$plusargs("SCRUB_SECC_MECC_ERROR")) begin
191 scrub_secc_mecc_err = 1'b1;
192 one_bit_data_err = 1'b1;
193 multi_bit_data_err = 1'b0;
194 end
195
196if ( $test$plusargs("FLIP1") && (one_bit_data_err || multi_bit_data_err ) )
197 begin
198 flip=1;
199 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: will FLIP 1 bit in nibble!");
200 end
201else if ( $test$plusargs("FLIP2") && (one_bit_data_err || multi_bit_data_err ) )
202 begin
203 flip=2;
204 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: will FLIP 2 bits in nibble!");
205 end
206else if ( $test$plusargs("FLIP3") && (one_bit_data_err || multi_bit_data_err ) )
207 begin
208 flip=3;
209 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: will FLIP 3 bits in nibble!");
210 end
211else if ( $test$plusargs("FLIP4") && (one_bit_data_err || multi_bit_data_err ) )
212 begin
213 flip=4;
214 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: will FLIP 4 bits in nibble!");
215 end
216else if ( $test$plusargs("RANDOM_FLIP") && (one_bit_data_err || multi_bit_data_err ) )
217 begin
218 flip=({$random}%4)+1;
219 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: will randomly FLIP 1/2/3/4 bits in nibble!");
220 end
221
222end
223
224always @(clk)
225begin
226 if (!DRAM_RST_L && dram_enb_error && AMB_L0_STATE)
227 begin
228 case (error_st)
229 ST_RAS: begin
230 if ( !DRAM_RAS_L && DRAM_CAS_L && DRAM_WE_L && !DRAM_CS_L[0] ) begin
231 error_st <= ST_CAS;
232 end
233 end
234 ST_CAS: begin
235 if ( DRAM_RAS_L && !DRAM_CAS_L && DRAM_WE_L && !DRAM_CS_L[0] ) begin
236 error_st <= ST_DATA;
237 end
238 end
239 ST_DATA: begin
240
241 case(cas_latency)
242 3: stop_dq_dly = 3;
243 4: stop_dq_dly = 4;
244 5: stop_dq_dly = 6;
245 6: stop_dq_dly = 8;
246 7: stop_dq_dly = 10;
247 default: stop_dq_dly = cas_latency-1;
248 endcase
249
250 `ifndef SUN_AMB
251 if (dq_dly == ((stop_dq_dly+3)*2) - 2) begin
252 `else
253 if (dq_dly == ((stop_dq_dly+3)*2) - 1) begin
254 `endif
255 inject_err_s1 <= 1;
256 dq_dly <= 0;
257 error_st <= ST_REL;
258 end
259 else dq_dly <= dq_dly + 1;
260 end
261 ST_REL: begin
262 inject_err_s1 <= 0;
263 error_st <= ST_RAS;
264 end
265 default: begin
266 `PR_ERROR ("amb_dram_err_injector", `ERROR, "Err injector entered unknown state\n");
267 error_st <= ST_RAS;
268 end
269 endcase
270 end
271end
272
273assign dqs = |DRAM_DQS;
274reg [7:0] burst_cntr;
275
276initial burst_cntr = 1;
277integer i;
278reg passed_bootEnd_mask=0;
279
280always @ (posedge inject_err_s1)
281begin
282
283 if(multiple_err_per_burst)
284 // means inject on multiple quad words ; select from 8 in single channel, or 4 in dual channel
285 begin
286 if (!$test$plusargs("SNG_CHANNEL")) // i.e. which means dual channel, burst length is 4
287 begin
288 if(inc_burst) begin
289 inject_enable = (burst_val + burst_cntr) % 16;
290 burst_cntr = burst_cntr + 1;
291 end
292 else if(!(burst_val == 8'h0)) begin
293 inject_enable = burst_val;
294 end
295 else begin
296 inject_enable[2:0] = ({$random(`PARGS.seed)} % 8);
297 inject_enable[3] = 1'b1;
298 inject_enable[7:4] = 4'b0;
299 end
300 end
301 else // single channel i.e. burst length is 8
302 begin
303 if(inc_burst) begin
304 inject_enable = (burst_val + burst_cntr) % 256;
305 burst_cntr = burst_cntr + 1;
306 end
307 else if(!(burst_val == 8'h0)) begin
308 inject_enable = burst_val;
309 end
310 else begin
311 inject_enable[1:0] = ({$random(`PARGS.seed)} % 3);
312 inject_enable[3:2] = ({$random(`PARGS.seed)} % 3);
313 inject_enable[5:4] = ({$random(`PARGS.seed)} % 3);
314 inject_enable[7:6] = ({$random(`PARGS.seed)} % 3);
315 end
316 end
317 end
318 else // if(!multiple_err_per_burst)
319 begin
320 if (!$test$plusargs("SNG_CHANNEL")) // i.e. which means dual channel
321 begin
322 inject_enable = 1 << ({$random(`PARGS.seed)} % 4); //pick any 1 of 4
323 end
324 else // single channel
325 begin
326 inject_enable = 1 << ({$random(`PARGS.seed)} % 8); //pick any 1 of 8
327 end
328 end
329
330
331 if(($test$plusargs("INJECT_ERR_ONCE")) && !inject_err_once)
332 inject_enable = 8'b0;
333
334`ifndef MCUSAT // only for fullchip
335`ifndef PLAYBACK
336 if ( !(`TOP.gOutOfBoot[63:0] === `TOP.verif_args.finish_mask[63:0]) )
337 inject_enable = 8'b0; // set it to 0 if you are still inside bootcode
338 else if (!passed_bootEnd_mask && (`TOP.gOutOfBoot[63:0] === `TOP.verif_args.finish_mask[63:0]) ) begin
339 repeat (1000) @ (posedge clk); // wait until 1000 cycles after bootcode ends, then start injecting...
340 passed_bootEnd_mask=1;
341 end
342`endif // PLAYBACK
343`endif
344
345
346 @(posedge dqs);
347 inject_err_s3 = inject_enable[0];
348 inject_enable[0] = 1'b0;
349
350 @(negedge dqs);
351 inject_err_s3_d1 = inject_enable[1];
352 inject_enable[1] = 1'b0;
353 inject_err_s3 = 1'b0;
354
355 @(posedge dqs);
356 inject_err_s3_d2 = inject_enable[2];
357 inject_enable[2] = 1'b0;
358 inject_err_s3_d1 = 1'b0;
359
360 @(negedge dqs);
361 inject_err_s3_d3 = inject_enable[3];
362 inject_enable[3] = 1'b0;
363 inject_err_s3_d2 = 1'b0;
364
365 `ifdef SNG_CHANNEL
366 @(posedge dqs);
367 inject_err_s3_d4 = inject_enable[4];
368 inject_enable[4] = 1'b0;
369 inject_err_s3_d3 = 1'b0;
370
371 @(negedge dqs);
372 inject_err_s3_d5 = inject_enable[5];
373 inject_enable[5] = 1'b0;
374 inject_err_s3_d4 = 1'b0;
375
376 @(posedge dqs);
377 inject_err_s3_d6 = inject_enable[6];
378 inject_enable[6] = 1'b0;
379 inject_err_s3_d5 = 1'b0;
380
381 @(negedge dqs);
382 inject_err_s3_d7 = inject_enable[7];
383 inject_enable[7] = 1'b0;
384 inject_err_s3_d6 = 1'b0;
385
386 @(posedge clk);
387 @(posedge clk);
388 inject_err_s3_d7 = 1'b0;
389
390 `else
391 @(posedge clk);
392 @(posedge clk);
393 inject_err_s3_d3 = 1'b0;
394 `endif
395
396end
397
398`ifdef MCU_GATE
399wire mcu0_esr_dac = `MCU0.rdpctl_err_sts_reg[23];
400wire mcu1_esr_dac = `MCU1.rdpctl_err_sts_reg[23];
401wire mcu2_esr_dac = `MCU2.rdpctl_err_sts_reg[23];
402wire mcu3_esr_dac = `MCU3.rdpctl_err_sts_reg[23];
403
404wire mcu0_esr_dau = `MCU0.rdpctl_err_sts_reg[22];
405wire mcu1_esr_dau = `MCU1.rdpctl_err_sts_reg[22];
406wire mcu2_esr_dau = `MCU2.rdpctl_err_sts_reg[22];
407wire mcu3_esr_dau = `MCU3.rdpctl_err_sts_reg[22];
408`else
409wire mcu0_esr_dac = `MCU0.drif.rdpctl_err_sts_reg[23];
410wire mcu1_esr_dac = `MCU1.drif.rdpctl_err_sts_reg[23];
411wire mcu2_esr_dac = `MCU2.drif.rdpctl_err_sts_reg[23];
412wire mcu3_esr_dac = `MCU3.drif.rdpctl_err_sts_reg[23];
413
414wire mcu0_esr_dau = `MCU0.drif.rdpctl_err_sts_reg[22];
415wire mcu1_esr_dau = `MCU1.drif.rdpctl_err_sts_reg[22];
416wire mcu2_esr_dau = `MCU2.drif.rdpctl_err_sts_reg[22];
417wire mcu3_esr_dau = `MCU3.drif.rdpctl_err_sts_reg[22];
418`endif
419
420
421
422
423reg [63:0] nibble_err_position1;
424reg [63:0] nibble_err_position2;
425reg [31:0] random;
426reg[63:0]tmp;
427
428
429time stop_ecc_inj_time=0; time restart_ecc_inj_time=0; time restart_stop_ecc_inj_time=0;
430reg stop_mask=0; reg restart_mask=0; reg restart_stop_mask=0;
431
432initial
433begin
434if($value$plusargs("STOP_ECC_INJ_TIME=%d",stop_ecc_inj_time))
435 `PR_ALWAYS("amb_dram_err_injector", `ALWAYS, "*** Parameter \"STOP_ECC_INJ_TIME\" has been set to %d",stop_ecc_inj_time);
436end
437initial
438begin
439if($value$plusargs("RESTART_ECC_INJ_TIME=%d",restart_ecc_inj_time))
440 `PR_ALWAYS("amb_dram_err_injector", `ALWAYS, "*** Parameter \"RESTART_ECC_INJ_TIME\" has been set to %d",restart_ecc_inj_time);
441end
442initial
443begin
444if($value$plusargs("RESTART_STOP_ECC_INJ_TIME=%d",restart_stop_ecc_inj_time))
445 `PR_ALWAYS("amb_dram_err_injector", `ALWAYS, "*** Parameter \"RESTART_STOP_ECC_INJ_TIME\" has been set to %d",restart_stop_ecc_inj_time);
446end
447
448
449`ifndef MCUSAT // only for fullchip
450integer delay_ecc;
451initial begin
452 if (!$value$plusargs("DELAY_ECC=%d",delay_ecc)) delay_ecc=10;
453end
454integer counter_delay_ecc; initial counter_delay_ecc=0;
455`endif
456
457
458reg [63:0] corrupted_data;
459integer ce_count; initial ce_count=0;
460integer ue_count; initial ue_count=0;
461
462
463always @ ( posedge inject_err_s3 or
464 posedge inject_err_s3_d1 or
465 posedge inject_err_s3_d2 or
466 posedge inject_err_s3_d3 or
467 posedge inject_err_s3_d4 or
468 posedge inject_err_s3_d5 or
469 posedge inject_err_s3_d6 or
470 posedge inject_err_s3_d7
471 ) begin
472
473 data = DRAM_DQ;
474 ecc = DRAM_CB;
475 inject_err_once=0;
476
477//random 1-bit or multi-bit
478 if(random_error) begin
479 random={$random}%2;
480 if(random[0]) begin
481 one_bit_data_err = 1'b1;
482 multi_bit_data_err = 1'b0;
483 end
484 else if(!random[0]) begin
485 one_bit_data_err = 1'b0;
486 multi_bit_data_err = 1'b1;
487 end
488 end
489
490
491 if ( !stop_mask && !($time < stop_ecc_inj_time) && !(stop_ecc_inj_time == 0) )
492 begin
493 `PR_ALWAYS("amb_dram_err_injector", `ALWAYS, "INFO: *** Stopping ecc err injection, time now is %d",$time);
494 force one_bit_data_err = 0; force multi_bit_data_err = 0;
495 stop_mask = 1;
496 end
497 else if ( !restart_mask && !($time < restart_ecc_inj_time) && !(restart_ecc_inj_time == 0) && (restart_ecc_inj_time > stop_ecc_inj_time) )
498 begin
499 `PR_ALWAYS("amb_dram_err_injector", `ALWAYS, "INFO: *** Restarting ecc err injection, time now is %d",$time);
500 release one_bit_data_err; release multi_bit_data_err;
501 restart_mask=1;
502 end
503 else if ( !restart_stop_mask && !($time < restart_stop_ecc_inj_time) && !(restart_stop_ecc_inj_time == 0) && (restart_stop_ecc_inj_time > restart_ecc_inj_time) )
504 begin
505 `PR_ALWAYS("amb_dram_err_injector", `ALWAYS, "INFO: *** Stopping the restarted ecc err injection, time now is %d",$time);
506 force one_bit_data_err = 0; force multi_bit_data_err = 0;
507 restart_stop_mask=1;
508 end
509
510
511`ifndef MCUSAT
512 counter_delay_ecc = counter_delay_ecc+1;
513 if ( (!mcu0_esr_dau && !mcu1_esr_dau && !mcu2_esr_dau && !mcu3_esr_dau) &&
514 (!mcu0_esr_dac && !mcu1_esr_dac && !mcu2_esr_dac && !mcu3_esr_dac) &&
515 (counter_delay_ecc % delay_ecc == 0) ) begin
516`endif
517 if (one_bit_data_err) ce_count=ce_count+1;
518 else if (multi_bit_data_err) ue_count=ue_count+1;
519 corrupted_data = error_inject(data, one_bit_data_err, multi_bit_data_err,flip,ce_count,ue_count);
520 #1 force DRAM_DQ = corrupted_data;
521`ifndef MCUSAT
522 end
523`endif
524
525 if (addr_parity_err) begin
526 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: Address parity inversion : Injecting err by inverting ecc %x,%x\n", ecc,data[63:56]);
527 force DRAM_CB = ~ecc;
528 force DRAM_DQ[63:56] = ~data[63:56];
529 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: Erred ecc is %x,%x", ~ecc, ~data[63:56]);
530 end
531
532 if(scrub_secc_mecc_err && one_bit_data_err) begin
533 multi_bit_data_err = 1'b1;
534 one_bit_data_err = 1'b0;
535 end
536 else if(scrub_secc_mecc_err && multi_bit_data_err) begin
537 multi_bit_data_err = 1'b0;
538 one_bit_data_err = 1'b0;
539 end
540 else if(scrub_secc_mecc_err && !one_bit_data_err && !multi_bit_data_err)
541 one_bit_data_err = 1'b1;
542
543 if(scrub_mecc_secc_err && multi_bit_data_err) begin
544 multi_bit_data_err = 1'b0;
545 one_bit_data_err = 1'b1;
546 end
547 else if(scrub_mecc_secc_err && one_bit_data_err) begin
548 multi_bit_data_err = 1'b0;
549 one_bit_data_err = 1'b0;
550 end
551 else if(scrub_mecc_secc_err && !multi_bit_data_err && !one_bit_data_err)
552 multi_bit_data_err = 1'b1;
553
554 if(only_one_mecc_secc_err && multi_bit_data_err) begin
555 multi_bit_data_err = 1'b0;
556 one_bit_data_err = 1'b1;
557 end
558 else if(only_one_mecc_secc_err && one_bit_data_err) begin
559 multi_bit_data_err = 1'b0;
560 one_bit_data_err = 1'b0;
561 only_one_mecc_secc_err = 1'b0;
562 end
563
564 if(only_one_secc_mecc_err && one_bit_data_err) begin
565 multi_bit_data_err = 1'b1;
566 one_bit_data_err = 1'b0;
567 end
568 else if(only_one_secc_mecc_err && multi_bit_data_err) begin
569 multi_bit_data_err = 1'b0;
570 one_bit_data_err = 1'b0;
571 only_one_secc_mecc_err = 1'b0;
572 end
573
574end
575
576
577always @ ( clk ) begin
578 #1000 release DRAM_DQ;
579 release DRAM_CB;
580end
581
582
583function [63:0] error_inject;
584input [63:0] data;
585input one_bit_data_err;
586input multi_bit_data_err;
587input [31:0] flip;
588input [31:0] ce_count;
589input [31:0] ue_count;
590reg [3:0] nibble_err_position1;
591reg [3:0] nibble_err_position2;
592reg [63:0]tmp_data;
593reg [3:0] cf_out;
594
595begin
596
597 if (one_bit_data_err)
598 begin
599 nibble_err_position1 = {$random}%16;
600
601 cf_out=calc_flipbits(flip);
602 tmp_data=(cf_out << (4*nibble_err_position1));
603 error_inject = data ^ tmp_data;
604 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: Injected CE error no. %d (nibble # is %d, %d bits/nibble flipped, nibble config is %4b) --> orig. data was %x, modif. data is %x",ce_count, nibble_err_position1,flip,cf_out,data,error_inject);
605 end
606
607 else if(multi_bit_data_err) begin
608 nibble_err_position1 = {$random}%16;
609 nibble_err_position2 = {$random}%16;
610 while (nibble_err_position2 == nibble_err_position1)
611 nibble_err_position2 = {$random}%16;
612
613 cf_out = calc_flipbits(flip);
614 tmp_data=(cf_out << (4*nibble_err_position1));
615 tmp_data=tmp_data | (cf_out << (4*nibble_err_position2));
616 error_inject = data ^ tmp_data;
617 `PR_ALWAYS ("amb_dram_err_injector", `ALWAYS, "INFO: Injected UE error no. %d (nibble #s are %d and %d, %d bits/nibble flipped, nibble config is %4b) --> orig. data was %x, modif. data is %x",ue_count, nibble_err_position1,nibble_err_position2,flip,cf_out,data,error_inject);
618 end
619
620end
621endfunction
622
623
624function [3:0] calc_flipbits;
625input [31:0] flip;
626begin
627 case (flip)
628 1: begin
629 i=({$random}%4)+1;
630 case (i)
631 1: calc_flipbits=4'b0001;
632 2: calc_flipbits=4'b0010;
633 3: calc_flipbits=4'b0100;
634 4: calc_flipbits=4'b1000;
635 default: calc_flipbits=4'b0001;
636 endcase
637 end
638 2: begin
639 i=({$random}%6)+1;
640 case (i)
641 1: calc_flipbits=4'b0011;
642 2: calc_flipbits=4'b0101;
643 3: calc_flipbits=4'b1001;
644 4: calc_flipbits=4'b0110;
645 5: calc_flipbits=4'b1010;
646 6: calc_flipbits=4'b1100;
647 default: calc_flipbits=4'b0011;
648 endcase
649 end
650 3: begin
651 i=({$random}%4)+1;
652 case (i)
653 1: calc_flipbits=4'b0111;
654 2: calc_flipbits=4'b1011;
655 3: calc_flipbits=4'b1101;
656 4: calc_flipbits=4'b1110;
657 default: calc_flipbits=4'b0111;
658 endcase
659 end
660 4: calc_flipbits=4'b1111;
661 endcase
662end
663endfunction
664
665`endif
666endmodule