Merge pull request #9 from AngeloJacobo/add_feature_ecc
Added ECC Feature
This commit is contained in:
commit
79b8b799aa
|
|
@ -1,3 +1,4 @@
|
|||
formal/ddr3_multiconfig_prf*
|
||||
formal/ddr3_multiconfig*prf*
|
||||
formal/ecc/
|
||||
formal/ddr3_singleconfig/
|
||||
example_demo/nexys_video/build/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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*
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
xil_defaultlib=xsim.dir/xil_defaultlib
|
||||
Loading…
Reference in New Issue