Merge pull request #17 from AngeloJacobo/self_refresh_feature

Add self refresh feature (passing simulation, formal, and hardware test)
This commit is contained in:
Angelo Jacobo 2024-11-25 17:48:54 +08:00 committed by GitHub
commit 29ce61bcac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 401 additions and 112 deletions

View File

@ -49,6 +49,7 @@ module ddr3_top_axi #(
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] 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[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[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 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 ) 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) serdes_ratio = 4, // this controller is fixed as a 4:1 memory controller (CONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD = 4)
@ -130,11 +131,14 @@ module ddr3_top_axi #(
output wire o_calib_complete, output wire o_calib_complete,
// //
// Debug outputs // Debug outputs
output wire[31:0] o_debug1 output wire[31:0] o_debug1,
// output wire[31:0] o_debug2, // output wire[31:0] o_debug2,
// output wire[31:0] o_debug3, // output wire[31:0] o_debug3,
// output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_p, // output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_p,
// output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_n // output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_n
//
// User enabled self-refresh
input wire i_user_self_refresh
); );
wire wb_cyc; wire wb_cyc;
@ -165,7 +169,8 @@ ddr3_top #(
.SKIP_INTERNAL_TEST(SKIP_INTERNAL_TEST), // skip built-in self test (would require >2 seconds of internal test right after calibration) .SKIP_INTERNAL_TEST(SKIP_INTERNAL_TEST), // skip built-in self test (would require >2 seconds of internal test right after calibration)
.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 ) .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 )
.DIC(DIC), // Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing) .DIC(DIC), // Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing)
.RTT_NOM(RTT_NOM) //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) .RTT_NOM(RTT_NOM), //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)
.SELF_REFRESH(SELF_REFRESH) // Self-refresh options (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_inst ) ddr3_top_inst
( (
//clock and reset //clock and reset
@ -222,11 +227,13 @@ ddr3_top #(
.o_calib_complete(o_calib_complete), .o_calib_complete(o_calib_complete),
// //
// Debug outputs // Debug outputs
.o_debug1(o_debug1) .o_debug1(o_debug1),
// .o_debug2(o_debug2), // .o_debug2(o_debug2),
// .o_debug3(o_debug3), // .o_debug3(o_debug3),
// .o_ddr3_debug_read_dqs_p(o_ddr3_debug_read_dqs_p), // .o_ddr3_debug_read_dqs_p(o_ddr3_debug_read_dqs_p),
// .o_ddr3_debug_read_dqs_n(o_ddr3_debug_read_dqs_n) // .o_ddr3_debug_read_dqs_n(o_ddr3_debug_read_dqs_n)
//
.i_user_self_refresh(i_user_self_refresh)
//////////////////////////////////// ////////////////////////////////////
); );

View File

