// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: amb_dram_err_inject.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
module amb_dram_err_inject(
//input [5:0] DRAM_FAIL_PART;
parameter AUTOREF_PERIOD = 1500;
parameter ST_RAS = 2'b00;
parameter ST_CAS = 2'b01;
parameter ST_DATA = 2'b10;
parameter ST_REL = 2'b11;
reg [3:0] err_bits,err_bits1;
reg disable_mecc, disable_secc;
wire synd_ecc_err_inject;
wire [3:0] synd_err_bits;
wire [31:0] synd_err_pos1;
// dbg signals for error_mon
reg dbg_mecc_err_injected;
reg dbg_secc_err_injected;
if ($test$plusargs("INJECT_ERR_ONCE"))
if ($test$plusargs("ADDR_PARITY_ERR"))
if ($test$plusargs("ENB_MECC_ERROR"))
if (! $value$plusargs("force_cas_latency=%d", cas_latency))
if ($test$plusargs("1BIT_DATA_ERROR"))
if ($test$plusargs("MULTI_BIT_DATA_ERROR"))
multi_bit_data_err = 1'b1;
if ($test$plusargs("SCRUB_MECC_SECC_ERROR")) begin
scrub_mecc_secc_err = 1'b1;
multi_bit_data_err = 1'b1;
if ($test$plusargs("ONLY_ONE_MECC_SECC")) begin
multi_bit_data_err = 1'b1;
if ($test$plusargs("ONLY_ONE_SECC_MECC")) begin
multi_bit_data_err = 1'b0;
if ($test$plusargs("RANDOM_ERROR")) begin
multi_bit_data_err = 1'b0;
if(!$value$plusargs("BOOT_CODE_FINISH=%d",bcode_finish))
dbg_mecc_err_injected <= 1'b0;
dbg_secc_err_injected <= 1'b0;
if (!DRAM_RST_L && dram_enb_error && AMB_L0_STATE)
//$display ("%0d %m: Err injector state ST_RAS\n", $time);
dbg_secc_err_injected <= 1'b0;
dbg_mecc_err_injected <= 1'b0;
if ( !DRAM_RAS_L && DRAM_CAS_L && DRAM_WE_L && !DRAM_CS_L[0] )
//$display ("%0d %m: Err injector state ST_CAS\n", $time);
if ( DRAM_RAS_L && !DRAM_CAS_L && DRAM_WE_L && !DRAM_CS_L[0] )
//$display ("%0d %m: Err injector state ST_DATA\n", $time);
default: stop_dq_dly = cas_latency-1;
if (dq_dly == ((stop_dq_dly+3)*2) - 2) begin
if (dq_dly == ((stop_dq_dly+3)*2) - 1) begin
else dq_dly <= dq_dly + 1;
//$display ("%0d %m: Err injector state ST_REL\n", $time);
$display ("%0d %m: Err injector entered unknown state\n", $time);
inject_err_s1_1 <= inject_err_s1;
inject_err_s1_2 <= inject_err_s1_1;
inject_err_s1_3 <= inject_err_s1_2;
inject_err_s1_4 <= inject_err_s1_3;
inject_err_s1_5 <= inject_err_s1_4;
always @ (posedge inject_err_s1)
err_burst1 = ($random() % 4);
inject_enable = 1'b1 << err_burst1;
if ($test$plusargs("TWO_ERROR_PER_BURST")) begin
err_burst2 = ($random() % 4);
if(err_burst2 != err_burst1)
inject_enable = inject_enable | (1'b1 << err_burst2);
inject_enable = inject_enable | (1'b1 << (err_burst2 + 1));
else if($test$plusargs("RANDOM_ERROR_PER_BURST"))
inject_enable = ($random() & 4'hf);
if(($test$plusargs("INJECT_ERR_ONCE")) && !inject_err_once)
inject_err_s3 = inject_enable[0];
inject_err_s3_d1 = inject_enable[1];
inject_err_s3_d2 = inject_enable[2];
inject_err_s3_d3 = inject_enable[3];
inject_err_s3 = inject_enable[0];
inject_err_s3_d2 = inject_enable[2];
inject_err_s3_d1 = inject_enable[1];
inject_err_s3_d3 = inject_enable[3];
inject_err_s2 <= inject_err_s1;
inject_err_s2_d1 <= inject_err_s1_1;
inject_err_s2_d2 <= inject_err_s1_2;
inject_err_s2_d3 <= inject_err_s1_3;
always @ (posedge inject_err_s2 or
posedge inject_err_s2_d1 or
posedge inject_err_s2_d2 or
posedge inject_err_s2_d3 )
inject_enable = #10 $random() & 4'hf;
if ($test$plusargs("ONE_ERROR_PER_BURST"))
else if ($test$plusargs("TWO_ERROR_PER_BURST"))
if(($test$plusargs("INJECT_ERR_ONCE")) && !inject_err_once)
inject_err_s3 <= (inject_enable[0] && inject_err_s2);
inject_err_s3_d1 <= (inject_enable[1] && inject_err_s2_d1);
inject_err_s3_d2 <= (inject_enable[2] && inject_err_s2_d2);
inject_err_s3_d3 <= (inject_enable[3] && inject_err_s2_d3);
always @ (negedge inject_err_s2)
always @ (negedge inject_err_s2_d1)
always @ (negedge inject_err_s2_d2)
always @ (negedge inject_err_s2_d3)
always @ (posedge inject_err_s3_d3)
flip_for_mecc = !flip_for_mecc;
reg [63:0] err_position1;
always @ (posedge inject_err_s3 or
posedge inject_err_s3_d1 or
posedge inject_err_s3_d2 or
posedge inject_err_s3_d3)
err_position = ($random % 63);
err_position1 = ($random % 63);
if(random_error == 1'b1) begin
err_type = ($random % 3);
if(err_type == 2'b0) begin
multi_bit_data_err = 1'b0;
else if(err_type == 2'b01) begin
multi_bit_data_err = 1'b0;
else if(err_type == 2'b10) begin
multi_bit_data_err = 1'b1;
if (one_bit_data_err) begin
$display ("%0d: Injecting 1 Bit error on data %x at bit %d\n", $time, data, err_position);
tmp = 64'b1 << err_position;
force DRAM_DQ = data ^ tmp;
dbg_secc_err_injected <= 1'b1;
$display ("%0d: Erred data is %x at bit %d\n", $time, (data ^ tmp), err_position);
end else if(multi_bit_data_err) begin
if((err_position / 4) == (err_position1 / 4)) begin
err_position1 = err_position1 + 4;
err_position1 = (err_position1 % 64);
$display ("%0d: Injecting Multi-bit error on data %x at bits %d and %d\n", $time, data, err_position, err_position1);
tmp = 64'b1 << err_position;
tmp = (tmp | (64'b1 << err_position1));
force DRAM_DQ = data ^ tmp;
dbg_mecc_err_injected <= 1'b1;
$display ("%0d: Erred data is %x, tmp = %x\n", $time, (data ^ tmp), tmp);
if (addr_parity_err) begin
$display ("%0d: Address parity inversion : Injecting error by inverting ecc %x \n", $time, ecc);
$display ("%0d: Erred ecc is %x\n", $time, ~ecc);
if(scrub_mecc_secc_err && multi_bit_data_err) begin
multi_bit_data_err = 1'b0;
else if(scrub_mecc_secc_err && one_bit_data_err) begin
multi_bit_data_err = 1'b0;
else if(scrub_mecc_secc_err)
multi_bit_data_err = 1'b1;
if(mecc_secc_err && multi_bit_data_err) begin
multi_bit_data_err = 1'b0;
else if(mecc_secc_err && one_bit_data_err) begin
multi_bit_data_err = 1'b0;
if(secc_mecc_err && one_bit_data_err) begin
multi_bit_data_err = 1'b1;
else if(secc_mecc_err && multi_bit_data_err) begin
multi_bit_data_err = 1'b0;
/* OLD N1 CODE; COMMENTED OUT BECAUSE IT DOESN'T WORK WELL WITH N2 -ncr
err_bits = $random() & 4'hf;
err_bits1 = $random() & 4'hf;
// If injecting error in each nibble
if ($test$plusargs("EACH_NIBBLE_ERROR")) begin
ecc_err_inject = (err_pos == 0) ? !ecc_err_inject : ecc_err_inject;
err_pos = (err_pos == 60) ? 0 : (((err_pos >> 2) + 1)*4);
err_pos1 = (err_pos1 == 60) ? 0 : (err_pos == 60) ? (((err_pos1 >> 2) + 1)*4) : err_pos1;
ecc_err_inject = $random() & 1'b1;
err_pos = ($random() & 5'h1f) * 4;
err_pos1 = ($random() & 5'h1f) * 4;
// *** Commented out for now ********
// if (dram_enb_error && DRAM_FAIL_OVER) begin
// force DRAM_DQ = data ^ ((err_bits << err_pos) | (4'hf << (DRAM_FAIL_PART * 4)));
// $display ("%0d: Injecting Err on data %x at bit %d\n", $time, data, err_pos);
// *****************************************
if (dram_enb_error) begin
if ($test$plusargs("ONLY_ONE_MECC_SECC")) begin
if (addr_parity_err && !disable_mecc) begin
$display ("%0d: Address parity inversion : Injecting Err by inverting ecc %x \n", $time, ecc);
force DRAM_DQ = data ^ (err_bits << err_pos);
$display ("%0d: Injecting Err on data %x at bit %d\n", $time, data, err_pos);
if ($test$plusargs("ONLY_ONE_SECC_MECC")) begin
force DRAM_DQ = data ^ (err_bits << err_pos);
$display ("%0d: Injecting Err on data %x at bit %d\n", $time, data, err_pos);
if (addr_parity_err && !disable_mecc) begin
$display ("%0d: Address parity inversion : Injecting Err by inverting ecc %x \n", $time, ecc);
if ($test$plusargs("SYNDROME_TEST")) begin
synd_err_pos = (synd_err_pos1 & 5'h1f) * 4;
if(!synd_ecc_err_inject) begin // this is a random number so inject data or ecc errors randomly
force DRAM_DQ = data ^ (synd_err_bits << synd_err_pos);
$display ("%0d: Injecting Err on data %x at bit %d\n", $time, data, synd_err_pos);
$display ("%0d: Erred data %x at synd_err_pos %x with synd_err_bits %x\n", $time, DRAM_DQ, synd_err_pos,synd_err_bits);
force DRAM_CB = ecc ^ (synd_err_bits << synd_err_pos[3:0]);
$display ("%0d: Injecting Err on ecc %x at bit %d\n", $time, ecc, synd_err_pos[3:0]);
$display ("%0d: Erred ecc %x at synd_err_pos %x with synd_err_bits %x\n", $time, DRAM_CB, synd_err_pos[3:0],synd_err_bits);
// This is normal error injection
if (addr_parity_err) begin
$display ("%0d: Address parity inversion : Injecting Err by inverting ecc %x \n", $time, ecc);
if (enb_mecc_error ) begin
// MECC is multiple errors in different chunks for data
force DRAM_DQ = (data ^ (err_bits << err_pos) ^ (err_bits1 << err_pos1) );
$display ("%0d: Injecting Err on data %x at bit %d %d\n", $time, data, err_pos,err_pos1);
if(!ecc_err_inject) begin // this is a random number so inject data or ecc errors randomly
force DRAM_DQ = data ^ (err_bits << err_pos);
$display ("%0d: Injecting Err on data %x at bit %d\n", $time, data, err_pos);
$display ("%0d: Erred data %x at err_pos %x with err_bits %x\n", $time, DRAM_DQ, err_pos,err_bits);
force DRAM_CB = ecc ^ (err_bits << err_pos[3:0]);
$display ("%0d: Injecting Err on ecc %x at bit %d\n", $time, ecc, err_pos[3:0]);
$display ("%0d: Erred ecc %x at err_pos %x with err_bits %x\n", $time, DRAM_CB, err_pos[3:0],err_bits);
// *********** Comment out for now *****************
// else if (DRAM_FAIL_OVER)
// force tb_top.mcusat_fbdimm.fbdimm_mem0.fbdimm0.fbdimm_DIMMx4.dq[63:0] = data ^ (4'hf << (DRAM_FAIL_PART * 4));
// **************************************************
//always @ (negedge inject_err_s3 or negedge inject_err_s3_d1 or negedge inject_err_s3_d2 or negedge inject_err_s3_d3) begin
always @ ( DRAM_CB ) begin