self-refresh feature done, passing simulation and formal

This commit is contained in:
AngeloJacobo 2024-11-24 14:31:20 +08:00
parent 1078e2ffe0
commit e08612658b
4 changed files with 192 additions and 66 deletions

View File

@ -255,7 +255,8 @@ module ddr3_controller #(
localparam tXSDLL = nCK_to_cycles(512); // cycles (controller) Exit Self Refresh to commands requiring a locked DLL
localparam tXSDLL_tRFC = tXSDLL - ps_to_cycles(tRFC); // cycles (controller) Time before refresh after exit from self-refresh
localparam tCKE = max(3, ps_to_nCK(7500) ); // nCK CKE minimum pulse width
localparam tCKESR = nCK_to_cycles(tCKE + 1); // cycles (controller) Minimum time that the DDR3 SDRAM must remain in Self-Refresh mode is tCKESR
localparam tCKESR = nCK_to_cycles(tCKE + 1)+ 5; // cycles (controller) Minimum time that the DDR3 SDRAM must remain in Self-Refresh mode is tCKESR
localparam tCPDED = 1; // cycle (tCPDED is at most 2nCK but we make it to 1cycle or 4nCK) Command pass disable delay , required cycles of NOP after CKE low
/*********************************************************************************************************************************************/
@ -668,7 +669,7 @@ module ddr3_controller #(
else
read_rom_instruction = {5'b01000 , CMD_NOP , ps_to_cycles(POWER_ON_RESET_HIGH)};
//0. RESET# needs to be maintained low for minimum 200us with power-up initialization. CKE is pulled
//Low anytime before RESET# being de-asserted (min. time 10 ns). .
//Low<EFBFBD>? anytime before RESET# being de-asserted (min. time 10 ns). .
5'd1:
if (MICRON_SIM)
@ -752,13 +753,16 @@ module ddr3_controller #(
5'd23: read_rom_instruction = {5'b01111, CMD_PRE, ps_to_cycles(tRP)};
// 23. All banks must be precharged (A10-AP = high) and idle for a minimum of the precharge time tRP(min) before the Self-Refresh Command can be applied.
5'd24: read_rom_instruction = {5'b01011, CMD_SREF_EN, tCKESR[DELAY_SLOT_WIDTH-1:0]};
// 24. Self-refresh entry
5'd24: read_rom_instruction = {5'b01001, CMD_NOP, tCPDED[DELAY_SLOT_WIDTH-1:0]};
// 24. CKE must go low to enter self-refresh, tCPDED cycles of NOP are required before CMD_SREF_EN
5'd25: read_rom_instruction = {5'b01001, CMD_SREF_EN, tCKESR[DELAY_SLOT_WIDTH-1:0]};
// 25. Self-refresh entry
// JEDEC Standard No. 79-3E Page 79: The minimum time that the DDR3 SDRAM must remain in Self-Refresh mode is tCKESR
5'd25: read_rom_instruction = {5'b01011, CMD_SREF_XT, tXSDLL_tRFC[DELAY_SLOT_WIDTH-1:0]};
// 25. From 24 (Self-refresh entry), wait until user-self_refresh is disabled then wait for tXSDLL - tRFC before going to 20 (Refresh)
5'd26: read_rom_instruction = {5'b01011, CMD_SREF_XT, tXSDLL_tRFC[DELAY_SLOT_WIDTH-1:0]};
// 26. From 25 (Self-refresh entry), wait until user-self_refresh is disabled then wait for tXSDLL - tRFC before going to 20 (Refresh)
// JEDEC Standard No. 79-3E Page 79: Before a command that requires a locked DLL can be applied, a delay of at least tXSDLL must be satisfied.
// JEDEC Standard No. 79-3E Page 80: Upon exit from Self-Refresh, the DDR3 SDRAM requires a minimum of one extra refresh command before it is put back into Self-Refresh Mode.
@ -798,7 +802,7 @@ module ddr3_controller #(
//delay_counter is 1 (for r/w calibration and prestall delay)
//address will only move forward for these kinds of delay only
//when skip_reset_seq_delay is toggled
else if(instruction[USE_TIMER] /*&& delay_counter != {(DELAY_COUNTER_WIDTH){1'b1}}*/ && !pause_counter) delay_counter <= delay_counter - 1;
else if(instruction[USE_TIMER] /*&& delay_counter != {(DELAY_COUNTER_WIDTH){1'b1}}*/ && !pause_counter && delay_counter != 0) delay_counter <= delay_counter - 1;
//delay_counter of 1 means we will need to update the delay_counter next clock cycle (delay_counter of zero) so we need to retrieve
//now the next instruction. The same thing needs to be done when current instruction does not need the timer delay.
@ -808,7 +812,7 @@ module ddr3_controller #(
if(instruction_address == 5'd22) begin // if user_self_refresh is disabled, wrap back to 19 (Precharge All before Refresh)
instruction_address <= 5'd19;
end
else if(instruction_address == 5'd25) begin // self-refresh exit always wraps back to 20 (Refresh)
else if(instruction_address == 5'd26) begin // self-refresh exit always wraps back to 20 (Refresh)
instruction_address <= 5'd20;
end
else begin
@ -823,6 +827,7 @@ module ddr3_controller #(
if(instruction_address == 5'd22 && user_self_refresh_q) begin // if user_self_refresh is enabled, go straight to 23
instruction_address <= 23; // go to Precharge All for Self-refresh
delay_counter_is_zero <= 1;
delay_counter <= 0;
instruction <= read_rom_instruction(instruction_address);
end
@ -834,7 +839,7 @@ module ddr3_controller #(
// register user-enabled self-refresh
always @(posedge i_controller_clk) begin
user_self_refresh_q <= i_user_self_refresh && (user_self_refresh_q || (instruction_address != 5'd25)); //will not go high again if already at instruction_address 25 (self-refresh exit)
user_self_refresh_q <= i_user_self_refresh && (user_self_refresh_q || (instruction_address != 5'd26)) && final_calibration_done; //will not go high again if already at instruction_address 26 (self-refresh exit), only go high when calibration is done
end
/*********************************************************************************************************************************************/
@ -922,7 +927,7 @@ module ddr3_controller #(
bank_active_row_q[index] <= bank_active_row_d[index];
end
if(instruction_address == 20) begin ///current instruction at precharge
if(instruction_address == 20 || instruction_address == 24) begin ///current instruction at precharge
cmd_odt_q <= 1'b0;
//all banks will be in idle after refresh
for( index=0; index < (1<<BA_BITS); index=index+1) begin
@ -2610,9 +2615,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
DONE_CALIBRATE: begin
calib_stb <= 0;
state_calibrate <= DONE_CALIBRATE;
if(instruction_address == 5'd25) begin // Self-refresh Exit
if(instruction_address == 5'd26) begin // Self-refresh Exit
pause_counter <= user_self_refresh_q; // wait until user-self-refresh is disabled before continuing 25 (Self-refresh Exit)
end
else begin
pause_counter <= 0;
end
end
endcase
@ -2627,7 +2635,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(odelay_data_cntvaluein[lane] == 15) begin
odelay_cntvalue_halfway <= 1;
end
if(instruction_address == 19) begin //pre-stall delay to finish all remaining requests
if(instruction_address == 19 || instruction_address == 23) begin //pre-stall delay before precharge all to finish all remaining requests
pause_counter <= 1; // pause instruction address until pre-stall delay before refresh sequence finishes
//skip to instruction address 20 (precharge all before refresh) when no pending requests anymore
//toggle it for 1 clk cycle only
@ -3509,9 +3517,24 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end
//move the pipeline forward when counter is about to go zero and we are not yet at end of reset sequence
else if((delay_counter == 1 || !instruction[USE_TIMER])) begin
f_addr <= (f_addr == 22)? 19:f_addr + 1;
if(f_addr == 22 && user_self_refresh_q) begin // if self refresh, move forward
f_addr <= 23;
end
else if(f_addr == 22 & !user_self_refresh_q) begin // if not self refresh, move backward
f_addr <= 19;
end
else if (f_addr == 26) begin // 26 (self-refresh exit) always wraps back to 20 (refresh)
f_addr <= 20;
end
else begin // else, just increment
f_addr <= f_addr + 1;
end
f_read <= f_addr;
end
else if(f_addr == 22 && user_self_refresh_q) begin // if self refresh, move forward immediately (no need to wait for delay zero)
f_addr <= 23;
f_read <= f_addr;
end
end
// assert f_addr and f_read as shadows of next and current instruction address
@ -3536,11 +3559,11 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end
else if(f_past_valid) begin
//if counter is zero previously and current instruction needs timer delay, then this cycle should now have the new updated counter value
if( $past(delay_counter_is_zero) && $past(f_read_inst[USE_TIMER]) ) begin
if( $past(delay_counter_is_zero) && $past(f_read_inst[USE_TIMER]) && !$past(user_self_refresh_q) ) begin
assert(delay_counter == f_read_inst[DELAY_COUNTER_WIDTH - 1:0]);
end
//delay_counter_is_zero can be high when counter is zero and current instruction needs delay
if($past(f_read_inst[USE_TIMER]) && !$past(pause_counter) ) begin
if($past(f_read_inst[USE_TIMER]) && !$past(pause_counter) && !$past(user_self_refresh_q)) begin
assert( delay_counter_is_zero == (delay_counter == 0) );
end
//delay_counter_is_zero will go high this cycle when we received a don't-use-timer instruction
@ -3557,12 +3580,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
//if delay is not yet zero and timer delay is enabled, then delay_counter should decrement
if(!$past(delay_counter_is_zero) && $past(f_read_inst[USE_TIMER]) && !$past(pause_counter) ) begin
assert(delay_counter == $past(delay_counter) - 1);
assert((delay_counter == $past(delay_counter) - 1) || (delay_counter == 0 && $past(user_self_refresh_q)));
assert(delay_counter < $past(delay_counter) ); //just to make sure delay_counter will never overflow back to all 1's
end
//sanity checking for the comment "delay_counter will be zero AT NEXT CLOCK CYCLE when counter is now one"
if($past(delay_counter) == 1) begin
if($past(delay_counter) == 1 && !$past(pause_counter)) begin
assert(delay_counter == 0 && delay_counter_is_zero);
end
//assert the relationship between the stages FOR RESET SEQUENCE
@ -3583,15 +3606,18 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
//assert the relationship between the stages FOR REFRESH SEQUENCE
else begin
if(f_read == 22) begin
assert(f_addr == 19); //if current instruction is 22, then next instruction must be at 19 (instruction address wraps from 15 to 12)
assert( (f_addr == 19) || (f_addr == 23 ) ); //if current instruction is 22, then next instruction must be at 19 or 23 (instruction address wraps from 22 to 19 if not self refresh, else 22 to 23)
end
else if(f_addr == 19) begin
assert(f_read == 22); //if next instruction is at 12, then current instruction must be at 15 (instruction address wraps from 15 to 12)
else if(f_addr == 19 || f_addr == 23) begin
assert(f_read == 22); //if next instruction is at 19 or 23, then current instruction must be at 22 (instruction address wraps from 22 to 19)
end
else if(f_read == 26) begin
assert(f_addr == 20); // if current instruction is 26 (exit self-refresh) then go to 20 (refresh)
end
else begin
assert(f_read + 1 == f_addr); //if there is no need to wrap around, then instruction address must increment
end
assert((f_read >= 19 && f_read <= 22) ); //refresh sequence is only on instruction address 19,20,21,22
assert((f_read >= 19 && f_read <= 26) ); //refresh sequence is only on instruction address 19,20,21,22
end
// reset_done must retain high when it was already asserted once
@ -3608,7 +3634,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(reset_done && f_read_inst[REF_IDLE]) begin
assert(f_read == 21);
end
end
end
@ -3621,9 +3647,18 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
assert( a[DELAY_COUNTER_WIDTH - 1:0] > 0);
end
end
// assertion on FSM calibration
always @* begin
if(instruction_address == 19 || instruction_address == 23) begin //pre-stall delay before precharge all to finish all remaining requests
if(pause_counter == 1) begin // if there are still pending requests (pause_counter high) then delay_counter should still be at PRE_REFRESH_DELAY
assert(delay_counter == PRE_REFRESH_DELAY);
end
end
if(instruction_address >= 24 && instruction_address < 26) begin
assert(!pause_counter); // no pause counter from precharge to sel-refresh entry
end
if(instruction_address < 13) begin
assert(state_calibrate == IDLE);
end
@ -3641,6 +3676,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(pause_counter) begin
assert(delay_counter != 0);
// will fix this soon
end
if(state_calibrate > ISSUE_WRITE_1 && state_calibrate <= ANALYZE_DATA) begin
@ -3936,10 +3972,10 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end
if(reset_done) begin
assert(cmd_d[PRECHARGE_SLOT][CMD_CKE] && cmd_d[PRECHARGE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[ACTIVATE_SLOT][CMD_CKE] && cmd_d[ACTIVATE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[READ_SLOT][CMD_CKE] && cmd_d[READ_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[WRITE_SLOT][CMD_CKE] && cmd_d[WRITE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[PRECHARGE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[ACTIVATE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[READ_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
assert(cmd_d[WRITE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
end
end
if(state_calibrate == DONE_CALIBRATE) begin
@ -3954,7 +3990,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(!f_empty) begin
assert(state_calibrate == DONE_CALIBRATE);
end
if(train_delay == 0 && state_calibrate == FINISH_READ) begin//remove
if(train_delay == 0 && state_calibrate == FINISH_READ) begin//fix this soon
assume(f_sum_of_pending_acks == 0);
end
end
@ -4099,6 +4135,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end
always @* begin
assert(f_bank_status == bank_status_q);
if(instruction_address >= 25) begin // after precharge until end of refresh, all banks are idle
assert(bank_status_q == 0);
end
if(instruction_address == 23 && pause_counter) begin // if at PRE_REFRESH_DELAY and not yet done, then delay_counter should still be at original value
end
end
(*keep*) reg[31:0] bank;
@ -4136,9 +4178,17 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
f_bank_status_2 = f_bank_status_2 | (1<<bank); //bank will be turned active
f_bank_active_row[bank] <= cmd_d[ACTIVATE_SLOT][CMD_ADDRESS_START:0]; //save row to be activated
end
if(instruction_address == 20 || instruction_address == 24) begin ///current instruction at precharge
//all banks will be in idle after refresh
for( index=0; index < (1<<BA_BITS); index=index+1) begin
f_bank_status_2[index] <= 0;
end
end
f_bank_status <= f_bank_status_2;
end
end
assign f_write_slot = WRITE_SLOT;
@ -4189,7 +4239,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end
always @* begin
if(instruction_address != 22 && instruction_address != 19) begin
if(instruction_address != 22 && instruction_address != 19 && instruction_address != 23) begin
assert(!stage1_pending && !stage2_pending); //must be pending except in tREFI and in prestall delay
end
@ -4390,7 +4440,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end
always @(posedge i_controller_clk) begin
if(f_past_valid) begin
if(instruction_address != 22 && instruction_address != 19 && $past(i_wb_cyc) && !past_sync_rst_controller) begin
if(instruction_address != 22 && instruction_address != 19 && instruction_address != 23 && $past(i_wb_cyc) && !past_sync_rst_controller) begin
assert(f_nreqs == $past(f_nreqs));
end
if(state_calibrate == DONE_CALIBRATE && $past(state_calibrate) != DONE_CALIBRATE && !past_sync_rst_controller) begin//just started DONE_CALBRATION
@ -4564,12 +4614,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
// extra assertions to make sure engine starts properly
always @* begin
//if(!past_sync_rst_controller) begin
assert(instruction_address <= 22);
assert(instruction_address <= 26);
assert(state_calibrate <= DONE_CALIBRATE);
if(!o_wb_stall) begin
assert(state_calibrate == DONE_CALIBRATE);
assert(instruction_address == 22 || (instruction_address == 19 && delay_counter == 0));
assert(instruction_address == 22 || (instruction_address == 19 && delay_counter == 0) || (instruction_address == 23));
end
if(instruction_address == 19 && delay_counter != 0 && state_calibrate == DONE_CALIBRATE) begin
@ -4580,7 +4630,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(stage1_pending || stage2_pending) begin
assert(state_calibrate > ISSUE_WRITE_1);
assert(instruction_address == 22 || instruction_address == 19);
assert(instruction_address == 22 || instruction_address == 19 || instruction_address == 23);
end
if(instruction_address < 13) begin
@ -4622,7 +4672,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
assert(o_wb_stall_calib);
end
if(reset_done) begin
assert(instruction_address >= 19 && instruction_address <= 22);
assert(instruction_address >= 19 && instruction_address <= 26);
end
//delay_counter is zero at first clock of new instruction address, the actual delay_clock wil start at next clock cycle
if(instruction_address == 19 && delay_counter != 0) begin

View File

@ -48,6 +48,7 @@ module ddr3_top #(
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[1:0] SELF_REFRESH = 2'b00, // 0 = use i_user_self_refresh input, 1 = Self-refresh mode is enabled after 64 controller clock cycles of no requests, 2 = 128 cycles, 3 = 256 cycles
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)
@ -210,6 +211,30 @@ ddr3_top #(
wire write_leveling_calib;
wire reset;
// logic for self-refresh
reg[8:0] refresh_counter = 0;
reg user_self_refresh;
// refresh counter
always @(posedge i_controller_clk) begin
if(i_wb_stb && i_wb_cyc) begin // if there is Wishbone request, then reset counter
refresh_counter <= 0;
end
else if(!o_wb_stall || user_self_refresh) begin // if no request (but not stalled) OR already on self-refresh, then increment counter
refresh_counter <= refresh_counter + 1;
end
end
// choose self-refresh options
always @* begin
case(SELF_REFRESH)
2'b00: user_self_refresh = i_user_self_refresh; // use input i_user_self_refresh (high = enter self-refresh, low = exit self-refresh)
2'b01: user_self_refresh = refresh_counter[6]; // Self-refresh mode is enabled after 64 controller clock cycles of no requests, then exit Self-refresh after another 64 controller clk cycles
2'b10: user_self_refresh = refresh_counter[7]; // Self-refresh mode is enabled after 128 controller clock cycles of no requests, then exit Self-refresh after another 128 controller clk cycles
2'b11: user_self_refresh = refresh_counter[8]; // Self-refresh mode is enabled after 256 controller clock cycles of no requests, then exit Self-refresh after another 256 controller clk cycles
endcase
end
//module instantiations
ddr3_controller #(
.CONTROLLER_CLK_PERIOD(CONTROLLER_CLK_PERIOD), //ps, clock period of the controller interface
@ -288,7 +313,7 @@ ddr3_top #(
// .o_debug2(o_debug2),
// .o_debug3(o_debug3)
// User enabled self-refresh
.i_user_self_refresh(i_user_self_refresh)
.i_user_self_refresh(user_self_refresh)
);
ddr3_phy #(
@ -348,4 +373,3 @@ ddr3_top #(
);
endmodule

View File

@ -64,7 +64,8 @@ module ddr3_dimm_micron_sim;
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
ECC_ENABLE = 0; // ECC enable
ECC_ENABLE = 0, // ECC enable
SELF_REFRESH = 2'b11;
reg i_controller_clk, i_ddr3_clk, i_ref_clk, i_ddr3_clk_90;
reg i_rst_n;
@ -164,7 +165,9 @@ ddr3_top #(
.ODELAY_SUPPORTED(ODELAY_SUPPORTED), //set to 1 if ODELAYE2 is supported
.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)
.WB_ERROR(1), // set to 1 to support Wishbone error (asserts at ECC double bit error)
.SKIP_INTERNAL_TEST(0), // skip built-in self test (would require >2 seconds of internal test right after calibration)
.SELF_REFRESH(SELF_REFRESH) // 0 = use i_user_self_refresh input, 1 = Self-refresh mode is enabled after 64 controller clock cycles of no requests, 2 = 128 cycles, 3 = 256 cycles
) ddr3_top
(
//clock and reset
@ -344,7 +347,11 @@ ddr3_top #(
i_rst_n <= 1;
end
wait(ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE);
// test self refresh after calibration
// test self refresh
self_refresh();
// test 1 phase 1: Write random word sequentially
// write to row 1
number_of_op <= 0;
@ -382,8 +389,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// test self refresh
self_refresh();
//Read sequentially
address <= start_address;
@ -409,7 +416,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// test self refresh
self_refresh();
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",
@ -456,7 +464,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// test self refresh
self_refresh();
// Read sequentially
address <= start_address;
@ -482,7 +491,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// test self refresh
self_refresh();
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",
@ -526,7 +536,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// test self refresh
self_refresh();
// Read sequentially
address <= start_address;
@ -558,15 +569,14 @@ ddr3_top #(
// i_wb_stb <= 0;
// end
// end
#1000_000; //rest here
// test self refresh
self_refresh();
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;
// Test 2:Random Access
// write randomly
address <= random_start; //this will just be used as the seed to generate a random number
@ -602,7 +612,9 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0;
end
end
#1000_000; //rest here
// test self refresh
self_refresh();
// Read sequentially
// Read the random words written at the random addresses
@ -639,8 +651,10 @@ ddr3_top #(
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));
#100_000;
// test self refresh
self_refresh();
// Test 3: Read from wishbone 2 (PHY)
// Wishbone 2
i_wb2_cyc <= 0; //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
@ -699,7 +713,11 @@ ddr3_top #(
end
end
#1000_000;
#1000_000; //rest here
// test self refresh
self_refresh();
#1000_000; // rest
$display("\n\n------- SUMMARY -------\nNumber of Writes = %0d\nNumber of Reads = %0d\nNumber of Success = %0d\nNumber of Fails = %0d\nNumber of Injected Errors = %0d\n",
number_of_writes, number_of_reads,number_of_successful, number_of_failed, number_of_injected_errors);
$display("\n\nTEST CALIBRATION\n[-]: write_test_address_counter = %0d", ddr3_top.ddr3_controller_inst.write_test_address_counter);
@ -709,6 +727,20 @@ ddr3_top #(
$stop;
end
task self_refresh;
if(SELF_REFRESH == 2'b00) begin
// test self refresh
@(posedge i_controller_clk)
i_user_self_refresh = 1;
#40_000_000; //40_000 ns of self-refresh
@(posedge i_controller_clk)
i_user_self_refresh = 0;
end
else begin
#10_000_000; // 10_000 ns of rest
end
endtask
//check read data
initial begin
start_read_address = 0; //start at first row
@ -988,4 +1020,3 @@ ddr3_top #(
*/
endmodule

View File

@ -11,15 +11,15 @@
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="749.583 ns"></ZoomStartTime>
<ZoomEndTime time="6,229.584 ns"></ZoomEndTime>
<Cursor1Time time="1,130.000 ns"></Cursor1Time>
<ZoomStartTime time="0.000000 us"></ZoomStartTime>
<ZoomEndTime time="55.000001 us"></ZoomEndTime>
<Cursor1Time time="33.460000 us"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="272"></NameColumnWidth>
<ValueColumnWidth column_width="129"></ValueColumnWidth>
<ValueColumnWidth column_width="125"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="47" />
<WVObjectSize size="52" />
<wvobject fp_name="divider869" type="divider">
<obj_property name="label">Clocks and Reset</obj_property>
<obj_property name="DisplayName">label</obj_property>
@ -45,16 +45,37 @@
<obj_property name="ObjectShortName">i_ref_clk</obj_property>
</wvobject>
<wvobject fp_name="divider869" type="divider">
<obj_property name="label">Calibration</obj_property>
<obj_property name="label">Self-refresh</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 type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_controller_inst/i_user_self_refresh">
<obj_property name="ElementShortName">i_user_self_refresh</obj_property>
<obj_property name="ObjectShortName">i_user_self_refresh</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 type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/ddr3_controller_inst/user_self_refresh_q">
<obj_property name="ElementShortName">user_self_refresh_q</obj_property>
<obj_property name="ObjectShortName">user_self_refresh_q</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/o_ddr3_cke">
<obj_property name="ElementShortName">o_ddr3_cke</obj_property>
<obj_property name="ObjectShortName">o_ddr3_cke</obj_property>
</wvobject>
<wvobject type="array" fp_name="/ddr3_dimm_micron_sim/ddr3_top/refresh_counter">
<obj_property name="ElementShortName">refresh_counter[8:0]</obj_property>
<obj_property name="ObjectShortName">refresh_counter[8:0]</obj_property>
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/o_wb_stall">
<obj_property name="ElementShortName">o_wb_stall</obj_property>
<obj_property name="ObjectShortName">o_wb_stall</obj_property>
</wvobject>
<wvobject type="logic" fp_name="/ddr3_dimm_micron_sim/ddr3_top/i_wb_stb">
<obj_property name="ElementShortName">i_wb_stb</obj_property>
<obj_property name="ObjectShortName">i_wb_stb</obj_property>
</wvobject>
<wvobject fp_name="divider869" type="divider">
<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/initial_calibration_done">
<obj_property name="ElementShortName">initial_calibration_done</obj_property>