@ -135,9 +135,11 @@ module ddr3_controller #(
// Done Calibration pin // Done Calibration pin
output wire o_calib_complete, output wire o_calib_complete,
// Debug port // Debug port
output wire [31:0] o_debug1 output wire [31:0] o_debug1,
// output wire [31:0] o_debug2, // output wire [31:0] o_debug2,
// output wire [31:0] o_debug3 // output wire [31:0] o_debug3
// User enabled self-refresh
input wire i_user_self_refresh
); );
@ -150,8 +152,10 @@ module ddr3_controller #(
CMD_WR = 4'b0100, // Write (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8) CMD_WR = 4'b0100, // Write (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8)
CMD_RD = 4'b0101, //Read (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8) CMD_RD = 4'b0101, //Read (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8)
CMD_NOP = 4'b0111, // No Operation CMD_NOP = 4'b0111, // No Operation
CMD_ZQC = 4'b0110; // ZQ Calibration (A10-AP: 0 = ZQ Calibration Short, 1 = ZQ Calibration Long) CMD_ZQC = 4'b0110, // ZQ Calibration (A10-AP: 0 = ZQ Calibration Short, 1 = ZQ Calibration Long)
CMD_SREF_EN = 4'b0001,
CMD_SREF_XT = 4'b0111;
localparam RST_DONE = 27, // Command bit that determines if reset seqeunce had aready finished. non-persistent (only needs to be toggled once), localparam RST_DONE = 27, // Command bit that determines if reset seqeunce had aready finished. non-persistent (only needs to be toggled once),
REF_IDLE = 27, // No refresh is about to start and no ongoing refresh. (same bit as RST_DONE) REF_IDLE = 27, // No refresh is about to start and no ongoing refresh. (same bit as RST_DONE)
USE_TIMER = 26, // Command bit that determines if timer will be used (if delay is zero, USE_TIMER must be LOW) USE_TIMER = 26, // Command bit that determines if timer will be used (if delay is zero, USE_TIMER must be LOW)
@ -248,7 +252,11 @@ module ddr3_controller #(
localparam DELAY_MAX_VALUE = ps_to_cycles(INITIAL_CKE_LOW); //Largest possible delay needed by the reset and refresh sequence localparam DELAY_MAX_VALUE = ps_to_cycles(INITIAL_CKE_LOW); //Largest possible delay needed by the reset and refresh sequence
localparam DELAY_COUNTER_WIDTH= $clog2(DELAY_MAX_VALUE); //Bitwidth needed by the maximum possible delay, this will be the delay counter width localparam DELAY_COUNTER_WIDTH= $clog2(DELAY_MAX_VALUE); //Bitwidth needed by the maximum possible delay, this will be the delay counter width
localparam CALIBRATION_DELAY = 2; // must be >= 2 localparam CALIBRATION_DELAY = 2; // must be >= 2
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)+ 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
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
@ -481,7 +489,8 @@ module ddr3_controller #(
initial begin initial begin
o_phy_bitslip = 0; o_phy_bitslip = 0;
end end
reg cmd_odt_q = 0, cmd_odt, cmd_ck_en, cmd_reset_n; reg cmd_odt_q = 0, cmd_odt, cmd_reset_n;
(* mark_debug = "true" *) reg cmd_ck_en;
reg o_wb_stall_q = 1, o_wb_stall_d, o_wb_stall_calib = 1; reg o_wb_stall_q = 1, o_wb_stall_d, o_wb_stall_calib = 1;
reg precharge_slot_busy; reg precharge_slot_busy;
reg activate_slot_busy; reg activate_slot_busy;
@ -586,7 +595,8 @@ module ddr3_controller #(
wire db_err_o; wire db_err_o;
wire[wb_data_bits - 1:0] o_wb_data_q_decoded; wire[wb_data_bits - 1:0] o_wb_data_q_decoded;
/* verilator lint_on UNDRIVEN */ /* verilator lint_on UNDRIVEN */
reg user_self_refresh_q; // registered i_user_self_refresh
// initial block for all regs // initial block for all regs
initial begin initial begin
o_wb_stall = 1; o_wb_stall = 1;
@ -660,7 +670,7 @@ module ddr3_controller #(
else else
read_rom_instruction = {5'b01000 , CMD_NOP , ps_to_cycles(POWER_ON_RESET_HIGH)}; 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 //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: 5'd1:
if (MICRON_SIM) if (MICRON_SIM)
@ -727,7 +737,7 @@ module ddr3_controller #(
5'd18: read_rom_instruction = {5'b01011, CMD_NOP, tMOD[DELAY_SLOT_WIDTH-1:0]}; 5'd18: read_rom_instruction = {5'b01011, CMD_NOP, tMOD[DELAY_SLOT_WIDTH-1:0]};
//18. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES //18. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
// Perform first refresh and any subsequent refresh (so instruction 12 to 15 will be re-used for the refresh sequence) // Perform first refresh and any subsequent refresh (so instruction 19 to 22 will be re-used for the refresh sequence)
5'd19: read_rom_instruction = {5'b01111, CMD_PRE, ps_to_cycles(tRP)}; 5'd19: read_rom_instruction = {5'b01111, CMD_PRE, ps_to_cycles(tRP)};
//19. All banks must be precharged (A10-AP = high) and idle for a minimum of the precharge time tRP(min) before the Refresh Command can be applied. //19. All banks must be precharged (A10-AP = high) and idle for a minimum of the precharge time tRP(min) before the Refresh Command can be applied.
@ -740,7 +750,22 @@ module ddr3_controller #(
5'd22: read_rom_instruction = {5'b01011, CMD_NOP, PRE_REFRESH_DELAY[DELAY_SLOT_WIDTH-1:0]}; 5'd22: read_rom_instruction = {5'b01011, CMD_NOP, PRE_REFRESH_DELAY[DELAY_SLOT_WIDTH-1:0]};
// 22. Extra delay needed before starting the refresh sequence. // 22. Extra delay needed before starting the refresh sequence.
// (this already sets the wishbone stall high to make sure no user request is on-going when refresh seqeunce starts) // (this already sets the wishbone stall high to make sure no user request is on-going when refresh seqeunce starts)
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'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'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.
default: read_rom_instruction = {5'b00011, CMD_NOP, {(DELAY_SLOT_WIDTH){1'b0}}}; default: read_rom_instruction = {5'b00011, CMD_NOP, {(DELAY_SLOT_WIDTH){1'b0}}};
endcase endcase
@ -778,21 +803,45 @@ module ddr3_controller #(
//delay_counter is 1 (for r/w calibration and prestall delay) //delay_counter is 1 (for r/w calibration and prestall delay)
//address will only move forward for these kinds of delay only //address will only move forward for these kinds of delay only
//when skip_reset_seq_delay is toggled //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 //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. //now the next instruction. The same thing needs to be done when current instruction does not need the timer delay.
if(delay_counter == 1 || !instruction[USE_TIMER]/* || skip_reset_seq_delay*/) begin if(delay_counter == 1 || !instruction[USE_TIMER]/* || skip_reset_seq_delay*/) begin
delay_counter_is_zero <= 1; delay_counter_is_zero <= 1;
instruction <= read_rom_instruction(instruction_address); instruction <= read_rom_instruction(instruction_address);
instruction_address <= (instruction_address == 5'd22)? 5'd19:instruction_address+1; //wrap back of address to repeat refresh sequence 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'd26) begin // self-refresh exit always wraps back to 20 (Refresh)
instruction_address <= 5'd20;
end
else begin
instruction_address <= instruction_address + 5'd1; // just increment address
end
end end
//we are now on the middle of a delay //we are now on the middle of a delay
else delay_counter_is_zero <=0; else begin
delay_counter_is_zero <=0;
end
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
//instruction[RST_DONE] is non-persistent thus we need to register it once it goes high //instruction[RST_DONE] is non-persistent thus we need to register it once it goes high
reset_done <= instruction[RST_DONE]? 1'b1:reset_done; reset_done <= instruction[RST_DONE]? 1'b1:reset_done;
end end
end end
// 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'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
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
@ -879,7 +928,7 @@ module ddr3_controller #(
bank_active_row_q[index] <= bank_active_row_d[index]; bank_active_row_q[index] <= bank_active_row_d[index];
end 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; cmd_odt_q <= 1'b0;
//all banks will be in idle after refresh //all banks will be in idle after refresh
for( index=0; index < (1<<BA_BITS); index=index+1) begin for( index=0; index < (1<<BA_BITS); index=index+1) begin
@ -2567,6 +2616,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
DONE_CALIBRATE: begin DONE_CALIBRATE: begin
calib_stb <= 0; calib_stb <= 0;
state_calibrate <= DONE_CALIBRATE; state_calibrate <= DONE_CALIBRATE;
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 end
endcase endcase
@ -2581,7 +2636,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(odelay_data_cntvaluein[lane] == 15) begin if(odelay_data_cntvaluein[lane] == 15) begin
odelay_cntvalue_halfway <= 1; odelay_cntvalue_halfway <= 1;
end 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 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 //skip to instruction address 20 (precharge all before refresh) when no pending requests anymore
//toggle it for 1 clk cycle only //toggle it for 1 clk cycle only
@ -3463,9 +3518,24 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end end
//move the pipeline forward when counter is about to go zero and we are not yet at end of reset sequence //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 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; f_read <= f_addr;
end 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 end
// assert f_addr and f_read as shadows of next and current instruction address // assert f_addr and f_read as shadows of next and current instruction address
@ -3490,11 +3560,11 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end end
else if(f_past_valid) begin 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 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]); assert(delay_counter == f_read_inst[DELAY_COUNTER_WIDTH - 1:0]);
end end
//delay_counter_is_zero can be high when counter is zero and current instruction needs delay //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) ); assert( delay_counter_is_zero == (delay_counter == 0) );
end end
//delay_counter_is_zero will go high this cycle when we received a don't-use-timer instruction //delay_counter_is_zero will go high this cycle when we received a don't-use-timer instruction
@ -3511,12 +3581,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 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 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 assert(delay_counter < $past(delay_counter) ); //just to make sure delay_counter will never overflow back to all 1's
end end
//sanity checking for the comment "delay_counter will be zero AT NEXT CLOCK CYCLE when counter is now one" //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); assert(delay_counter == 0 && delay_counter_is_zero);
end end
//assert the relationship between the stages FOR RESET SEQUENCE //assert the relationship between the stages FOR RESET SEQUENCE
@ -3537,15 +3607,18 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
//assert the relationship between the stages FOR REFRESH SEQUENCE //assert the relationship between the stages FOR REFRESH SEQUENCE
else begin else begin
if(f_read == 22) 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 end
else if(f_addr == 19) begin else if(f_addr == 19 || f_addr == 23) 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) 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 end
else begin else begin
assert(f_read + 1 == f_addr); //if there is no need to wrap around, then instruction address must increment assert(f_read + 1 == f_addr); //if there is no need to wrap around, then instruction address must increment
end 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 end
// reset_done must retain high when it was already asserted once // reset_done must retain high when it was already asserted once
@ -3562,7 +3635,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(reset_done && f_read_inst[REF_IDLE]) begin if(reset_done && f_read_inst[REF_IDLE]) begin
assert(f_read == 21); assert(f_read == 21);
end end
end end
end end
@ -3575,9 +3648,18 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
assert( a[DELAY_COUNTER_WIDTH - 1:0] > 0); assert( a[DELAY_COUNTER_WIDTH - 1:0] > 0);
end end
end end
// assertion on FSM calibration // assertion on FSM calibration
always @* begin 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 if(instruction_address < 13) begin
assert(state_calibrate == IDLE); assert(state_calibrate == IDLE);
end end
@ -3595,6 +3677,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(pause_counter) begin if(pause_counter) begin
assert(delay_counter != 0); assert(delay_counter != 0);
// will fix this soon
end end
if(state_calibrate > ISSUE_WRITE_1 && state_calibrate <= ANALYZE_DATA) begin if(state_calibrate > ISSUE_WRITE_1 && state_calibrate <= ANALYZE_DATA) begin
@ -3890,10 +3973,10 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end end
if(reset_done) begin 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[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[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[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[WRITE_SLOT][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done
end end
end end
if(state_calibrate == DONE_CALIBRATE) begin if(state_calibrate == DONE_CALIBRATE) begin
@ -3908,7 +3991,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(!f_empty) begin if(!f_empty) begin
assert(state_calibrate == DONE_CALIBRATE); assert(state_calibrate == DONE_CALIBRATE);
end 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); assume(f_sum_of_pending_acks == 0);
end end
end end
@ -4053,6 +4136,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end end
always @* begin always @* begin
assert(f_bank_status == bank_status_q); 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 end
(*keep*) reg[31:0] bank; (*keep*) reg[31:0] bank;
@ -4090,9 +4179,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_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 f_bank_active_row[bank] <= cmd_d[ACTIVATE_SLOT][CMD_ADDRESS_START:0]; //save row to be activated
end 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; f_bank_status <= f_bank_status_2;
end end
end end
assign f_write_slot = WRITE_SLOT; assign f_write_slot = WRITE_SLOT;
@ -4143,7 +4240,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end end
always @* begin 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 assert(!stage1_pending && !stage2_pending); //must be pending except in tREFI and in prestall delay
end end
@ -4344,7 +4441,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
end end
always @(posedge i_controller_clk) begin always @(posedge i_controller_clk) begin
if(f_past_valid) 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)); assert(f_nreqs == $past(f_nreqs));
end end
if(state_calibrate == DONE_CALIBRATE && $past(state_calibrate) != DONE_CALIBRATE && !past_sync_rst_controller) begin//just started DONE_CALBRATION if(state_calibrate == DONE_CALIBRATE && $past(state_calibrate) != DONE_CALIBRATE && !past_sync_rst_controller) begin//just started DONE_CALBRATION
@ -4518,12 +4615,12 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
// extra assertions to make sure engine starts properly // extra assertions to make sure engine starts properly
always @* begin always @* begin
//if(!past_sync_rst_controller) begin //if(!past_sync_rst_controller) begin
assert(instruction_address <= 22); assert(instruction_address <= 26);
assert(state_calibrate <= DONE_CALIBRATE); assert(state_calibrate <= DONE_CALIBRATE);
if(!o_wb_stall) begin if(!o_wb_stall) begin
assert(state_calibrate == DONE_CALIBRATE); 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 end
if(instruction_address == 19 && delay_counter != 0 && state_calibrate == DONE_CALIBRATE) begin if(instruction_address == 19 && delay_counter != 0 && state_calibrate == DONE_CALIBRATE) begin
@ -4534,7 +4631,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
if(stage1_pending || stage2_pending) begin if(stage1_pending || stage2_pending) begin
assert(state_calibrate > ISSUE_WRITE_1); assert(state_calibrate > ISSUE_WRITE_1);
assert(instruction_address == 22 || instruction_address == 19); assert(instruction_address == 22 || instruction_address == 19 || instruction_address == 23);
end end
if(instruction_address < 13) begin if(instruction_address < 13) begin
@ -4576,7 +4673,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
assert(o_wb_stall_calib); assert(o_wb_stall_calib);
end end
if(reset_done) begin if(reset_done) begin
assert(instruction_address >= 19 && instruction_address <= 22); assert(instruction_address >= 19 && instruction_address <= 26);
end end
//delay_counter is zero at first clock of new instruction address, the actual delay_clock wil start at next clock cycle //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 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] 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[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[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 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 ) 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) serdes_ratio = 4, // this controller is fixed as a 4:1 memory controller (CONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD = 4)
@ -108,11 +109,14 @@ module ddr3_top #(
// Done Calibration pin // Done Calibration pin
output wire o_calib_complete, output wire o_calib_complete,
// Debug outputs // Debug outputs
output wire[31:0] o_debug1 output wire[31:0] o_debug1,
// output wire[31:0] o_debug2, // output wire[31:0] o_debug2,
// output wire[31:0] o_debug3, // output wire[31:0] o_debug3,
// output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_p, // output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_p,
// output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_n // output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_n
//
// User enabled self-refresh
input wire i_user_self_refresh
); );
// Instantiation Template (DEFAULT VALUE IS FOR ARTY S7) // Instantiation Template (DEFAULT VALUE IS FOR ARTY S7)
@ -207,6 +211,30 @@ ddr3_top #(
wire write_leveling_calib; wire write_leveling_calib;
wire reset; 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 //module instantiations
ddr3_controller #( ddr3_controller #(
.CONTROLLER_CLK_PERIOD(CONTROLLER_CLK_PERIOD), //ps, clock period of the controller interface .CONTROLLER_CLK_PERIOD(CONTROLLER_CLK_PERIOD), //ps, clock period of the controller interface
@ -281,9 +309,11 @@ ddr3_top #(
// Done Calibration pin // Done Calibration pin
.o_calib_complete(o_calib_complete), .o_calib_complete(o_calib_complete),
// Debug outputs // Debug outputs
.o_debug1(o_debug1) .o_debug1(o_debug1),
// .o_debug2(o_debug2), // .o_debug2(o_debug2),
// .o_debug3(o_debug3) // .o_debug3(o_debug3)
// User enabled self-refresh
.i_user_self_refresh(user_self_refresh)
); );
ddr3_phy #( ddr3_phy #(
@ -341,6 +371,29 @@ ddr3_top #(
.o_ddr3_debug_read_dqs_p(/*o_ddr3_debug_read_dqs_p*/), .o_ddr3_debug_read_dqs_p(/*o_ddr3_debug_read_dqs_p*/),
.o_ddr3_debug_read_dqs_n(/*o_ddr3_debug_read_dqs_n*/) .o_ddr3_debug_read_dqs_n(/*o_ddr3_debug_read_dqs_n*/)
); );
endmodule
// display value of parameters for easy debugging
initial begin
$display("\nDDR3 TOP PARAMETERS:\n-----------------------------");
$display("CONTROLLER_CLK_PERIOD = %0d", CONTROLLER_CLK_PERIOD);
$display("DDR3_CLK_PERIOD = %0d", DDR3_CLK_PERIOD);
$display("ROW_BITS = %0d", ROW_BITS);
$display("COL_BITS = %0d", COL_BITS);
$display("BA_BITS = %0d", BA_BITS);
$display("BYTE_LANES = %0d", BYTE_LANES);
$display("AUX_WIDTH = %0d", AUX_WIDTH);
$display("WB2_ADDR_BITS = %0d", WB2_ADDR_BITS);
$display("WB2_DATA_BITS = %0d", WB2_DATA_BITS);
$display("MICRON_SIM = %0d", MICRON_SIM);
$display("ODELAY_SUPPORTED = %0d", ODELAY_SUPPORTED);
$display("SECOND_WISHBONE = %0d", SECOND_WISHBONE);
$display("WB_ERROR = %0d", WB_ERROR);
$display("SKIP_INTERNAL_TEST = %0d", SKIP_INTERNAL_TEST);
$display("ECC_ENABLE = %0d", ECC_ENABLE);
$display("DIC = %0d", DIC);
$display("RTT_NOM = %0d", RTT_NOM);
$display("SELF_REFRESH = %0d", SELF_REFRESH);
$display("End of DDR3 TOP PARAMETERS\n-----------------------------");
end
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 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 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 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_controller_clk, i_ddr3_clk, i_ref_clk, i_ddr3_clk_90;
reg i_rst_n; reg i_rst_n;
@ -107,7 +108,8 @@ module ddr3_dimm_micron_sim;
wire o_wb2_stall; //1 = busy, cannot accept requests wire o_wb2_stall; //1 = busy, cannot accept requests
wire o_wb2_ack; //1 = read/write request has completed wire o_wb2_ack; //1 = read/write request has completed
wire[$bits(ddr3_top.o_wb2_data)-1:0] o_wb2_data; //read data wire[$bits(ddr3_top.o_wb2_data)-1:0] o_wb2_data; //read data
// User enabled self-refresh
reg i_user_self_refresh;
wire clk_locked; wire clk_locked;
`ifdef USE_CLOCK_WIZARD `ifdef USE_CLOCK_WIZARD
@ -163,7 +165,9 @@ ddr3_top #(
.ODELAY_SUPPORTED(ODELAY_SUPPORTED), //set to 1 if ODELAYE2 is supported .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 ) .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 ) ddr3_top
( (
//clock and reset //clock and reset
@ -211,9 +215,9 @@ ddr3_top #(
.io_ddr3_dq(dq), .io_ddr3_dq(dq),
.io_ddr3_dqs(dqs), .io_ddr3_dqs(dqs),
.io_ddr3_dqs_n(dqs_n), .io_ddr3_dqs_n(dqs_n),
.o_ddr3_dm(ddr3_dm) .o_ddr3_dm(ddr3_dm),
// User enabled self-refresh
//////////////////////////////////// .i_user_self_refresh(i_user_self_refresh)
); );
@ -318,6 +322,7 @@ ddr3_top #(
integer average_1, average_2, average_3, average_4; 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 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 initial begin
i_user_self_refresh = 0;
//toggle reset for 1 slow clk //toggle reset for 1 slow clk
@(posedge i_controller_clk) begin @(posedge i_controller_clk) begin
i_rst_n <= 0; i_rst_n <= 0;
@ -342,7 +347,11 @@ ddr3_top #(
i_rst_n <= 1; i_rst_n <= 1;
end end
wait(ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE); 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 // test 1 phase 1: Write random word sequentially
// write to row 1 // write to row 1
number_of_op <= 0; number_of_op <= 0;
@ -380,8 +389,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0; if (!o_wb_stall) i_wb_stb <= 1'b0;
end end
end end
#1000_000; //rest here // test self refresh
self_refresh();
//Read sequentially //Read sequentially
address <= start_address; address <= start_address;
@ -407,7 +416,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0; if (!o_wb_stall) i_wb_stb <= 1'b0;
end end
end end
#1000_000; //rest here // test self refresh
self_refresh();
average_1 = ($time-time_started)/(number_of_op*1000); 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", $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",
@ -454,7 +464,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0; if (!o_wb_stall) i_wb_stb <= 1'b0;
end end
end end
#1000_000; //rest here // test self refresh
self_refresh();
// Read sequentially // Read sequentially
address <= start_address; address <= start_address;
@ -480,7 +491,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0; if (!o_wb_stall) i_wb_stb <= 1'b0;
end end
end end
#1000_000; //rest here // test self refresh
self_refresh();
average_2 = ($time-time_started)/(number_of_op*1000); 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", $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",
@ -524,7 +536,8 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0; if (!o_wb_stall) i_wb_stb <= 1'b0;
end end
end end
#1000_000; //rest here // test self refresh
self_refresh();
// Read sequentially // Read sequentially
address <= start_address; address <= start_address;
@ -556,15 +569,14 @@ ddr3_top #(
// i_wb_stb <= 0; // i_wb_stb <= 0;
// end // end
// end // end
#1000_000; //rest here // test self refresh
self_refresh();
average_3 = ($time-time_started)/(number_of_op*1000); 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", $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)); number_of_op,time_started/1000, $time/1000, ($time-time_started)/(number_of_op*1000));
//#100_000; //#100_000;
// Test 2:Random Access // Test 2:Random Access
// write randomly // write randomly
address <= random_start; //this will just be used as the seed to generate a random number address <= random_start; //this will just be used as the seed to generate a random number
@ -600,7 +612,9 @@ ddr3_top #(
if (!o_wb_stall) i_wb_stb <= 1'b0; if (!o_wb_stall) i_wb_stb <= 1'b0;
end end
end end
#1000_000; //rest here
// test self refresh
self_refresh();
// Read sequentially // Read sequentially
// Read the random words written at the random addresses // Read the random words written at the random addresses
@ -637,8 +651,10 @@ ddr3_top #(
average_4 = ($time-time_started)/(number_of_op*1000); 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", $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)); 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) // Test 3: Read from wishbone 2 (PHY)
// Wishbone 2 // Wishbone 2
i_wb2_cyc <= 0; //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled) i_wb2_cyc <= 0; //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
@ -697,7 +713,11 @@ ddr3_top #(
end end
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", $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); 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); $display("\n\nTEST CALIBRATION\n[-]: write_test_address_counter = %0d", ddr3_top.ddr3_controller_inst.write_test_address_counter);
@ -707,6 +727,20 @@ ddr3_top #(
$stop; $stop;
end 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 //check read data
initial begin initial begin
start_read_address = 0; //start at first row start_read_address = 0; //start at first row
@ -986,4 +1020,3 @@ ddr3_top #(
*/ */
endmodule endmodule

