diff --git a/rtl/ddr3_controller.v b/rtl/ddr3_controller.v index 8122b76..9f9a90e 100644 --- a/rtl/ddr3_controller.v +++ b/rtl/ddr3_controller.v @@ -186,7 +186,9 @@ module ddr3_controller #( localparam CWL_nCK = 5; //create a function for this localparam DELAY_MAX_VALUE = ns_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 PRE_STALL_DELAY = ((PRECHARGE_TO_ACTIVATE_DELAY+1) + (ACTIVATE_TO_WRITE_DELAY+1) + (WRITE_TO_PRECHARGE_DELAY+1) + 1)*2; + localparam CALIBRATION_DELAY = 2; + localparam PRE_REFRESH_DELAY = WRITE_TO_PRECHARGE_DELAY + 1; + //localparam PRE_STALL_DELAY = ((PRECHARGE_TO_ACTIVATE_DELAY+1) + (ACTIVATE_TO_WRITE_DELAY+1) + (WRITE_TO_PRECHARGE_DELAY+1) + 1)*2; //worst case scenario: two consecutive writes at same bank but different row //delay will be: PRECHARGE -> PRECHARGE_TO_ACTIVATE_DELAY -> ACTIVATE -> ACTIVATE_TO_WRITE_DELAY -> WRITE -> WRITE_TO_PRECHARGE_DELAY -> //PRECHARGE -> PRECHARGE_TO_ACTIVATE_DELAY -> ACTIVATE -> ACTIVATE_TO_WRITE_DELAY -> WRITE -> WRITE_TO_PRECHARGE_DELAY @@ -303,7 +305,7 @@ module ddr3_controller #( reg[ DELAY_COUNTER_WIDTH - 1:0] delay_counter = INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0]; //counter used for delays reg delay_counter_is_zero = (INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0] == 0); //counter is now zero so retrieve next delay reg reset_done = 0; //high if reset has already finished - reg skip_reset_seq_delay = 0; //flag to skip delay and go to next reset instruction + reg pause_counter = 0; wire issue_read_command; wire issue_write_command; reg[(1< f_read_time_stamp[index]) begin + assert((f_precharge_time_stamp[index] - f_read_time_stamp[index]) >= ns_to_nCK(tRTP)); + end + + /* + // Check tWTR (Delay from start of internal write transaction to internal read command) + if(f_read_time_stamp[index] > f_write_time_stamp[index]) begin + assert((f_read_time_stamp[index] - f_write_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tWTR) + end + */ + + // Check tRCD (ACT to internal read or write delay time) + if(f_read_time_stamp[index] > f_activate_time_stamp[index]) begin + assert((f_read_time_stamp[index] - f_activate_time_stamp[index]) >= ns_to_nCK(tRCD)); + end + if(f_write_time_stamp[index] > f_activate_time_stamp[index]) begin + assert((f_write_time_stamp[index] - f_activate_time_stamp[index]) >= ns_to_nCK(tRCD)); + end + + // Check tRP (PRE command period) + if(f_activate_time_stamp[index] > f_precharge_time_stamp[index]) begin + assert((f_activate_time_stamp[index] - f_precharge_time_stamp[index]) >= ns_to_nCK(tRP)); + end + + // Check tRAS (ACTIVE to PRECHARGE command period) + if(f_precharge_time_stamp[index] > f_activate_time_stamp[index]) begin + assert((f_precharge_time_stamp[index] - f_activate_time_stamp[index]) >= ns_to_nCK(tRAS)); + end + end + end + + // assertion on FSM calibration + always @* begin + assert(instruction_address <= 22); + assert(state_calibrate <= DONE_CALIBRATE); + if(instruction_address < 13) begin + assert(state_calibrate == IDLE); + end + + if(state_calibrate > IDLE && state_calibrate <= BITSLIP_DQS_TRAIN_2) begin + assert(instruction_address == 13); + assert(pause_counter); + end + + + if(state_calibrate > START_WRITE_LEVEL && state_calibrate <= WAIT_FOR_FEEDBACK) begin + assert(instruction_address == 17); + assert(pause_counter); + end + + if(pause_counter) begin + assert(delay_counter != 0); + end + + if(state_calibrate > ISSUE_WRITE_1 && state_calibrate < DONE_CALIBRATE) begin + assume(instruction_address == 22); //write-then-read calibration will not take more than tREFI (7.8us, delay a address 22) + assert(reset_done); + end + + if(state_calibrate == DONE_CALIBRATE) begin + assert(reset_done); + assert(instruction_address >= 19); + end + + if(reset_done) begin + assert(instruction_address >= 19); + end + + if(!reset_done) begin + assert(!stage1_pending && !stage2_pending); + assert(o_wb_stall); + end + if(reset_done) begin + assert(instruction_address >= 19 && instruction_address <= 22); + 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 + assert(o_wb_stall); + end + + if(instruction_address == 19 && pause_counter) begin //pre-stall delay to finish all remaining requests + assert(delay_counter == PRE_REFRESH_DELAY); + assert(reset_done); + assert(DONE_CALIBRATE); + end + end + `endif //endif for TEST_TIME_PARAMETERS + + + `ifdef TEST_CONTROLLER_PIPELINE // wires and registers used in this formal section `ifdef TEST_DATA localparam F_TEST_CMD_DATA_WIDTH = $bits(i_wb_data) + $bits(i_wb_sel) + $bits(i_aux) + $bits(i_wb_addr) + $bits(i_wb_we); @@ -1809,7 +1978,7 @@ module ddr3_controller #( f_read <= 0; 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] || skip_reset_seq_delay)) begin + else if((delay_counter == 1 || !instruction[USE_TIMER])) begin f_addr <= (f_addr == 22)? 19:f_addr + 1; f_read <= f_addr; end @@ -1841,11 +2010,11 @@ module ddr3_controller #( 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(skip_reset_seq_delay) ) begin + if($past(f_read_inst[USE_TIMER]) && !$past(pause_counter) ) 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 - else if(!$past(f_read_inst[USE_TIMER]) && !$past(skip_reset_seq_delay)) begin + else if(!$past(f_read_inst[USE_TIMER]) && !$past(pause_counter)) begin assert(delay_counter_is_zero); end @@ -1857,13 +2026,13 @@ module ddr3_controller #( end //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])) 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) ); //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 && !$past(skip_reset_seq_delay,2)) begin + if($past(delay_counter) == 1) begin assert(delay_counter == 0 && delay_counter_is_zero); end //assert the relationship between the stages FOR RESET SEQUENCE @@ -1931,14 +2100,17 @@ module ddr3_controller #( if(state_calibrate > IDLE && state_calibrate <= BITSLIP_DQS_TRAIN_2) begin assert(instruction_address == 13); + assert(pause_counter); end + if(state_calibrate > START_WRITE_LEVEL && state_calibrate <= WAIT_FOR_FEEDBACK) begin assert(instruction_address == 17); + assert(pause_counter); end - - if(instruction_address == 13 || instruction_address == 17) begin - assume(delay_counter != 1); //read (address 13) and write(17) will not take more than the max delay (500us) + + if(pause_counter) begin + assert(delay_counter != 0); end if(state_calibrate > ISSUE_WRITE_1 && state_calibrate < DONE_CALIBRATE) begin @@ -2035,7 +2207,7 @@ module ddr3_controller #( if(stage1_pending && $past(state_calibrate) == READ_DATA && state_calibrate == READ_DATA) begin assert(!stage1_we); end - if(instruction_address == 21 || (instruction_address == 20 && delay_counter != 0) || instruction_address < 19) begin //not inside active or calibration + if(instruction_address == 21 || ($past(instruction_address) == 20 && $past(instruction_address,2) == 19) || instruction_address < 19) begin //not inside active or calibration assert(f_bank_status == 0); assert(bank_status_q == 0); end @@ -2105,6 +2277,7 @@ module ddr3_controller #( else if(state_calibrate > ISSUE_WRITE_1) begin assert(stage2_aux == 1); end + //assert(f_bank_active_row[cmd_d[WRITE_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1]] == current_row); //column to be written must be the current active row end if(cmd_d[READ_SLOT][CMD_CS_N:CMD_WE_N] == 4'b0101) begin //READ @@ -2127,6 +2300,7 @@ module ddr3_controller #( else if(state_calibrate > ISSUE_WRITE_1) begin assert(stage2_aux == 0); end + //assert(f_bank_active_row[cmd_d[READ_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1]] == current_row);//column to be written must be the current active row end if(cmd_d[PRECHARGE_SLOT][CMD_CS_N:CMD_WE_N] == 4'b0010) begin //PRECHARGE @@ -2186,14 +2360,13 @@ module ddr3_controller #( //check if a DDR3 command is issued if(cmd_d[PRECHARGE_SLOT][CMD_CS_N:CMD_WE_N] == 4'b0010) begin //PRECHARGE bank = cmd_d[PRECHARGE_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1]; - f_precharge_time_stamp[bank] <= f_timer; + f_precharge_time_stamp[bank] <= f_timer + PRECHARGE_SLOT; if(cmd_d[PRECHARGE_SLOT][10]) begin //A10 precharge all banks for(index=0; index < (1< f_read_time_stamp[index]) begin - assert((f_precharge_time_stamp[index] - f_read_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tRTP); - end - - /* - // Check tWTR (Delay from start of internal write transaction to internal read command) - if(f_read_time_stamp[index] > f_write_time_stamp[index]) begin - assert((f_read_time_stamp[index] - f_write_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tWTR) - end - */ - - // Check tRCD (ACT to internal read or write delay time) - if(f_read_time_stamp[index] > f_activate_time_stamp[index]) begin - assert((f_read_time_stamp[index] - f_activate_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tRCD); - end - if(f_write_time_stamp[index] > f_activate_time_stamp[index]) begin - assert((f_write_time_stamp[index] - f_activate_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tRCD); - end - - // Check tRP (PRE command period) - if(f_activate_time_stamp[index] > f_precharge_time_stamp[index]) begin - assert((f_activate_time_stamp[index] - f_precharge_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tRP); - end - - // Check tRAS (ACTIVE to PRECHARGE command period) - if(f_precharge_time_stamp[index] > f_activate_time_stamp[index]) begin - assert((f_precharge_time_stamp[index] - f_activate_time_stamp[index])*CONTROLLER_CLK_PERIOD >= tRAS); - end - - end - - end - - localparam PRECHARGE_TO_ACTIVATE_DELAY = find_delay(ns_to_nCK(tRP), PRECHARGE_SLOT, ACTIVATE_SLOT); //3 - localparam ACTIVATE_TO_PRECHARGE_DELAY = find_delay(ns_to_nCK(tRAS), ACTIVATE_SLOT, PRECHARGE_SLOT); - localparam ACTIVATE_TO_WRITE_DELAY = find_delay(ns_to_nCK(tRCD), ACTIVATE_SLOT, WRITE_SLOT); //3 - localparam ACTIVATE_TO_READ_DELAY = find_delay(ns_to_nCK(tRCD), ACTIVATE_SLOT, READ_SLOT); //2 - localparam READ_TO_WRITE_DELAY = find_delay((CL_nCK + tCCD + 3'd2 - CWL_nCK), READ_SLOT, WRITE_SLOT); //2 - localparam READ_TO_READ_DELAY = 0; - localparam READ_TO_PRECHARGE_DELAY = find_delay(ns_to_nCK(tRTP), READ_SLOT, PRECHARGE_SLOT); //1 - localparam WRITE_TO_WRITE_DELAY = 0; - localparam WRITE_TO_READ_DELAY = find_delay((CWL_nCK + 3'd4 + ns_to_nCK(tWTR)), WRITE_SLOT, READ_SLOT); //4 - localparam WRITE_TO_PRECHARGE_DELAY = find_delay((CWL_nCK + 3'd4 + ns_to_nCK(tWR)), WRITE_SLOT, PRECHARGE_SLOT); //5 - `endif fwb_slave #( // {{{ @@ -2514,7 +2635,7 @@ module ddr3_controller #( // }}} // }}} ); - `endif //endif for FORMAL_COVER + `endif //endif for TEST_CONTROLLER_PIPELINE `endif //endif for FORMAL endmodule