Merge pull request #9 from AngeloJacobo/add_feature_ecc

Added ECC Feature
This commit is contained in:
Angelo Jacobo 2024-08-16 15:42:45 +08:00 committed by GitHub
commit 79b8b799aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 87693 additions and 289 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
formal/ddr3_multiconfig_prf*
formal/ddr3_multiconfig*prf*
formal/ecc/
formal/ddr3_singleconfig/
example_demo/nexys_video/build/

View File

@ -66,11 +66,10 @@
wire tx_full;
wire o_wb_ack;
wire[7:0] o_wb_data;
wire o_aux;
wire[7:0] rd_data;
wire o_wb_stall;
reg i_wb_stb = 0, i_wb_we;
wire[63:0] o_debug1;
wire[31:0] o_debug1;
reg[7:0] i_wb_data;
reg[7:0] i_wb_addr;
// o_debug1 taps on value of state_calibrate (can be traced inside ddr3_controller module)
@ -140,12 +139,14 @@
.COL_BITS(10), //width of column address
.BA_BITS(3), //width of bank address
.BYTE_LANES(2), //number of DDR3 modules to be controlled
.AUX_WIDTH(4), //width of aux line (must be >= 4)
.AUX_WIDTH(16), //width of aux line (must be >= 4)
.WB2_ADDR_BITS(32), //width of 2nd wishbone address bus
.WB2_DATA_BITS(32), //width of 2nd wishbone data bus
.MICRON_SIM(0), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
.ODELAY_SUPPORTED(0), //set to 1 when ODELAYE2 is supported
.SECOND_WISHBONE(0) //set to 1 if 2nd wishbone is needed
.SECOND_WISHBONE(0), //set to 1 if 2nd wishbone is needed
.ECC_ENABLE(0), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
.WB_ERROR(0) // set to 1 to support Wishbone error (asserts at ECC double bit error)
) ddr3_top
(
//clock and reset
@ -165,8 +166,9 @@
// Wishbone outputs
.o_wb_stall(o_wb_stall), //1 = busy, cannot accept requests
.o_wb_ack(o_wb_ack), //1 = read/write request has completed
.o_wb_err(), //1 = Error due to ECC double bit error (fixed to 0 if WB_ERROR = 0)
.o_wb_data(o_wb_data), //read data, for a 4:1 controller data width is 8 times the number of pins on the device
.o_aux(o_aux),
.o_aux(),
// Wishbone 2 (PHY) inputs
.i_wb2_cyc(), //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
.i_wb2_stb(), //request a transfer

View File

@ -138,12 +138,14 @@
.COL_BITS(10), //width of column address
.BA_BITS(3), //width of bank address
.BYTE_LANES(8), //number of DDR3 modules to be controlled
.AUX_WIDTH(4), //width of aux line (must be >= 4)
.AUX_WIDTH(16), //width of aux line (must be >= 4)
.WB2_ADDR_BITS(32), //width of 2nd wishbone address bus
.WB2_DATA_BITS(32), //width of 2nd wishbone data bus
.MICRON_SIM(0), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
.ODELAY_SUPPORTED(1), //set to 1 when ODELAYE2 is supported
.SECOND_WISHBONE(0) //set to 1 if 2nd wishbone is needed
.SECOND_WISHBONE(0), //set to 1 if 2nd wishbone is needed
.ECC_ENABLE(0), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
.WB_ERROR(0) // set to 1 to support Wishbone error (asserts at ECC double bit error)
) ddr3_top
(
//clock and reset

View File

@ -1,58 +0,0 @@
[tasks]
prf2lanes_83MHz prf opt_2lanes opt_83MHz opt_with_ODELAY
prf4lanes_83MHz prf opt_4lanes opt_83MHz opt_with_ODELAY
prf8lanes_83MHz prf opt_8lanes opt_83MHz opt_with_ODELAY
prf2lanes_100MHz prf opt_2lanes opt_100MHz opt_with_ODELAY
prf4lanes_100MHz prf opt_4lanes opt_100MHz opt_with_ODELAY
prf8lanes_100MHz prf opt_8lanes opt_100MHz opt_with_ODELAY
prf_no_ODELAY prf opt_8lanes opt_100MHz opt_no_ODELAY
[options]
prf: mode prove
prf: depth 7
[engines]
prf: smtbmc
[script]
read -formal ddr3_controller.v
read -formal fwb_slave.v
--pycode-begin--
cmd = "hierarchy -top ddr3_controller"
# Number of Lanes
if "opt_2lanes" in tags:
cmd += " -chparam LANES 2"
elif "opt_4lanes" in tags:
cmd += " -chparam LANES 4"
elif "opt_8lanes" in tags:
cmd += " -chparam LANES 8"
else:
cmd += " -chparam LANES 8"
# Clock period
if "opt_83MHz" in tags:
cmd += " -chparam CONTROLLER_CLK_PERIOD 12000"
cmd += " -chparam DDR3_CLK_PERIOD 3000"
elif "opt_100MHz" in tags:
cmd += " -chparam CONTROLLER_CLK_PERIOD 10000"
cmd += " -chparam DDR3_CLK_PERIOD 2500"
else:
cmd += " -chparam CONTROLLER_CLK_PERIOD 10000"
cmd += " -chparam DDR3_CLK_PERIOD 2500"
# ODELAY support
if "opt_with_ODELAY" in tags:
cmd += " -chparam ODELAY_SUPPORTED 1"
elif "opt_no_ODELAY" in tags:
cmd += " -chparam ODELAY_SUPPORTED 0"
output(cmd)
--pycode-end--
prep -top ddr3_controller
[files]
./rtl/ddr3_controller.v
./formal/fwb_slave.v

View File

@ -0,0 +1,64 @@
[tasks]
prf2lanes_83MHz prf opt_2lanes opt_83MHz opt_with_ODELAY
prf4lanes_83MHz prf opt_4lanes opt_83MHz opt_with_ODELAY
prf8lanes_83MHz prf opt_8lanes opt_83MHz opt_with_ODELAY opt_WB_ERR
prf2lanes_100MHz prf opt_2lanes opt_100MHz opt_with_ODELAY opt_WB_ERR
prf4lanes_100MHz prf opt_4lanes opt_100MHz opt_with_ODELAY
prf8lanes_100MHz prf opt_8lanes opt_100MHz opt_with_ODELAY
prf_no_ODELAY prf opt_8lanes opt_100MHz
[options]
prf: mode prove
prf: depth 7
[engines]
prf: smtbmc
[script]
read -formal ddr3_controller.v
read -formal fwb_slave.v
--pycode-begin--
# Number of Lanes
if "opt_2lanes" in tags:
cmd = "chparam -set LANES 2 ddr3_controller\n"
elif "opt_4lanes" in tags:
cmd = "chparam -set LANES 4 ddr3_controller\n"
elif "opt_8lanes" in tags:
cmd = "chparam -set LANES 8 ddr3_controller\n"
else:
cmd = "chparam -set LANES 8 ddr3_controller\n"
# Clock period
if "opt_83MHz" in tags:
cmd += "chparam -set CONTROLLER_CLK_PERIOD 12000 ddr3_controller\n"
cmd += "chparam -set DDR3_CLK_PERIOD 3000 ddr3_controller\n"
elif "opt_100MHz" in tags:
cmd += "chparam -set CONTROLLER_CLK_PERIOD 10000 ddr3_controller\n"
cmd += "chparam -set DDR3_CLK_PERIOD 2500 ddr3_controller\n"
else:
cmd += "chparam -set CONTROLLER_CLK_PERIOD 10000 ddr3_controller\n"
cmd += "chparam -set DDR3_CLK_PERIOD 2500 ddr3_controller\n"
# ODELAY support
if "opt_with_ODELAY" in tags:
cmd += "chparam -set ODELAY_SUPPORTED 1 ddr3_controller\n"
else:
cmd += "chparam -set ODELAY_SUPPORTED 0 ddr3_controller\n"
# Wishbone Error
if "opt_WB_ERR" in tags:
cmd += "chparam -set WB_ERROR 1 ddr3_controller\n"
else:
cmd += "chparam -set WB_ERROR 0 ddr3_controller\n"
output(cmd)
--pycode-end--
prep -top ddr3_controller
[files]
./rtl/ddr3_controller.v
./formal/fwb_slave.v

View File

@ -0,0 +1,83 @@
[tasks]
prf2lanes_83MHz_ECC_1 prf opt_2lanes opt_83MHz opt_with_ODELAY opt_ECC_1
prf8lanes_100MHz_ECC_1 prf opt_8lanes opt_100MHz opt_ECC_1
prf8lanes_100MHz_ECC_1_err prf opt_8lanes opt_100MHz opt_with_ODELAY opt_ECC_1 opt_WB_ERR
prf2lanes_83MHz_ECC_2_err prf opt_2lanes opt_83MHz opt_with_ODELAY opt_ECC_2 opt_WB_ERR
prf2lanes_83MHz_ECC_3 prf_ECC3 opt_2lanes opt_100MHz opt_with_ODELAY opt_ECC_3
prf8lanes_100MHz_ECC_3 prf_ECC3 opt_8lanes opt_83MHz opt_ECC_3
prf8lanes_100MHz_ECC_3_err prf_ECC3 opt_8lanes opt_100MHz opt_ECC_3 opt_WB_ERR
[options]
prf: mode prove
prf: depth 7
prf_ECC3: mode prove
prf_ECC3: depth 5
[engines]
prf: smtbmc
prf_ECC3: smtbmc
[script]
read -formal ddr3_controller.v
read -formal fwb_slave.v
read -formal ecc_dec.sv
read -formal ecc_enc.sv
--pycode-begin--
# Number of Lanes
if "opt_2lanes" in tags:
cmd = "chparam -set LANES 2 ddr3_controller\n"
elif "opt_4lanes" in tags:
cmd = "chparam -set LANES 4 ddr3_controller\n"
elif "opt_8lanes" in tags:
cmd = "chparam -set LANES 8 ddr3_controller\n"
else:
cmd = "chparam -set LANES 8 ddr3_controller\n"
# Clock period
if "opt_83MHz" in tags:
cmd += "chparam -set CONTROLLER_CLK_PERIOD 12000 ddr3_controller\n"
cmd += "chparam -set DDR3_CLK_PERIOD 3000 ddr3_controller\n"
elif "opt_100MHz" in tags:
cmd += "chparam -set CONTROLLER_CLK_PERIOD 10000 ddr3_controller\n"
cmd += "chparam -set DDR3_CLK_PERIOD 2500 ddr3_controller\n"
else:
cmd += "chparam -set CONTROLLER_CLK_PERIOD 10000 ddr3_controller\n"
cmd += "chparam -set DDR3_CLK_PERIOD 2500 ddr3_controller\n"
# ODELAY support
if "opt_with_ODELAY" in tags:
cmd += "chparam -set ODELAY_SUPPORTED 1 ddr3_controller\n"
else:
cmd += "chparam -set ODELAY_SUPPORTED 0 ddr3_controller\n"
# ECC
if "opt_ECC_3" in tags:
cmd += "chparam -set ECC_ENABLE 3 ddr3_controller\n"
elif "opt_ECC_2" in tags:
cmd += "chparam -set ECC_ENABLE 2 ddr3_controller\n"
elif "opt_ECC_1" in tags:
cmd += "chparam -set ECC_ENABLE 1 ddr3_controller\n"
else:
cmd += "chparam -set ECC_ENABLE 0 ddr3_controller\n"
# Wishbone Error
if "opt_WB_ERR" in tags:
cmd += "chparam -set WB_ERROR 1 ddr3_controller\n"
else:
cmd += "chparam -set WB_ERROR 0 ddr3_controller\n"
output(cmd)
--pycode-end--
prep -top ddr3_controller
[files]
./rtl/ddr3_controller.v
./formal/fwb_slave.v
./rtl/ecc/ecc_dec.sv
./rtl/ecc/ecc_enc.sv

View File

@ -10,8 +10,13 @@ smtbmc
[script]
read -formal ddr3_controller.v
read -formal fwb_slave.v
read -formal ecc_dec.sv
read -formal ecc_enc.sv
prep -top ddr3_controller
[files]
./rtl/ddr3_controller.v
./formal/fwb_slave.v
./rtl/ecc/ecc_dec.sv
./rtl/ecc/ecc_enc.sv

20
formal/ecc.sby Normal file
View File

@ -0,0 +1,20 @@
[options]
mode prove
depth 1
#mode cover
#depth 50
[engines]
smtbmc
[script]
read -formal ecc_formal.v
read -formal ecc_dec.sv
read -formal ecc_enc.sv
prep -top ecc_formal
[files]
./formal/ecc_formal.v
./rtl/ecc/ecc_dec.sv
./rtl/ecc/ecc_enc.sv

125
formal/ecc_formal.v Normal file
View File

@ -0,0 +1,125 @@
module ecc_formal;
parameter K = 8,
P0_LSB = 0;
// function to find number of check bits
function integer calculate_m;
input integer k;
integer m;
begin
m=1;
while (2**m < m+k+1) m=m+1;
calculate_m = m;
end
endfunction
// anyseq indicates nets that are controllable by engine
(*anyseq*)wire[K-1:0] d_i; // information input
(*anyseq*) wire[1:0] corrupted; // 0 or 3 = not corrupted bit, 1 = 1 corrupted bit, 2 = 2 corrupted bits
(*anyseq*) wire[$clog2(K+calculate_m(K))-1:0] corrupted_bit1, corrupted_bit2; // which bit will be corrupted
wire[K-1:0] q_o_dec;
wire[K+calculate_m(K):0] q_o_enc;
reg[K+calculate_m(K):0] q_o_enc_corrupted;
wire sb_err_o;
wire db_err_o;
ecc_enc #(
.K(K), //Information bit vector size
.P0_LSB(P0_LSB) //0: p0 is located at MSB
//1: p0 is located at LSB
) ecc_enc_inst (
.d_i(d_i), //information bit vector input
.q_o(q_o_enc), //encoded data word output
.p_o(), //parity vector output
.p0_o() //extended parity bit
);
ecc_dec #(
.K(K), //Information bit vector size
.LATENCY(0), //0: no latency (combinatorial design)
//1: registered outputs
//2: registered inputs+outputs
.P0_LSB(P0_LSB) //0: p0 is located at MSB
//1: p0 is located at LSB
) ecc_dec_inst (
//clock/reset ports (if LATENCY > 0)
.rst_ni(1'b1), //asynchronous reset
.clk_i(1'b0), //clock input
.clkena_i(1'b0), //clock enable input
//data ports
.d_i(q_o_enc_corrupted), //encoded code word input
.q_o(q_o_dec), //information bit vector output
.syndrome_o(), //syndrome vector output
//flags
.sb_err_o(sb_err_o), //single bit error detected
.db_err_o(db_err_o), //double bit error detected
.sb_fix_o() //repaired error in the information bits
);
`ifdef FORMAL
(*gclk*) reg f_clk = 0; // reference: https://symbiyosys.readthedocs.io/en/latest/verilog.html#global-clock
reg[9:0] f_counter = 0;
// corrupt the information based on the value of "corrupted" which is controllable by formal engine:
// 0 = no corrupted bits , 1 = 1 corrupted bit, 2 = 2 corrupted bits, 3 = no corrupted bits
always @* begin
q_o_enc_corrupted = q_o_enc;
if(corrupted == 1) begin
q_o_enc_corrupted[corrupted_bit1] = !q_o_enc_corrupted[corrupted_bit1]; //corrupt 1 random bit
assume(corrupted_bit1 != (K+calculate_m(K))); //
end
else if (corrupted == 2) begin // flip 2 bits
q_o_enc_corrupted[corrupted_bit1] = !q_o_enc_corrupted[corrupted_bit1]; //corrupt 2 random bits
q_o_enc_corrupted[corrupted_bit2] = !q_o_enc_corrupted[corrupted_bit2];
end
assume(corrupted_bit1 != corrupted_bit2); // corrupted bit should be different (in case of 2 corrupted bits)
assume(corrupted_bit1 <= (K+calculate_m(K))); // corrupted bit should be within the index of q_o_enc_corrupted
assume(corrupted_bit2 <= (K+calculate_m(K))); // corrupted bit should be within the index of q_o_enc_corrupted
end
// main contract of this design
always @* begin
// if no corrupted bits, then decoded info must be equal to original info, and error flags should be low
// OR there is 1 corrupted bit but its the MSB p0 that is corrupted
if( (corrupted == 0 || corrupted == 3) || ( (corrupted == 1) && (corrupted_bit1 == (K+calculate_m(K))) ) ) begin
assert(d_i == q_o_dec);
assert(!sb_err_o);
assert(!db_err_o);
end
// if 1 corrupted bit, then decoded info must still be equal to original info, single-bit error flag must be high, double-bit error flag must be low
else if(corrupted == 1) begin
assert(d_i == q_o_dec);
assert(sb_err_o);
assert(!db_err_o);
end
// if 2 corrupted bits, then single-bit error flag must be low, double-bit error flag must be high
else if(corrupted == 2) begin
assert(!sb_err_o);
assert(db_err_o);
end
end
// cover 10 cycles
always @(posedge f_clk) begin
f_counter <= f_counter + 1;
assume(corrupted == f_counter[1:0]); // number of corrupted bits change per clock cycle
cover((f_counter == 10));
end
// simulate random information
always @(posedge f_clk) begin
assume(d_i != $past(d_i,1));
assume(d_i != $past(d_i,2));
assume(d_i != $past(d_i,3));
assume(d_i != $past(d_i,4));
assume(d_i != $past(d_i,5));
assume(d_i != $past(d_i,6));
assume(d_i != $past(d_i,7));
assume(d_i != $past(d_i,8));
assume(d_i != $past(d_i,9));
assume(d_i != $past(d_i,10));
end
`endif
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -43,8 +43,10 @@ module ddr3_top #(
parameter[0:0] MICRON_SIM = 0, //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
ODELAY_SUPPORTED = 0, //set to 1 when ODELAYE2 is supported
SECOND_WISHBONE = 0, //set to 1 if 2nd wishbone for debugging is needed
parameter[1:0] DIC = 2'b00, //Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms)
parameter[2:0] RTT_NOM = 3'b011, //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms)
WB_ERROR = 0, // set to 1 to support Wishbone error (asserts at ECC double bit error)
parameter[1:0] ECC_ENABLE = 0, // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
parameter[1:0] DIC = 2'b00, //Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing)
parameter[2:0] RTT_NOM = 3'b011, //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms) (only change when you know what you are doing)
parameter // The next parameters act more like a localparam (since user does not have to set this manually) but was added here to simplify port declaration
DQ_BITS = 8, //device width (fixed to 8, if DDR3 is x16 then BYTE_LANES will be 2 while )
serdes_ratio = 4, // this controller is fixed as a 4:1 memory controller (CONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD = 4)
@ -71,6 +73,7 @@ module ddr3_top #(
// Wishbone outputs
output wire o_wb_stall, //1 = busy, cannot accept requests
output wire o_wb_ack, //1 = read/write request has completed
output wire o_wb_err, //1 = Error due to ECC double bit error (fixed to 0 if WB_ERROR = 0)
output wire[wb_data_bits - 1:0] o_wb_data, //read data, for a 4:1 controller data width is 8 times the number of pins on the device
output wire[AUX_WIDTH - 1:0] o_aux, //for AXI-interface compatibility (given upon strobe)
//
@ -123,8 +126,8 @@ ddr3_top #(
.MICRON_SIM(0), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
.ODELAY_SUPPORTED(0), //set to 1 if ODELAYE2 is supported
.SECOND_WISHBONE(0), //set to 1 if 2nd wishbone for debugging is needed
.WB2_ADDR_BITS(7), //width of 2nd wishbone address bus
.WB2_DATA_BITS(32) //width of 2nd wishbone data bus
.ECC_ENABLE(0), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
.WB_ERROR(0), // set to 1 to support Wishbone error (asserts at ECC double bit error)
) ddr3_top
(
//clock and reset
@ -145,6 +148,7 @@ ddr3_top #(
// Wishbone outputs
.o_wb_stall(o_wb_stall), //1 = busy, cannot accept requests
.o_wb_ack(o_wb_ack), //1 = read/write request has completed
.o_wb_err(o_wb_err), //1 = Error due to ECC double bit error (fixed to 0 if WB_ERROR = 0)
.o_wb_data(o_wb_data), //read data, for a 4:1 controller data width is 8 times the number of pins on the device
.o_aux(o_aux),
//
@ -219,6 +223,8 @@ ddr3_top #(
.MICRON_SIM(MICRON_SIM), //simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
.ODELAY_SUPPORTED(ODELAY_SUPPORTED), //set to 1 when ODELAYE2 is supported
.SECOND_WISHBONE(SECOND_WISHBONE), //set to 1 if 2nd wishbone is needed
.ECC_ENABLE(ECC_ENABLE), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
.WB_ERROR(WB_ERROR), // set to 1 to support Wishbone error (asserts at ECC double bit error)
.DIC(DIC), //Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms)
.RTT_NOM(RTT_NOM) //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms)
) ddr3_controller_inst (
@ -235,6 +241,7 @@ ddr3_top #(
// Wishbone outputs
.o_wb_stall(o_wb_stall), //1 = busy, cannot accept requests
.o_wb_ack(o_wb_ack), //1 = read/write request has completed
.o_wb_err(o_wb_err), //1 = Error due to ECC double bit error (fixed to 0 if WB_ERROR = 0)
.o_wb_data(o_wb_data), //read data, for a 4:1 controller data width is 8 times the number of pins on the device
.o_aux(o_aux), //for AXI-interface compatibility (returned upon ack)
// Wishbone 2 (PHY) inputs

317
rtl/ecc/ecc_dec.sv Normal file
View File

@ -0,0 +1,317 @@
/////////////////////////////////////////////////////////////////////
// ,------. ,--. ,--. //
// | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. //
// | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' //
// | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. //
// `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' //
// `---' //
// Error Correction and Detection Decoder //
// Parameterized Extended Hamming Code Decoder //
// //
/////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2017 ROA Logic BV //
// www.roalogic.com //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR //
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, //
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT //
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; //
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) //
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR //
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS //
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
// //
/////////////////////////////////////////////////////////////////////
// +FHDR - Semiconductor Reuse Standard File Header Section -------
// FILE NAME : ecc_dec.sv
// DEPARTMENT :
// AUTHOR : rherveille
// AUTHOR'S EMAIL :
// ------------------------------------------------------------------
// RELEASE HISTORY
// VERSION DATE AUTHOR DESCRIPTION
// 1.0 2017-04-07 rherveille initial release
// ------------------------------------------------------------------
// KEYWORDS : HAMMING ERROR CORRECTION DECODER
// ------------------------------------------------------------------
// PURPOSE : Decodes Data and ECC bits from incoming data
// Detects and corrects bit errors
// ------------------------------------------------------------------
// PARAMETERS
// PARAM NAME RANGE DESCRIPTION DEFAULT UNITS
// K 1+ Information vector size 8
// LATENCY 0,1,2 0: No latency 0
// 1: Registered outputs
// 2: Registered inputs/outputs
// P0_LSB 0,1 0: p0 located at MSB 1
// 1: p0 located at LSB
// ------------------------------------------------------------------
// REUSE ISSUES
// Reset Strategy : external asynchronous active low; rst_ni
// Clock Domains : 1, clk_i, rising edge
// Critical Timing :
// Test Features : na
// Asynchronous I/F : no
// Scan Methodology : na
// Instantiations : none
// Synthesizable (y/n) : Yes
// Other :
// -FHDR-------------------------------------------------------------
//-----------------------------------------------------------------------------
// Hamming codes can detect and correct a single bit error.
// An extended Hamming code allows detection of double bit errors and
// correction of single bit errors.
// This is called SECDED; Single Error Correction, Double Error Detection
//
// Number of bits required by a Hamming code: n = m + k
// n = code length
// m = number of check bits
// k = number of information bits
//
// Information, parity, and syndrome expressed as vectors:
// u = Information bit vector
// p = Parity check bit vector
// s = Syndrome vector
//
// The parity vector is encoded in 'n'.
// The information bit vector is part of 'p'
// The syndrome vector needs to be calculated.
//
// Bits required:
// p ranges from 0 to m+k; or p_range=m+k+1
// As a result 2^m >= m+k+1
//-----------------------------------------------------------------------------
module ecc_dec #(
parameter K = 8, //Information bit vector size
parameter LATENCY = 0, //0: no latency (combinatorial design)
//1: registered outputs
//2: registered inputs+outputs
parameter P0_LSB = 1, //0: p0 is located at MSB
//1: p0 is located at LSB
//These should be localparams
parameter m = calculate_m(K),
parameter n = m + K
)
(
/* verilator lint_off UNUSEDSIGNAL */
//clock/reset ports (if LATENCY > 0)
input rst_ni, //asynchronous reset
input clk_i, //clock input
input clkena_i, //clock enable input
/* verilator lint_on UNUSEDSIGNAL */
//data ports
input [n :0] d_i, //encoded code word input
output reg [K-1:0] q_o, //information bit vector output
output reg [m :0] syndrome_o, //syndrome vector output
//flags
output reg sb_err_o, //single bit error detected
output reg db_err_o, //double bit error detected
output reg sb_fix_o //repaired error in the information bits
);
//---------------------------------------------------------
// Functions
//---------------------------------------------------------
function integer calculate_m(input integer k);
integer m_local;
begin
m_local=1;
while (2**m_local < m_local+k+1) m_local++;
calculate_m = m_local;
end
endfunction //calculate_m
function [m:1] calculate_syndrome(input [n:0] cw);
integer p_idx, cw_idx;
begin
//clear syndrome
calculate_syndrome = 0;
for (p_idx =1; p_idx <=m; p_idx++) //parity vector index
for (cw_idx=1; cw_idx<=n; cw_idx++) //code-word index
if (|(2**(p_idx-1) & cw_idx)) calculate_syndrome[p_idx] = calculate_syndrome[p_idx] ^ cw[cw_idx];
end
endfunction //calculate_syndrome
function [n:0] correct_codeword(input [n:0] cw, input [m:1] syndrome);
/*
Correct all bits, including parity bits and extended parity bit.
This simplifies this section and keeps the logic simple.
The parity-bits are not used when extracting the information bits vector.
Dead-logic-removal gets rid of the generated logic for the parity bits.
*/
//assign code word
correct_codeword = cw;
//then invert bit indicated by syndrome
correct_codeword[syndrome] = ~correct_codeword[syndrome];
endfunction //correct_codeword
function [K-1:0] extract_q(input [n:0] cw);
integer bit_idx, cw_idx;
begin
//This function extracts the information bits vector from the codeword
//information bits are stored in non-power-of-2 locations
bit_idx=0; //information bit vector index
for (cw_idx=1; cw_idx<=n; cw_idx++) //codeword index
if (2**$clog2(cw_idx) != cw_idx)
/* verilator lint_off UNUSEDSIGNAL */
extract_q[bit_idx++] = cw[cw_idx];
/* verilator lint_on UNUSEDSIGNAL */
end
endfunction //extract_q
function is_power_of_2(input [m:1] n_local);
is_power_of_2 = (n_local & (n_local-1)) == 0;
endfunction
function information_error(input [m:1] syndrome);
begin
//This function checks if an error was detected/corrected in the information bits
information_error = |syndrome & !is_power_of_2(syndrome);
end
endfunction //information_error
//---------------------------------------------------------
// Variables
//---------------------------------------------------------
wire parity; //full codeword parity check
logic parity_reg;
wire [m :1] syndrome; //bit error indication/location
logic [m :1] syndrome_reg;
wire [n :0] cw_fixed; //corrected code word
wire [n :0] d;
logic [n :0] d_reg;
wire [K-1:0] q;
wire sb_err;
wire db_err;
wire sb_fix;
//---------------------------------------------------------
// Module Body
//---------------------------------------------------------
/*
Below diagram indicates the locations of the parity and data bits
in the final 'p' vector.
It also shows what databits each parity bit operates on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
p1 p2 d1 p4 d2 d3 d4 p8 d5 d6 d7 d8 d9 d10 d11
p1 x x x x x x x x
p2 x x x x x x x x
p4 x x x x x x x x
p8 x x x x x x x x
*/
//Step 1: Locate Parity bit
assign d = P0_LSB ? d_i : {d_i[n-1:0],d_i[n]};
//Step 2: Calculate code word parity
assign parity = ^d;
//Step 3: Calculate syndrome
assign syndrome = calculate_syndrome(d);
//Step 4: Generate intermediate registers (if any)
generate
if (LATENCY > 1)
begin : gen_inter_reg_latency_g1
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
begin
d_reg <= {n+1{1'b0}};
parity_reg <= 1'b0;
syndrome_reg <= {m{1'b0}};
end
else if (clkena_i)
begin
d_reg <= d;
parity_reg <= parity;
syndrome_reg <= syndrome;
end
end
else
begin : gen_inter_reg_latency_0
assign d_reg = d;
assign parity_reg = parity;
assign syndrome_reg = syndrome;
end
endgenerate
//Step 5: Correct erroneous bit (if any)
assign cw_fixed = correct_codeword(d_reg, syndrome_reg);
//Step 6: Extract information bits vector
assign q = extract_q(cw_fixed);
//Step 7: Generate status flags
assign sb_err = (parity_reg & |syndrome_reg);
assign db_err = ~parity_reg & |syndrome_reg;
assign sb_fix = parity_reg & |information_error(syndrome_reg);
//Step 8: Generate output registers (if required)
generate
if (LATENCY > 0)
begin : gen_output_reg_latency_g0 //Generate output registers
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
begin
q_o <= {K{1'b0}};
syndrome_o <= {m+1{1'b0}};
sb_err_o <= 1'b0;
db_err_o <= 1'b0;
sb_fix_o <= 1'b0;
end
else if (clkena_i)
begin
q_o <= q;
syndrome_o <= P0_LSB ? {syndrome_reg, parity_reg} : {parity_reg, syndrome_reg};
sb_err_o <= sb_err;
db_err_o <= db_err;
sb_fix_o <= sb_fix;
end
end
else
begin : gen_output_reg_latency_0//No output registers
always_comb
begin
q_o = q;
syndrome_o = P0_LSB ? {syndrome_reg, parity_reg} : {parity_reg, syndrome_reg};
sb_err_o = sb_err;
db_err_o = db_err;
sb_fix_o = sb_fix;
end
end
endgenerate
endmodule

219
rtl/ecc/ecc_enc.sv Normal file
View File

@ -0,0 +1,219 @@
/////////////////////////////////////////////////////////////////////
// ,------. ,--. ,--. //
// | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. //
// | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' //
// | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. //
// `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' //
// `---' //
// Error Correction and Detection Encoder //
// Parameterized Extended Hamming Code Encoder //
// //
/////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2017 ROA Logic BV //
// www.roalogic.com //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR //
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, //
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT //
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; //
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) //
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR //
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS //
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
// //
/////////////////////////////////////////////////////////////////////
// +FHDR - Semiconductor Reuse Standard File Header Section -------
// FILE NAME : ecc_enc.sv
// DEPARTMENT :
// AUTHOR : rherveille
// AUTHOR'S EMAIL :
// ------------------------------------------------------------------
// RELEASE HISTORY
// VERSION DATE AUTHOR DESCRIPTION
// 1.0 2017-04-07 rherveille initial release
// ------------------------------------------------------------------
// KEYWORDS : HAMMING ERROR CORRECTION ENCODER
// ------------------------------------------------------------------
// PURPOSE : Adds ECC bits to incoming data
// ------------------------------------------------------------------
// PARAMETERS
// PARAM NAME RANGE DESCRIPTION DEFAULT UNITS
// K 1+ Information vector size 8
// P0_LSB 0,1 0: p0 located at MSB 1
// 1: p0 located at LSB
// ------------------------------------------------------------------
// REUSE ISSUES
// Reset Strategy : none
// Clock Domains : none
// Critical Timing :
// Test Features : na
// Asynchronous I/F : yes
// Scan Methodology : na
// Instantiations : none
// Synthesizable (y/n) : Yes
// Other :
// -FHDR-------------------------------------------------------------
//-----------------------------------------------------------------------------
// Hamming codes can detect and correct a single bit error.
// An extended Hamming code allows detection of double bit errors and
// correction of single bit errors.
// This is called SECDED; Single Error Correction, Double Error Detection
//
// Number of bits required by a Hamming code: n = m + k
// n = code length
// m = number of check bits
// k = number of information bits
//
// Information, parity, and syndrome expressed as vectors:
// u = Information bit vector
// p = Parity check bit vector
// s = Syndrome vector
//
// The parity vector is encoded in 'n'.
// The information bit vector is part of 'p'
// The syndrome vector needs to be calculated.
//
// Bits required:
// p ranges from 0 to m+k; or p_range=m+k+1
// As a result 2^m >= m+k+1
//-----------------------------------------------------------------------------
module ecc_enc #(
parameter K = 8, //Information bit vector size
parameter P0_LSB = 1, //0: p0 is located at MSB
//1: p0 is located at LSB
//these should be localparams
parameter m = calculate_m(K),
parameter n = m + K
)
(
input [K-1:0] d_i, //information bit vector input
output [n :0] q_o, //encoded data word output
output [m :1] p_o, //parity vector output
output p0_o //extended parity bit
);
//---------------------------------------------------------
// Functions
//---------------------------------------------------------
function integer calculate_m;
input integer k;
integer m_local;
begin
m_local=1;
while (2**m_local < m_local+k+1) m_local++;
calculate_m = m_local;
end
endfunction //calculate_m
function [n:1] store_dbits_in_codeword;
input [K-1:0] d;
integer bit_idx, cw_idx;
begin
//This function puts the information bits vector in the correct location
//Information bits are stored in non-power-of-2 locations
//clear all bits
store_dbits_in_codeword = 0;
bit_idx=0; //information vector bit index
for (cw_idx=1; cw_idx<=n; cw_idx++)
if (2**$clog2(cw_idx) != cw_idx)
/* verilator lint_off UNUSEDSIGNAL */
store_dbits_in_codeword[cw_idx] = d[bit_idx++];
/* verilator lint_on UNUSEDSIGNAL */
end
endfunction //store_dbits_in_codeword
function [m:1] calculate_p;
input [n:1] cw;
integer p_idx, cw_idx;
begin
//clear p
calculate_p = 0;
for (p_idx =1; p_idx <=m; p_idx++) //parity-index
for (cw_idx=1; cw_idx<=n; cw_idx++) //codeword-index
if (|(2**(p_idx-1) & cw_idx)) calculate_p[p_idx] = calculate_p[p_idx] ^ cw[cw_idx];
end
endfunction //calculate_p
function [n:1] store_p_in_codeword;
input [n:1] cw;
input [m:1] p;
integer i;
begin
//databits don't change ... copy into codeword
store_p_in_codeword = cw;
//put parity vector at power-of-2 locations
for (i=1; i<=m; i=i+1)
store_p_in_codeword[2**(i-1)] = p[i];
end
endfunction //store_p_in_codeword
//---------------------------------------------------------
// Variables
//---------------------------------------------------------
logic [n:1] cw_w_dbits; //codeword with loaded data bits
logic [n:1] cw; //codeword with information + parity bits
//---------------------------------------------------------
// Module Body
//---------------------------------------------------------
/*
Below diagram indicates the locations of the parity and data bits
in the final 'p' vector.
It also shows what databits each parity bit operates on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
p1 p2 d1 p4 d2 d3 d4 p8 d5 d6 d7 d8 d9 d10 d11
p1 x x x x x x x x
p2 x x x x x x x x
p4 x x x x x x x x
p8 x x x x x x x x
*/
//Step 1: Load all databits in codeword
assign cw_w_dbits = store_dbits_in_codeword(d_i);
//Step 2: Calculate p-vector
assign p_o = calculate_p(cw_w_dbits);
//Step 3: Store p-vector in codeword
assign cw = store_p_in_codeword(cw_w_dbits, p_o);
//Step 4: Calculate p0 (extended parity bit)
// and store it in the codeword
assign p0_o = ^cw;
assign q_o = P0_LSB ? {cw,p0_o} : {p0_o,cw};
endmodule

View File

@ -1,6 +1,10 @@
# Clean files
rm -rf formal/ddr3*prf*
rm -rf formal/ddr3_singleconfig
# run verilator lint
echo -e "\e[32mRun Verilator Lint:\e[0m"
verilator --lint-only rtl/ddr3_controller.v -Irtl/ -Wall
verilator --lint-only rtl/ddr3_controller.v rtl/ecc/ecc_dec.sv rtl/ecc/ecc_enc.sv -Irtl/ -Wall
echo "DONE!"
@ -9,7 +13,7 @@ echo ""
echo ""
echo -e "\e[32mRun Yosys Compile:\e[0m"
yosys -q -p "
read_verilog -sv ./rtl/ddr3_controller.v;
read_verilog -sv ./rtl/ddr3_controller.v rtl/ecc/ecc_dec.sv rtl/ecc/ecc_enc.sv;
synth -top ddr3_controller"
# run iverilog compile
@ -22,15 +26,25 @@ rm out
echo
# run symbiyosys
echo ""
echo -e "\e[32mRun Symbiyosys Formal Verification: ECC\e[0m"
echo "---------------------------------------"
sby -f formal/ecc.sby
echo ""
echo -e "\e[32mRun Symbiyosys Formal Verification: Single Configuration\e[0m"
echo "---------------------------------------"
sby -f formal/ddr3_singleconfig.sby
echo ""
echo -e "\e[32mRun Symbiyosys Formal Verification: Multiple Configurations\e[0m"
echo -e "\e[32mRun Symbiyosys Formal Verification: Multiple Configurations (DEFAULT)\e[0m"
echo "---------------------------------------"
sby -f formal/ddr3_multiconfig.sby
sby -f formal/ddr3_multiconfig_default.sby
echo ""
echo -e "\e[32mRun Symbiyosys Formal Verification: Multiple Configurations (ECC)\e[0m"
echo "---------------------------------------"
sby -f formal/ddr3_multiconfig_ecc.sby
# ANSI color codes
@ -53,3 +67,14 @@ for folder in formal/ddr3*/ ; do
fi
done
# Iterate over folders inside 'ecc/'
for folder in formal/ecc/ ; do
# Check if the 'PASS' file exists in the folder
if [[ -e "${folder}PASS" ]]; then
# Print the folder name and 'PASS' in green
echo -e "${folder}: ${GREEN}PASS${NC}"
else
# Print the folder name and 'FAIL' in red
echo -e "${folder}: ${RED}FAIL${NC}"
fi
done

View File

@ -57,13 +57,14 @@ module ddr3_dimm_micron_sim;
`ifdef EIGHT_LANES_x8
localparam BYTE_LANES = 8,
ODELAY_SUPPORTED = 1;;
ODELAY_SUPPORTED = 1;
`endif
localparam CONTROLLER_CLK_PERIOD = 10_000, //ps, period of clock input to this DDR3 controller module
DDR3_CLK_PERIOD = 2500, //ps, period of clock input to DDR3 RAM device
AUX_WIDTH = 16; // AUX lines
AUX_WIDTH = 16, // AUX lines
ECC_ENABLE = 0; // ECC enable
reg i_controller_clk, i_ddr3_clk, i_ref_clk, i_ddr3_clk_90;
reg i_rst_n;
@ -160,7 +161,9 @@ ddr3_top #(
.AUX_WIDTH(AUX_WIDTH), //width of aux line (must be >= 4)
.MICRON_SIM(1), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
.ODELAY_SUPPORTED(ODELAY_SUPPORTED), //set to 1 if ODELAYE2 is supported
.SECOND_WISHBONE(0) //set to 1 if 2nd wishbone for debugging is needed
.SECOND_WISHBONE(0), //set to 1 if 2nd wishbone for debugging is needed
.ECC_ENABLE(ECC_ENABLE), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
.WB_ERROR(1) // set to 1 to support Wishbone error (asserts at ECC double bit error)
) ddr3_top
(
//clock and reset
@ -258,7 +261,52 @@ ddr3_top #(
.dq(dq)
);
`endif
reg[ddr3_top.ddr3_controller_inst.wb_data_bits-1:0] orig_phy_data;
// Force change for ECC tests
// Uncommented since there is ECC_TEST parameter inside ddr3_controller to test ECC
// generate
// if(ECC_ENABLE == 2) begin
// always @(ddr3_top.ddr3_controller_inst.stage2_data[ddr3_top.ddr3_controller_inst.STAGE2_DATA_DEPTH-1]) begin
// if(ddr3_top.ddr3_controller_inst.initial_calibration_done) begin
// orig_phy_data = ddr3_top.ddr3_controller_inst.stage2_data[ddr3_top.ddr3_controller_inst.STAGE2_DATA_DEPTH-1];
// orig_phy_data[0] = 1'b0; // replace bit 0 with 0
// force ddr3_top.ddr3_controller_inst.o_phy_data = orig_phy_data;
// end
// else begin
// release ddr3_top.ddr3_controller_inst.o_phy_data;
// end
// end
// end
// else if(ECC_ENABLE == 1) begin
// always @(ddr3_top.ddr3_controller_inst.stage2_data[ddr3_top.ddr3_controller_inst.STAGE2_DATA_DEPTH-1]) begin
// if(ddr3_top.ddr3_controller_inst.initial_calibration_done) begin
// orig_phy_data = ddr3_top.ddr3_controller_inst.stage2_data[ddr3_top.ddr3_controller_inst.STAGE2_DATA_DEPTH-1];
// for(index = 0; index < 8; index = index + 1) begin
// orig_phy_data[8*BYTE_LANES*index] = 1'b0; // replace LSB of EVERY burst
// end
// force ddr3_top.ddr3_controller_inst.o_phy_data = orig_phy_data;
// end
// else begin
// release ddr3_top.ddr3_controller_inst.o_phy_data;
// end
// end
// end
// else if(ECC_ENABLE == 3) begin
// always @(ddr3_top.ddr3_controller_inst.stage1_data) begin
// if(ddr3_top.ddr3_controller_inst.initial_calibration_done) begin
// orig_phy_data = ddr3_top.ddr3_controller_inst.stage1_data;
// //corrupt last bit to zero of the encoded data (non-ECC data)
// for(index = 0; index < ddr3_top.ddr3_controller_inst.wb_data_bits/64; index = index + 1) begin
// orig_phy_data[64*index+2] = 1'b0; // replace second to LSB of EVERY 64 bit blocks
// end
// force ddr3_top.ddr3_controller_inst.stage1_data_encoded = orig_phy_data;
// end
// else begin
// release ddr3_top.ddr3_controller_inst.stage1_data_encoded;
// end
// end
// end
// endgenerate
reg[511:0] write_data = 0, expected_read_data = 0;
integer address = 0, read_address = 0, address_inner = 0;
integer start_address = 0, start_read_address;
@ -267,6 +315,7 @@ ddr3_top #(
integer number_of_injected_errors = 0;
integer number_of_op = 0;
integer time_started = 0;
integer average_1, average_2, average_3, average_4;
localparam MAX_READS = (2**COL_BITS)*(2**BA_BITS + 1)/8; //1 row = 2**(COL_BITS) addresses/8 burst = 128 words per row. Times 8 to pass all 8 banks
initial begin
//toggle reset for 1 slow clk
@ -326,7 +375,14 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
//Read sequentially
address <= start_address;
#1; //just to make sure the non-blocking are assignments are all over
@ -346,12 +402,14 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
/*while(i_wb_stb) begin
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end*/
end
#1000_000; //rest here
average_1 = ($time-time_started)/(number_of_op*1000);
$display("\n--------------------------------\nDONE TEST 1: FIRST ROW\nNumber of Operations: %0d\nTime Started: %0d ns\nTime Done: %0d ns\nAverage Rate: %0d ns/request\n--------------------------------\n\n",
number_of_op,time_started/1000, $time/1000, ($time-time_started)/(number_of_op*1000));
// #100_000;
@ -391,6 +449,12 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// Read sequentially
address <= start_address;
@ -411,18 +475,21 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
/*while(i_wb_stb) begin
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end*/
end
#1000_000; //rest here
average_2 = ($time-time_started)/(number_of_op*1000);
$display("\n--------------------------------\nDONE TEST 1: MIDDLE ROW\nNumber of Operations: %0d\nTime Started: %0d ns\nTime Done: %0d ns\nAverage Rate: %0d ns/request\n--------------------------------\n\n",
number_of_op,time_started/1000, $time/1000, ($time-time_started)/(number_of_op*1000));
//#100_000;
// write to last row (then go back to first row)
start_address <= ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS) - (2**COL_BITS)*(2**BA_BITS))*($bits(ddr3_top.i_wb_data)/32)/8; //start at the last row
start_address <= ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS - (ECC_ENABLE == 3)) - (2**COL_BITS)*(2**BA_BITS))*($bits(ddr3_top.i_wb_data)/32)/8; //start at the last row
#1; //just to make sure the non-blocking are assignments are all over
address <= start_address;
number_of_op <= 0;
@ -451,6 +518,13 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
// turn off strobe
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// Read sequentially
address <= start_address;
@ -471,11 +545,20 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
/*while(i_wb_stb) begin
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end*/
end
// turn off strobe
// @(posedge i_controller_clk) begin
// if(!i_wb_stb || !o_wb_stall) begin
// i_wb_stb <= 0;
// end
// end
#1000_000; //rest here
average_3 = ($time-time_started)/(number_of_op*1000);
$display("\n--------------------------------\nDONE TEST 1: LAST ROW\nNumber of Operations: %0d\nTime Started: %0d ns\nTime Done: %0d ns\nAverage Rate: %0d ns/request\n--------------------------------\n\n",
number_of_op,time_started/1000, $time/1000, ($time-time_started)/(number_of_op*1000));
//#100_000;
@ -511,6 +594,13 @@ ddr3_top #(
end
#1; //just to make sure the non-blocking are assignments are all over
end
// turn off strobe
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// Read sequentially
// Read the random words written at the random addresses
@ -531,11 +621,20 @@ ddr3_top #(
end
end
end
// // turn off strobe
// @(posedge i_controller_clk) begin
// if(!i_wb_stb || !o_wb_stall) begin
// i_wb_stb <= 0;
// end
// end
// #1000_000; //rest here
while(i_wb_stb) begin
@(posedge i_controller_clk) begin
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
average_4 = ($time-time_started)/(number_of_op*1000);
$display("\n--------------------------------\nDONE TEST 2: RANDOM\nNumber of Operations: %0d\nTime Started: %0d ns\nTime Done: %0d ns\nAverage Rate: %0d ns/request\n--------------------------------\n\n",
number_of_op,time_started/1000, $time/1000, ($time-time_started)/(number_of_op*1000));
@ -615,10 +714,16 @@ ddr3_top #(
while(read_address < start_read_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux == 0) begin
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux[2:0] == 0) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if (ECC_ENABLE == 2) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS] = 0;
end
else if (ECC_ENABLE == 1) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS*8] = 0;
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
@ -635,10 +740,16 @@ ddr3_top #(
read_address = start_read_address;
while(read_address < start_read_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux == 0) begin
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux[2:0] == 0) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if (ECC_ENABLE == 2) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS] = 0;
end
else if (ECC_ENABLE == 1) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS*8] = 0;
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
@ -651,14 +762,20 @@ ddr3_top #(
end
end
start_read_address = ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS) - (2**COL_BITS)*(2**BA_BITS))*($bits(ddr3_top.i_wb_data)/32)/8; //start at the last row
start_read_address = ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS-(ECC_ENABLE == 3)) - (2**COL_BITS)*(2**BA_BITS))*($bits(ddr3_top.i_wb_data)/32)/8; //start at the last row
read_address = start_read_address;
while(read_address < start_read_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux == 0) begin
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux[2:0] == 0) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if (ECC_ENABLE == 2) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS] = 0;
end
else if (ECC_ENABLE == 1) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS*8] = 0;
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
@ -675,10 +792,16 @@ ddr3_top #(
read_address = random_start;
while(read_address < random_start + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux == 0) begin
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE && o_aux[2:0] == 0) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if (ECC_ENABLE == 2) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS] = 0;
end
else if (ECC_ENABLE == 1) begin
expected_read_data[511 : ddr3_top.ddr3_controller_inst.ECC_INFORMATION_BITS*8] = 0;
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;

View File

@ -11,15 +11,15 @@
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="64,090.179 ns"></ZoomStartTime>
<ZoomEndTime time="64,220.813 ns"></ZoomEndTime>
<Cursor1Time time="64,130.000 ns"></Cursor1Time>
<ZoomStartTime time="749.583 ns"></ZoomStartTime>
<ZoomEndTime time="6,229.584 ns"></ZoomEndTime>
<Cursor1Time time="1,130.000 ns"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="268"></NameColumnWidth>
<ValueColumnWidth column_width="66"></ValueColumnWidth>
<NameColumnWidth column_width="272"></NameColumnWidth>
<ValueColumnWidth column_width="129"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="44" />
<WVObjectSize size="47" />
<wvobject fp_name="divider869" type="divider">
<obj_property name="label">Clocks and Reset</obj_property>
<obj_property name="DisplayName">label</obj_property>
@ -48,6 +48,18 @@
<obj_property name="label">Calibration</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_controller_inst/\sideband_ECC_per_8_bursts.ecc_dec_inst /sb_err">
<obj_property name="ElementShortName">sb_err</obj_property>
<obj_property name="ObjectShortName">sb_err</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_controller_inst/\sideband_ECC_per_8_bursts.ecc_dec_inst /db_err">
<obj_property name="ElementShortName">db_err</obj_property>
<obj_property name="ObjectShortName">db_err</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_controller_inst/initial_calibration_done">
<obj_property name="ElementShortName">initial_calibration_done</obj_property>
<obj_property name="ObjectShortName">initial_calibration_done</obj_property>
</wvobject>
<wvobject type="array" fp_name="/ddr3_dimm_micron_sim/calibration_state">
<obj_property name="ElementShortName">calibration_state[319:0]</obj_property>
<obj_property name="ObjectShortName">calibration_state[319:0]</obj_property>
@ -71,12 +83,10 @@
<wvobject type="array" fp_name="/ddr3_dimm_micron_sim/ddr3_top/io_ddr3_dqs">
<obj_property name="ElementShortName">io_ddr3_dqs[1:0]</obj_property>
<obj_property name="ObjectShortName">io_ddr3_dqs[1:0]</obj_property>
<obj_property name="isExpanded"></obj_property>
</wvobject>
<wvobject type="array" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_phy_inst/idelay_dqs">
<obj_property name="ElementShortName">idelay_dqs[1:0]</obj_property>
<obj_property name="ObjectShortName">idelay_dqs[1:0]</obj_property>
<obj_property name="isExpanded"></obj_property>
</wvobject>
<wvobject type="array" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_controller_inst/lane">
<obj_property name="ElementShortName">lane[0:0]</obj_property>

49
testbench/xsim/README.txt Normal file
View File

@ -0,0 +1,49 @@
################################################################################
# Vivado (TM) v2022.1 (64-bit)
#
# README.txt: Please read the sections below to understand the steps required to
# run the exported script and information about the source files.
#
# Generated by export_simulation on Sat Jul 27 15:51:00 PST 2024
#
################################################################################
1. How to run the generated simulation script:-
From the shell prompt in the current directory, issue the following command:-
./ddr3_dimm_micron_sim.sh
This command will launch the 'compile', 'elaborate' and 'simulate' functions
implemented in the script file for the 3-step flow. These functions are called
from the main 'run' function in the script file.
The 'run' function first executes the 'setup' function, the purpose of which is to
create simulator specific setup files, create design library mappings and library
directories and copy 'glbl.v' from the Vivado software install location into the
current directory.
The 'setup' function is also used for removing the simulator generated data in
order to reset the current directory to the original state when export_simulation
was launched from Vivado. This generated data can be removed by specifying the
'-reset_run' switch to the './ddr3_dimm_micron_sim.sh' script.
./ddr3_dimm_micron_sim.sh -reset_run
To keep the generated data from the previous run but regenerate the setup files and
library directories, use the '-noclean_files' switch.
./ddr3_dimm_micron_sim.sh -noclean_files
For more information on the script, please type './ddr3_dimm_micron_sim.sh -help'.
2. Additional design information files:-
export_simulation generates following additional file that can be used for fetching
the design files information or for integrating with external custom scripts.
Name : file_info.txt
Purpose: This file contains detail design file information based on the compile order
when export_simulation was executed from Vivado. The file contains information
about the file type, name, whether it is part of the IP, associated library
and the file path information.

12
testbench/xsim/cmd.tcl Normal file
View File

@ -0,0 +1,12 @@
set curr_wave [current_wave_config]
if { [string length $curr_wave] == 0 } {
if { [llength [get_objects]] > 0} {
add_wave /
set_property needs_save false [current_wave_config]
} else {
send_msg_id Add_Wave-1 WARNING "No top level signals found. Simulator will start without a wave window. If you want to open a wave window go to 'File->New Waveform Configuration' or type 'create_wave_config' in the TCL console."
}
}
run -all
quit

View File

@ -0,0 +1,9 @@
ddr3_controller.v,verilog,xil_defaultlib,../Desktop/UberDDR3/rtl/ddr3_controller.v,incdir="../"
ddr3_phy.v,verilog,xil_defaultlib,../Desktop/UberDDR3/rtl/ddr3_phy.v,incdir="../"
ddr3_top.v,verilog,xil_defaultlib,../Desktop/UberDDR3/rtl/ddr3_top.v,incdir="../"
ddr3.sv,systemverilog,xil_defaultlib,../Desktop/UberDDR3/testbench/ddr3.sv,incdir="../"
ddr3.sv,systemverilog,xil_defaultlib,../Desktop/UberDDR3/testbench/ddr3_module.sv,incdir="../"
ecc_dec.sv,systemverilog,xil_defaultlib,../Desktop/UberDDR3/rtl/ecc/ecc_dec.sv,incdir="../"
ecc_enc.sv,systemverilog,xil_defaultlib,../Desktop/UberDDR3/rtl/ecc/ecc_enc.sv,incdir="../"
ddr3_dimm_micron_sim.sv,systemverilog,xil_defaultlib,../Desktop/UberDDR3/testbench/ddr3_dimm_micron_sim.sv,incdir="../"
glbl.v,Verilog,xil_defaultlib,glbl.v

84
testbench/xsim/glbl.v Normal file
View File

@ -0,0 +1,84 @@
// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $
`ifndef GLBL
`define GLBL
`timescale 1 ps / 1 ps
module glbl ();
parameter ROC_WIDTH = 100000;
parameter TOC_WIDTH = 0;
parameter GRES_WIDTH = 10000;
parameter GRES_START = 10000;
//-------- STARTUP Globals --------------
wire GSR;
wire GTS;
wire GWE;
wire PRLD;
wire GRESTORE;
tri1 p_up_tmp;
tri (weak1, strong0) PLL_LOCKG = p_up_tmp;
wire PROGB_GLBL;
wire CCLKO_GLBL;
wire FCSBO_GLBL;
wire [3:0] DO_GLBL;
wire [3:0] DI_GLBL;
reg GSR_int;
reg GTS_int;
reg PRLD_int;
reg GRESTORE_int;
//-------- JTAG Globals --------------
wire JTAG_TDO_GLBL;
wire JTAG_TCK_GLBL;
wire JTAG_TDI_GLBL;
wire JTAG_TMS_GLBL;
wire JTAG_TRST_GLBL;
reg JTAG_CAPTURE_GLBL;
reg JTAG_RESET_GLBL;
reg JTAG_SHIFT_GLBL;
reg JTAG_UPDATE_GLBL;
reg JTAG_RUNTEST_GLBL;
reg JTAG_SEL1_GLBL = 0;
reg JTAG_SEL2_GLBL = 0 ;
reg JTAG_SEL3_GLBL = 0;
reg JTAG_SEL4_GLBL = 0;
reg JTAG_USER_TDO1_GLBL = 1'bz;
reg JTAG_USER_TDO2_GLBL = 1'bz;
reg JTAG_USER_TDO3_GLBL = 1'bz;
reg JTAG_USER_TDO4_GLBL = 1'bz;
assign (strong1, weak0) GSR = GSR_int;
assign (strong1, weak0) GTS = GTS_int;
assign (weak1, weak0) PRLD = PRLD_int;
assign (strong1, weak0) GRESTORE = GRESTORE_int;
initial begin
GSR_int = 1'b1;
PRLD_int = 1'b1;
#(ROC_WIDTH)
GSR_int = 1'b0;
PRLD_int = 1'b0;
end
initial begin
GTS_int = 1'b1;
#(TOC_WIDTH)
GTS_int = 1'b0;
end
initial begin
GRESTORE_int = 1'b0;
#(GRES_START);
GRESTORE_int = 1'b1;
#(GRES_WIDTH);
GRESTORE_int = 1'b0;
end
endmodule
`endif

26
testbench/xsim/run_batch.sh Executable file
View File

@ -0,0 +1,26 @@
rm -rf *backup*
rm -rf *test_ecc*.log*
echo -e "\e[32mRun test: test_ecc_0 \e[0m"
./test_ecc_0.sh -reset_run
./test_ecc_0.sh >> ./test_ecc_0.log
./test_ecc_0.sh -reset_run
echo ""
echo ""
echo -e "\e[32mRun test: test_ecc_1 \e[0m"
./test_ecc_1.sh >> ./test_ecc_1.log
./test_ecc_1.sh -reset_run
echo ""
echo ""
echo -e "\e[32mRun test: test_ecc_2 \e[0m"
./test_ecc_2.sh >> ./test_ecc_2.log
./test_ecc_2.sh -reset_run
echo ""
echo ""
echo -e "\e[32mRun test: test_ecc_3 \e[0m"
./test_ecc_3.sh >> ./test_ecc_3.log
./test_ecc_3.sh -reset_run
rm -rf *backup*

22240
testbench/xsim/test_ecc_0.log Normal file

File diff suppressed because it is too large Load Diff

129
testbench/xsim/test_ecc_0.sh Executable file
View File

@ -0,0 +1,129 @@
#!/bin/bash -f
#*********************************************************************************************************
# Vivado (TM) v2022.1 (64-bit)
#
# Filename : ddr3_dimm_micron_sim.sh
# Simulator : Xilinx Vivado Simulator
# Description : Simulation script for compiling, elaborating and verifying the project source files.
# The script will automatically create the design libraries sub-directories in the run
# directory, add the library logical mappings in the simulator setup file, create default
# 'do/prj' file, execute compilation, elaboration and simulation steps.
#
# Generated by Vivado on Sat Jul 27 15:51:00 PST 2024
# SW Build 3526262 on Mon Apr 18 15:47:01 MDT 2022
#
# Tool Version Limit: 2022.04
#
# usage: ddr3_dimm_micron_sim.sh [-help]
# usage: ddr3_dimm_micron_sim.sh [-lib_map_path]
# usage: ddr3_dimm_micron_sim.sh [-noclean_files]
# usage: ddr3_dimm_micron_sim.sh [-reset_run]
#
#*********************************************************************************************************
# Set xvlog options
xvlog_opts="--incr --relax -L uvm"
# Script info
echo -e "ddr3_dimm_micron_sim.sh - Script generated by export_simulation (Vivado v2022.1 (64-bit)-id)\n"
# Main steps
run()
{
check_args $# $1
setup $1 $2
compile
elaborate
simulate
}
# RUN_STEP: <compile>
compile()
{
xvlog $xvlog_opts -prj vlog.prj 2>&1 | tee compile.log
}
# RUN_STEP: <elaborate>
elaborate()
{
xelab -generic_top "ECC_ENABLE=0" --incr --debug typical --relax --mt auto -L xil_defaultlib -L uvm -L unisims_ver -L unimacro_ver -L secureip --snapshot ddr3_dimm_micron_sim xil_defaultlib.ddr3_dimm_micron_sim xil_defaultlib.glbl -log elaborate.log
}
# RUN_STEP: <simulate>
simulate()
{
xsim ddr3_dimm_micron_sim -key {Behavioral:sim_1:Functional:ddr3_dimm_micron_sim} -tclbatch cmd.tcl -log simulate.log
}
# STEP: setup
setup()
{
case $1 in
"-lib_map_path" )
if [[ ($2 == "") ]]; then
echo -e "ERROR: Simulation library directory path not specified (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
;;
"-reset_run" )
reset_run
echo -e "INFO: Simulation run files deleted.\n"
exit 0
;;
"-noclean_files" )
# do not remove previous data
;;
* )
esac
# Add any setup/initialization commands here:-
# <user specific commands>
}
# Delete generated data from the previous run
reset_run()
{
files_to_remove=(xelab.pb xsim.jou xvhdl.log xvlog.log compile.log elaborate.log simulate.log xelab.log xsim.log run.log xvhdl.pb xvlog.pb ddr3_dimm_micron_sim.wdb xsim.dir)
for (( i=0; i<${#files_to_remove[*]}; i++ )); do
file="${files_to_remove[i]}"
if [[ -e $file ]]; then
rm -rf $file
fi
done
}
# Check command line arguments
check_args()
{
if [[ ($1 == 1 ) && ($2 != "-lib_map_path" && $2 != "-noclean_files" && $2 != "-reset_run" && $2 != "-help" && $2 != "-h") ]]; then
echo -e "ERROR: Unknown option specified '$2' (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
if [[ ($2 == "-help" || $2 == "-h") ]]; then
usage
fi
}
# Script usage
usage()
{
msg="Usage: ddr3_dimm_micron_sim.sh [-help]\n\
Usage: ddr3_dimm_micron_sim.sh [-lib_map_path]\n\
Usage: ddr3_dimm_micron_sim.sh [-reset_run]\n\
Usage: ddr3_dimm_micron_sim.sh [-noclean_files]\n\n\
[-help] -- Print help information for this script\n\n\
[-lib_map_path <path>] -- Compiled simulation library directory path. The simulation library is compiled\n\
using the compile_simlib tcl command. Please see 'compile_simlib -help' for more information.\n\n\
[-reset_run] -- Recreate simulator setup files and library mappings for a clean run. The generated files\n\
from the previous run will be removed. If you don't want to remove the simulator generated files, use the\n\
-noclean_files switch.\n\n\
[-noclean_files] -- Reset previous run, but do not remove simulator generated files from the previous run.\n\n"
echo -e $msg
exit 1
}
# Launch script
run $1 $2

19569
testbench/xsim/test_ecc_1.log Normal file

File diff suppressed because it is too large Load Diff

129
testbench/xsim/test_ecc_1.sh Executable file
View File

@ -0,0 +1,129 @@
#!/bin/bash -f
#*********************************************************************************************************
# Vivado (TM) v2022.1 (64-bit)
#
# Filename : ddr3_dimm_micron_sim.sh
# Simulator : Xilinx Vivado Simulator
# Description : Simulation script for compiling, elaborating and verifying the project source files.
# The script will automatically create the design libraries sub-directories in the run
# directory, add the library logical mappings in the simulator setup file, create default
# 'do/prj' file, execute compilation, elaboration and simulation steps.
#
# Generated by Vivado on Sat Jul 27 15:51:00 PST 2024
# SW Build 3526262 on Mon Apr 18 15:47:01 MDT 2022
#
# Tool Version Limit: 2022.04
#
# usage: ddr3_dimm_micron_sim.sh [-help]
# usage: ddr3_dimm_micron_sim.sh [-lib_map_path]
# usage: ddr3_dimm_micron_sim.sh [-noclean_files]
# usage: ddr3_dimm_micron_sim.sh [-reset_run]
#
#*********************************************************************************************************
# Set xvlog options
xvlog_opts="--incr --relax -L uvm"
# Script info
echo -e "ddr3_dimm_micron_sim.sh - Script generated by export_simulation (Vivado v2022.1 (64-bit)-id)\n"
# Main steps
run()
{
check_args $# $1
setup $1 $2
compile
elaborate
simulate
}
# RUN_STEP: <compile>
compile()
{
xvlog $xvlog_opts -prj vlog.prj 2>&1 | tee compile.log
}
# RUN_STEP: <elaborate>
elaborate()
{
xelab -generic_top "ECC_ENABLE=1" --incr --debug typical --relax --mt auto -L xil_defaultlib -L uvm -L unisims_ver -L unimacro_ver -L secureip --snapshot ddr3_dimm_micron_sim xil_defaultlib.ddr3_dimm_micron_sim xil_defaultlib.glbl -log elaborate.log
}
# RUN_STEP: <simulate>
simulate()
{
xsim ddr3_dimm_micron_sim -key {Behavioral:sim_1:Functional:ddr3_dimm_micron_sim} -tclbatch cmd.tcl -log simulate.log
}
# STEP: setup
setup()
{
case $1 in
"-lib_map_path" )
if [[ ($2 == "") ]]; then
echo -e "ERROR: Simulation library directory path not specified (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
;;
"-reset_run" )
reset_run
echo -e "INFO: Simulation run files deleted.\n"
exit 0
;;
"-noclean_files" )
# do not remove previous data
;;
* )
esac
# Add any setup/initialization commands here:-
# <user specific commands>
}
# Delete generated data from the previous run
reset_run()
{
files_to_remove=(xelab.pb xsim.jou xvhdl.log xvlog.log compile.log elaborate.log simulate.log xelab.log xsim.log run.log xvhdl.pb xvlog.pb ddr3_dimm_micron_sim.wdb xsim.dir)
for (( i=0; i<${#files_to_remove[*]}; i++ )); do
file="${files_to_remove[i]}"
if [[ -e $file ]]; then
rm -rf $file
fi
done
}
# Check command line arguments
check_args()
{
if [[ ($1 == 1 ) && ($2 != "-lib_map_path" && $2 != "-noclean_files" && $2 != "-reset_run" && $2 != "-help" && $2 != "-h") ]]; then
echo -e "ERROR: Unknown option specified '$2' (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
if [[ ($2 == "-help" || $2 == "-h") ]]; then
usage
fi
}
# Script usage
usage()
{
msg="Usage: ddr3_dimm_micron_sim.sh [-help]\n\
Usage: ddr3_dimm_micron_sim.sh [-lib_map_path]\n\
Usage: ddr3_dimm_micron_sim.sh [-reset_run]\n\
Usage: ddr3_dimm_micron_sim.sh [-noclean_files]\n\n\
[-help] -- Print help information for this script\n\n\
[-lib_map_path <path>] -- Compiled simulation library directory path. The simulation library is compiled\n\
using the compile_simlib tcl command. Please see 'compile_simlib -help' for more information.\n\n\
[-reset_run] -- Recreate simulator setup files and library mappings for a clean run. The generated files\n\
from the previous run will be removed. If you don't want to remove the simulator generated files, use the\n\
-noclean_files switch.\n\n\
[-noclean_files] -- Reset previous run, but do not remove simulator generated files from the previous run.\n\n"
echo -e $msg
exit 1
}
# Launch script
run $1 $2

19569
testbench/xsim/test_ecc_2.log Normal file

File diff suppressed because it is too large Load Diff

129
testbench/xsim/test_ecc_2.sh Executable file
View File

@ -0,0 +1,129 @@
#!/bin/bash -f
#*********************************************************************************************************
# Vivado (TM) v2022.1 (64-bit)
#
# Filename : ddr3_dimm_micron_sim.sh
# Simulator : Xilinx Vivado Simulator
# Description : Simulation script for compiling, elaborating and verifying the project source files.
# The script will automatically create the design libraries sub-directories in the run
# directory, add the library logical mappings in the simulator setup file, create default
# 'do/prj' file, execute compilation, elaboration and simulation steps.
#
# Generated by Vivado on Sat Jul 27 15:51:00 PST 2024
# SW Build 3526262 on Mon Apr 18 15:47:01 MDT 2022
#
# Tool Version Limit: 2022.04
#
# usage: ddr3_dimm_micron_sim.sh [-help]
# usage: ddr3_dimm_micron_sim.sh [-lib_map_path]
# usage: ddr3_dimm_micron_sim.sh [-noclean_files]
# usage: ddr3_dimm_micron_sim.sh [-reset_run]
#
#*********************************************************************************************************
# Set xvlog options
xvlog_opts="--incr --relax -L uvm"
# Script info
echo -e "ddr3_dimm_micron_sim.sh - Script generated by export_simulation (Vivado v2022.1 (64-bit)-id)\n"
# Main steps
run()
{
check_args $# $1
setup $1 $2
compile
elaborate
simulate
}
# RUN_STEP: <compile>
compile()
{
xvlog $xvlog_opts -prj vlog.prj 2>&1 | tee compile.log
}
# RUN_STEP: <elaborate>
elaborate()
{
xelab -generic_top "ECC_ENABLE=2" --incr --debug typical --relax --mt auto -L xil_defaultlib -L uvm -L unisims_ver -L unimacro_ver -L secureip --snapshot ddr3_dimm_micron_sim xil_defaultlib.ddr3_dimm_micron_sim xil_defaultlib.glbl -log elaborate.log
}
# RUN_STEP: <simulate>
simulate()
{
xsim ddr3_dimm_micron_sim -key {Behavioral:sim_1:Functional:ddr3_dimm_micron_sim} -tclbatch cmd.tcl -log simulate.log
}
# STEP: setup
setup()
{
case $1 in
"-lib_map_path" )
if [[ ($2 == "") ]]; then
echo -e "ERROR: Simulation library directory path not specified (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
;;
"-reset_run" )
reset_run
echo -e "INFO: Simulation run files deleted.\n"
exit 0
;;
"-noclean_files" )
# do not remove previous data
;;
* )
esac
# Add any setup/initialization commands here:-
# <user specific commands>
}
# Delete generated data from the previous run
reset_run()
{
files_to_remove=(xelab.pb xsim.jou xvhdl.log xvlog.log compile.log elaborate.log simulate.log xelab.log xsim.log run.log xvhdl.pb xvlog.pb ddr3_dimm_micron_sim.wdb xsim.dir)
for (( i=0; i<${#files_to_remove[*]}; i++ )); do
file="${files_to_remove[i]}"
if [[ -e $file ]]; then
rm -rf $file
fi
done
}
# Check command line arguments
check_args()
{
if [[ ($1 == 1 ) && ($2 != "-lib_map_path" && $2 != "-noclean_files" && $2 != "-reset_run" && $2 != "-help" && $2 != "-h") ]]; then
echo -e "ERROR: Unknown option specified '$2' (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
if [[ ($2 == "-help" || $2 == "-h") ]]; then
usage
fi
}
# Script usage
usage()
{
msg="Usage: ddr3_dimm_micron_sim.sh [-help]\n\
Usage: ddr3_dimm_micron_sim.sh [-lib_map_path]\n\
Usage: ddr3_dimm_micron_sim.sh [-reset_run]\n\
Usage: ddr3_dimm_micron_sim.sh [-noclean_files]\n\n\
[-help] -- Print help information for this script\n\n\
[-lib_map_path <path>] -- Compiled simulation library directory path. The simulation library is compiled\n\
using the compile_simlib tcl command. Please see 'compile_simlib -help' for more information.\n\n\
[-reset_run] -- Recreate simulator setup files and library mappings for a clean run. The generated files\n\
from the previous run will be removed. If you don't want to remove the simulator generated files, use the\n\
-noclean_files switch.\n\n\
[-noclean_files] -- Reset previous run, but do not remove simulator generated files from the previous run.\n\n"
echo -e $msg
exit 1
}
# Launch script
run $1 $2

23435
testbench/xsim/test_ecc_3.log Normal file

File diff suppressed because it is too large Load Diff

129
testbench/xsim/test_ecc_3.sh Executable file
View File

@ -0,0 +1,129 @@
#!/bin/bash -f
#*********************************************************************************************************
# Vivado (TM) v2022.1 (64-bit)
#
# Filename : ddr3_dimm_micron_sim.sh
# Simulator : Xilinx Vivado Simulator
# Description : Simulation script for compiling, elaborating and verifying the project source files.
# The script will automatically create the design libraries sub-directories in the run
# directory, add the library logical mappings in the simulator setup file, create default
# 'do/prj' file, execute compilation, elaboration and simulation steps.
#
# Generated by Vivado on Sat Jul 27 15:51:00 PST 2024
# SW Build 3526262 on Mon Apr 18 15:47:01 MDT 2022
#
# Tool Version Limit: 2022.04
#
# usage: ddr3_dimm_micron_sim.sh [-help]
# usage: ddr3_dimm_micron_sim.sh [-lib_map_path]
# usage: ddr3_dimm_micron_sim.sh [-noclean_files]
# usage: ddr3_dimm_micron_sim.sh [-reset_run]
#
#*********************************************************************************************************
# Set xvlog options
xvlog_opts="--incr --relax -L uvm"
# Script info
echo -e "ddr3_dimm_micron_sim.sh - Script generated by export_simulation (Vivado v2022.1 (64-bit)-id)\n"
# Main steps
run()
{
check_args $# $1
setup $1 $2
compile
elaborate
simulate
}
# RUN_STEP: <compile>
compile()
{
xvlog $xvlog_opts -prj vlog.prj 2>&1 | tee compile.log
}
# RUN_STEP: <elaborate>
elaborate()
{
xelab -generic_top "ECC_ENABLE=3" --incr --debug typical --relax --mt auto -L xil_defaultlib -L uvm -L unisims_ver -L unimacro_ver -L secureip --snapshot ddr3_dimm_micron_sim xil_defaultlib.ddr3_dimm_micron_sim xil_defaultlib.glbl -log elaborate.log
}
# RUN_STEP: <simulate>
simulate()
{
xsim ddr3_dimm_micron_sim -key {Behavioral:sim_1:Functional:ddr3_dimm_micron_sim} -tclbatch cmd.tcl -log simulate.log
}
# STEP: setup
setup()
{
case $1 in
"-lib_map_path" )
if [[ ($2 == "") ]]; then
echo -e "ERROR: Simulation library directory path not specified (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
;;
"-reset_run" )
reset_run
echo -e "INFO: Simulation run files deleted.\n"
exit 0
;;
"-noclean_files" )
# do not remove previous data
;;
* )
esac
# Add any setup/initialization commands here:-
# <user specific commands>
}
# Delete generated data from the previous run
reset_run()
{
files_to_remove=(xelab.pb xsim.jou xvhdl.log xvlog.log compile.log elaborate.log simulate.log xelab.log xsim.log run.log xvhdl.pb xvlog.pb ddr3_dimm_micron_sim.wdb xsim.dir)
for (( i=0; i<${#files_to_remove[*]}; i++ )); do
file="${files_to_remove[i]}"
if [[ -e $file ]]; then
rm -rf $file
fi
done
}
# Check command line arguments
check_args()
{
if [[ ($1 == 1 ) && ($2 != "-lib_map_path" && $2 != "-noclean_files" && $2 != "-reset_run" && $2 != "-help" && $2 != "-h") ]]; then
echo -e "ERROR: Unknown option specified '$2' (type \"./ddr3_dimm_micron_sim.sh -help\" for more information)\n"
exit 1
fi
if [[ ($2 == "-help" || $2 == "-h") ]]; then
usage
fi
}
# Script usage
usage()
{
msg="Usage: ddr3_dimm_micron_sim.sh [-help]\n\
Usage: ddr3_dimm_micron_sim.sh [-lib_map_path]\n\
Usage: ddr3_dimm_micron_sim.sh [-reset_run]\n\
Usage: ddr3_dimm_micron_sim.sh [-noclean_files]\n\n\
[-help] -- Print help information for this script\n\n\
[-lib_map_path <path>] -- Compiled simulation library directory path. The simulation library is compiled\n\
using the compile_simlib tcl command. Please see 'compile_simlib -help' for more information.\n\n\
[-reset_run] -- Recreate simulator setup files and library mappings for a clean run. The generated files\n\
from the previous run will be removed. If you don't want to remove the simulator generated files, use the\n\
-noclean_files switch.\n\n\
[-noclean_files] -- Reset previous run, but do not remove simulator generated files from the previous run.\n\n"
echo -e $msg
exit 1
}
# Launch script
run $1 $2

15
testbench/xsim/vlog.prj Normal file
View File

@ -0,0 +1,15 @@
verilog xil_defaultlib --include "../" \
"../../rtl/ddr3_controller.v" \
"../../rtl/ddr3_phy.v" \
"../../rtl/ddr3_top.v" \
sv xil_defaultlib --include "../" \
"../ddr3.sv" \
"../../rtl/ecc/ecc_dec.sv" \
"../../rtl/ecc/ecc_enc.sv" \
"../ddr3_dimm_micron_sim.sv" \
"../ddr3_module.sv" \
verilog xil_defaultlib "glbl.v"
nosort

1
testbench/xsim/xsim.ini Normal file
View File

@ -0,0 +1 @@
xil_defaultlib=xsim.dir/xil_defaultlib