View File

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

View File

@ -311,28 +311,6 @@
</spirit:portMap> </spirit:portMap>
</spirit:portMaps> </spirit:portMaps>
</spirit:busInterface> </spirit:busInterface>
<spirit:busInterface>
<spirit:name>i_rst_n</spirit:name>
<spirit:busType spirit:vendor="xilinx.com" spirit:library="signal" spirit:name="reset" spirit:version="1.0"/>
<spirit:abstractionType spirit:vendor="xilinx.com" spirit:library="signal" spirit:name="reset_rtl" spirit:version="1.0"/>
<spirit:slave/>
<spirit:portMaps>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>RST</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>i_rst_n</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
</spirit:portMaps>
<spirit:parameters>
<spirit:parameter>
<spirit:name>POLARITY</spirit:name>
<spirit:value spirit:id="BUSIFPARAM_VALUE.I_RST_N.POLARITY" spirit:choiceRef="choice_list_9d8b0d81">ACTIVE_LOW</spirit:value>
</spirit:parameter>
</spirit:parameters>
</spirit:busInterface>
<spirit:busInterface> <spirit:busInterface>
<spirit:name>i_controller_clk</spirit:name> <spirit:name>i_controller_clk</spirit:name>
<spirit:busType spirit:vendor="xilinx.com" spirit:library="signal" spirit:name="clock" spirit:version="1.0"/> <spirit:busType spirit:vendor="xilinx.com" spirit:library="signal" spirit:name="clock" spirit:version="1.0"/>
@ -387,6 +365,28 @@
</spirit:portMap> </spirit:portMap>
</spirit:portMaps> </spirit:portMaps>
</spirit:busInterface> </spirit:busInterface>
<spirit:busInterface>
<spirit:name>i_rst_n</spirit:name>
<spirit:busType spirit:vendor="xilinx.com" spirit:library="signal" spirit:name="reset" spirit:version="1.0"/>
<spirit:abstractionType spirit:vendor="xilinx.com" spirit:library="signal" spirit:name="reset_rtl" spirit:version="1.0"/>
<spirit:slave/>
<spirit:portMaps>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>RST</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>i_rst_n</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
</spirit:portMaps>
<spirit:parameters>
<spirit:parameter>
<spirit:name>POLARITY</spirit:name>
<spirit:value spirit:id="BUSIFPARAM_VALUE.I_RST_N.POLARITY" spirit:choiceRef="choice_list_9d8b0d81">ACTIVE_LOW</spirit:value>
</spirit:parameter>
</spirit:parameters>
</spirit:busInterface>
<spirit:busInterface> <spirit:busInterface>
<spirit:name>ddr3</spirit:name> <spirit:name>ddr3</spirit:name>
<spirit:displayName>ddr3</spirit:displayName> <spirit:displayName>ddr3</spirit:displayName>
@ -561,7 +561,7 @@
<spirit:parameters> <spirit:parameters>
<spirit:parameter> <spirit:parameter>
<spirit:name>viewChecksum</spirit:name> <spirit:name>viewChecksum</spirit:name>
<spirit:value>e9f63973</spirit:value> <spirit:value>1dea7b87</spirit:value>
</spirit:parameter> </spirit:parameter>
</spirit:parameters> </spirit:parameters>
</spirit:view> </spirit:view>
@ -577,7 +577,7 @@
<spirit:parameters> <spirit:parameters>
<spirit:parameter> <spirit:parameter>
<spirit:name>viewChecksum</spirit:name> <spirit:name>viewChecksum</spirit:name>
<spirit:value>e9f63973</spirit:value> <spirit:value>1dea7b87</spirit:value>
</spirit:parameter> </spirit:parameter>
</spirit:parameters> </spirit:parameters>
</spirit:view> </spirit:view>
@ -591,7 +591,7 @@
<spirit:parameters> <spirit:parameters>
<spirit:parameter> <spirit:parameter>
<spirit:name>viewChecksum</spirit:name> <spirit:name>viewChecksum</spirit:name>
<spirit:value>30e22270</spirit:value> <spirit:value>ce7b9cf6</spirit:value>
</spirit:parameter> </spirit:parameter>
</spirit:parameters> </spirit:parameters>
</spirit:view> </spirit:view>
@ -1578,6 +1578,29 @@
</spirit:wireTypeDefs> </spirit:wireTypeDefs>
</spirit:wire> </spirit:wire>
</spirit:port> </spirit:port>
<spirit:port>
<spirit:name>i_user_self_refresh</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>wire</spirit:typeName>
<spirit:viewNameRef>xilinx_anylanguagesynthesis</spirit:viewNameRef>
<spirit:viewNameRef>xilinx_anylanguagebehavioralsimulation</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
<spirit:driver>
<spirit:defaultValue spirit:format="long">0</spirit:defaultValue>
</spirit:driver>
</spirit:wire>
<spirit:vendorExtensions>
<xilinx:portInfo>
<xilinx:enablement>
<xilinx:isEnabled xilinx:resolve="dependent" xilinx:id="PORT_ENABLEMENT.i_user_self_refresh" xilinx:dependency="$SELF_REFRESH = 0">true</xilinx:isEnabled>
</xilinx:enablement>
</xilinx:portInfo>
</spirit:vendorExtensions>
</spirit:port>
</spirit:ports> </spirit:ports>
<spirit:modelParameters> <spirit:modelParameters>
<spirit:modelParameter xsi:type="spirit:nameValueTypeType" spirit:dataType="integer"> <spirit:modelParameter xsi:type="spirit:nameValueTypeType" spirit:dataType="integer">
@ -1655,6 +1678,11 @@
<spirit:displayName>Ecc Enable</spirit:displayName> <spirit:displayName>Ecc Enable</spirit:displayName>
<spirit:value spirit:format="long" spirit:resolve="generated" spirit:id="MODELPARAM_VALUE.ECC_ENABLE">0</spirit:value> <spirit:value spirit:format="long" spirit:resolve="generated" spirit:id="MODELPARAM_VALUE.ECC_ENABLE">0</spirit:value>
</spirit:modelParameter> </spirit:modelParameter>
<spirit:modelParameter spirit:dataType="integer">
<spirit:name>SELF_REFRESH</spirit:name>
<spirit:displayName>Self-Refresh</spirit:displayName>
<spirit:value spirit:format="long" spirit:resolve="generated" spirit:id="MODELPARAM_VALUE.SELF_REFRESH">0</spirit:value>
</spirit:modelParameter>
<spirit:modelParameter spirit:dataType="integer"> <spirit:modelParameter spirit:dataType="integer">
<spirit:name>DIC</spirit:name> <spirit:name>DIC</spirit:name>
<spirit:displayName>Dic</spirit:displayName> <spirit:displayName>Dic</spirit:displayName>
@ -1723,6 +1751,20 @@
<spirit:enumeration>ACTIVE_HIGH</spirit:enumeration> <spirit:enumeration>ACTIVE_HIGH</spirit:enumeration>
<spirit:enumeration>ACTIVE_LOW</spirit:enumeration> <spirit:enumeration>ACTIVE_LOW</spirit:enumeration>
</spirit:choice> </spirit:choice>
<spirit:choice>
<spirit:name>choice_pairs_933dc0fc</spirit:name>
<spirit:enumeration spirit:text="0 (ECC DIsabled)">0</spirit:enumeration>
<spirit:enumeration spirit:text="1 (Side-band ECC per burst)">1</spirit:enumeration>
<spirit:enumeration spirit:text="2 (Side-band ECC per 8 bursts)">2</spirit:enumeration>
<spirit:enumeration spirit:text="3 (Inline ECC)">3</spirit:enumeration>
</spirit:choice>
<spirit:choice>
<spirit:name>choice_pairs_96a879b9</spirit:name>
<spirit:enumeration spirit:text="0 (Enable self-refresh based on i_user_self_refresh)">0</spirit:enumeration>
<spirit:enumeration spirit:text="1 (Enable self-refresh after 64 clock cycles of inactivity)">1</spirit:enumeration>
<spirit:enumeration spirit:text="2 (Enable self-refresh after 128 clock cycles of inactivity)">2</spirit:enumeration>
<spirit:enumeration spirit:text="3 (Enable self-refresh after 256 clock cycles of inactivity)">3</spirit:enumeration>
</spirit:choice>
</spirit:choices> </spirit:choices>
<spirit:fileSets> <spirit:fileSets>
<spirit:fileSet> <spirit:fileSet>
@ -1778,7 +1820,7 @@
<spirit:file> <spirit:file>
<spirit:name>../rtl/axi/ddr3_top_axi.v</spirit:name> <spirit:name>../rtl/axi/ddr3_top_axi.v</spirit:name>
<spirit:fileType>verilogSource</spirit:fileType> <spirit:fileType>verilogSource</spirit:fileType>
<spirit:userFileType>CHECKSUM_4123fcc3</spirit:userFileType> <spirit:userFileType>CHECKSUM_f4e2d855</spirit:userFileType>
</spirit:file> </spirit:file>
</spirit:fileSet> </spirit:fileSet>
<spirit:fileSet> <spirit:fileSet>
@ -1841,7 +1883,7 @@
<spirit:file> <spirit:file>
<spirit:name>xgui/uberddr3_axi_v1_0.tcl</spirit:name> <spirit:name>xgui/uberddr3_axi_v1_0.tcl</spirit:name>
<spirit:fileType>tclSource</spirit:fileType> <spirit:fileType>tclSource</spirit:fileType>
<spirit:userFileType>CHECKSUM_30e22270</spirit:userFileType> <spirit:userFileType>CHECKSUM_ce7b9cf6</spirit:userFileType>
<spirit:userFileType>XGUI_VERSION_2</spirit:userFileType> <spirit:userFileType>XGUI_VERSION_2</spirit:userFileType>
</spirit:file> </spirit:file>
</spirit:fileSet> </spirit:fileSet>
@ -1935,7 +1977,7 @@
<spirit:parameter> <spirit:parameter>
<spirit:name>ECC_ENABLE</spirit:name> <spirit:name>ECC_ENABLE</spirit:name>
<spirit:displayName>ECC Enable</spirit:displayName> <spirit:displayName>ECC Enable</spirit:displayName>
<spirit:value spirit:format="long" spirit:resolve="user" spirit:id="PARAM_VALUE.ECC_ENABLE" spirit:minimum="0" spirit:maximum="3" spirit:rangeType="long">0</spirit:value> <spirit:value spirit:format="long" spirit:resolve="user" spirit:id="PARAM_VALUE.ECC_ENABLE" spirit:choiceRef="choice_pairs_933dc0fc">0</spirit:value>
</spirit:parameter> </spirit:parameter>
<spirit:parameter> <spirit:parameter>
<spirit:name>DIC</spirit:name> <spirit:name>DIC</spirit:name>
@ -2057,6 +2099,11 @@
<spirit:name>Component_Name</spirit:name> <spirit:name>Component_Name</spirit:name>
<spirit:value spirit:resolve="user" spirit:id="PARAM_VALUE.Component_Name" spirit:order="1">uberddr3_axi_v1_0</spirit:value> <spirit:value spirit:resolve="user" spirit:id="PARAM_VALUE.Component_Name" spirit:order="1">uberddr3_axi_v1_0</spirit:value>
</spirit:parameter> </spirit:parameter>
<spirit:parameter>
<spirit:name>SELF_REFRESH</spirit:name>
<spirit:displayName>Self-Refresh</spirit:displayName>
<spirit:value spirit:resolve="user" spirit:id="PARAM_VALUE.SELF_REFRESH" spirit:choiceRef="choice_pairs_96a879b9">0</spirit:value>
</spirit:parameter>
</spirit:parameters> </spirit:parameters>
<spirit:vendorExtensions> <spirit:vendorExtensions>
<xilinx:coreExtensions> <xilinx:coreExtensions>
@ -2090,20 +2137,20 @@
<xilinx:displayName>uberddr3_axi_v1_0</xilinx:displayName> <xilinx:displayName>uberddr3_axi_v1_0</xilinx:displayName>
<xilinx:definitionSource>package_project</xilinx:definitionSource> <xilinx:definitionSource>package_project</xilinx:definitionSource>
<xilinx:vendorURL>https://github.com/AngeloJacobo/UberDDR3</xilinx:vendorURL> <xilinx:vendorURL>https://github.com/AngeloJacobo/UberDDR3</xilinx:vendorURL>
<xilinx:coreRevision>9</xilinx:coreRevision> <xilinx:coreRevision>11</xilinx:coreRevision>
<xilinx:coreCreationDateTime>2024-10-19T05:33:11Z</xilinx:coreCreationDateTime> <xilinx:coreCreationDateTime>2024-11-24T08:00:34Z</xilinx:coreCreationDateTime>
<xilinx:tags> <xilinx:tags>
<xilinx:tag xilinx:name="nopcore"/> <xilinx:tag xilinx:name="nopcore"/>
</xilinx:tags> </xilinx:tags>
</xilinx:coreExtensions> </xilinx:coreExtensions>
<xilinx:packagingInfo> <xilinx:packagingInfo>
<xilinx:xilinxVersion>2022.1</xilinx:xilinxVersion> <xilinx:xilinxVersion>2022.1</xilinx:xilinxVersion>
<xilinx:checksum xilinx:scope="busInterfaces" xilinx:value="a8e6cc4e"/> <xilinx:checksum xilinx:scope="busInterfaces" xilinx:value="6c0c2bc0"/>
<xilinx:checksum xilinx:scope="memoryMaps" xilinx:value="cd65c31e"/> <xilinx:checksum xilinx:scope="memoryMaps" xilinx:value="cd65c31e"/>
<xilinx:checksum xilinx:scope="fileGroups" xilinx:value="68e3a14b"/> <xilinx:checksum xilinx:scope="fileGroups" xilinx:value="ba5aba03"/>
<xilinx:checksum xilinx:scope="ports" xilinx:value="a969876f"/> <xilinx:checksum xilinx:scope="ports" xilinx:value="abd96048"/>
<xilinx:checksum xilinx:scope="hdlParameters" xilinx:value="86f21185"/> <xilinx:checksum xilinx:scope="hdlParameters" xilinx:value="86f21185"/>
<xilinx:checksum xilinx:scope="parameters" xilinx:value="17670e8c"/> <xilinx:checksum xilinx:scope="parameters" xilinx:value="5574e240"/>
</xilinx:packagingInfo> </xilinx:packagingInfo>
</spirit:vendorExtensions> </spirit:vendorExtensions>
</spirit:component> </spirit:component>

View File

@ -15,6 +15,7 @@ proc init_gui { IPINST } {
ipgui::add_param $IPINST -name "DIC" -parent ${Page_0} ipgui::add_param $IPINST -name "DIC" -parent ${Page_0}
ipgui::add_param $IPINST -name "DQ_BITS" -parent ${Page_0} ipgui::add_param $IPINST -name "DQ_BITS" -parent ${Page_0}
ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0} ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0}
ipgui::add_param $IPINST -name "SELF_REFRESH" -parent ${Page_0}
ipgui::add_param $IPINST -name "MICRON_SIM" -parent ${Page_0} ipgui::add_param $IPINST -name "MICRON_SIM" -parent ${Page_0}
ipgui::add_param $IPINST -name "ODELAY_SUPPORTED" -parent ${Page_0} ipgui::add_param $IPINST -name "ODELAY_SUPPORTED" -parent ${Page_0}
ipgui::add_param $IPINST -name "ROW_BITS" -parent ${Page_0} ipgui::add_param $IPINST -name "ROW_BITS" -parent ${Page_0}
@ -142,6 +143,15 @@ proc validate_PARAM_VALUE.ECC_ENABLE { PARAM_VALUE.ECC_ENABLE } {
return true return true
} }
proc update_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } {
# Procedure called to update SELF_REFRESH when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } {
# Procedure called to validate SELF_REFRESH
return true
}
proc update_PARAM_VALUE.MICRON_SIM { PARAM_VALUE.MICRON_SIM } { proc update_PARAM_VALUE.MICRON_SIM { PARAM_VALUE.MICRON_SIM } {
# Procedure called to update MICRON_SIM when any of the dependent parameters in the arguments change # Procedure called to update MICRON_SIM when any of the dependent parameters in the arguments change
} }
@ -353,6 +363,11 @@ proc update_MODELPARAM_VALUE.ECC_ENABLE { MODELPARAM_VALUE.ECC_ENABLE PARAM_VALU
set_property value [get_property value ${PARAM_VALUE.ECC_ENABLE}] ${MODELPARAM_VALUE.ECC_ENABLE} set_property value [get_property value ${PARAM_VALUE.ECC_ENABLE}] ${MODELPARAM_VALUE.ECC_ENABLE}
} }
proc update_MODELPARAM_VALUE.SELF_REFRESH { MODELPARAM_VALUE.SELF_REFRESH PARAM_VALUE.SELF_REFRESH } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.SELF_REFRESH}] ${MODELPARAM_VALUE.SELF_REFRESH}
}
proc update_MODELPARAM_VALUE.DIC { MODELPARAM_VALUE.DIC PARAM_VALUE.DIC } { proc update_MODELPARAM_VALUE.DIC { MODELPARAM_VALUE.DIC PARAM_VALUE.DIC } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.DIC}] ${MODELPARAM_VALUE.DIC} set_property value [get_property value ${PARAM_VALUE.DIC}] ${MODELPARAM_VALUE.DIC}

View File

@ -19,8 +19,10 @@ proc init_gui { IPINST } {
set_property tooltip {Width of bank address} ${BA_BITS} set_property tooltip {Width of bank address} ${BA_BITS}
set BYTE_LANES [ipgui::add_param $IPINST -name "BYTE_LANES" -parent ${Page_0}] set BYTE_LANES [ipgui::add_param $IPINST -name "BYTE_LANES" -parent ${Page_0}]
set_property tooltip {Number of byte lanes of DDR3 RAM in the FPGA board (e.g. x16 DDR3 will have 2 byte lanes)} ${BYTE_LANES} set_property tooltip {Number of byte lanes of DDR3 RAM in the FPGA board (e.g. x16 DDR3 will have 2 byte lanes)} ${BYTE_LANES}
set ECC_ENABLE [ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0}] set ECC_ENABLE [ipgui::add_param $IPINST -name "ECC_ENABLE" -parent ${Page_0} -widget comboBox]
set_property tooltip {0 = DIsabled, 1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC} ${ECC_ENABLE} set_property tooltip {Type of ECC (0,1,2,3)} ${ECC_ENABLE}
set SELF_REFRESH [ipgui::add_param $IPINST -name "SELF_REFRESH" -parent ${Page_0} -widget comboBox]
set_property tooltip {Enable option for self-refresh} ${SELF_REFRESH}
set SKIP_INTERNAL_TEST [ipgui::add_param $IPINST -name "SKIP_INTERNAL_TEST" -parent ${Page_0}] set SKIP_INTERNAL_TEST [ipgui::add_param $IPINST -name "SKIP_INTERNAL_TEST" -parent ${Page_0}]
set_property tooltip {Check to skip built-in self-test (check this if UberDDR3 will be connected to Microblaze)} ${SKIP_INTERNAL_TEST} set_property tooltip {Check to skip built-in self-test (check this if UberDDR3 will be connected to Microblaze)} ${SKIP_INTERNAL_TEST}
set ODELAY_SUPPORTED [ipgui::add_param $IPINST -name "ODELAY_SUPPORTED" -parent ${Page_0}] set ODELAY_SUPPORTED [ipgui::add_param $IPINST -name "ODELAY_SUPPORTED" -parent ${Page_0}]
@ -284,6 +286,15 @@ proc validate_PARAM_VALUE.SECOND_WISHBONE { PARAM_VALUE.SECOND_WISHBONE } {
return true return true
} }
proc update_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } {
# Procedure called to update SELF_REFRESH when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.SELF_REFRESH { PARAM_VALUE.SELF_REFRESH } {
# Procedure called to validate SELF_REFRESH
return true
}
proc update_PARAM_VALUE.SKIP_INTERNAL_TEST { PARAM_VALUE.SKIP_INTERNAL_TEST } { proc update_PARAM_VALUE.SKIP_INTERNAL_TEST { PARAM_VALUE.SKIP_INTERNAL_TEST } {
# Procedure called to update SKIP_INTERNAL_TEST when any of the dependent parameters in the arguments change # Procedure called to update SKIP_INTERNAL_TEST when any of the dependent parameters in the arguments change
} }
@ -405,6 +416,11 @@ proc update_MODELPARAM_VALUE.ECC_ENABLE { MODELPARAM_VALUE.ECC_ENABLE PARAM_VALU
set_property value [get_property value ${PARAM_VALUE.ECC_ENABLE}] ${MODELPARAM_VALUE.ECC_ENABLE} set_property value [get_property value ${PARAM_VALUE.ECC_ENABLE}] ${MODELPARAM_VALUE.ECC_ENABLE}
} }
proc update_MODELPARAM_VALUE.SELF_REFRESH { MODELPARAM_VALUE.SELF_REFRESH PARAM_VALUE.SELF_REFRESH } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.SELF_REFRESH}] ${MODELPARAM_VALUE.SELF_REFRESH}
}
proc update_MODELPARAM_VALUE.DIC { MODELPARAM_VALUE.DIC PARAM_VALUE.DIC } { proc update_MODELPARAM_VALUE.DIC { MODELPARAM_VALUE.DIC PARAM_VALUE.DIC } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.DIC}] ${MODELPARAM_VALUE.DIC} set_property value [get_property value ${PARAM_VALUE.DIC}] ${MODELPARAM_VALUE.DIC}