From 217770b9773b941a8409cb4bc7715d825327594f Mon Sep 17 00:00:00 2001 From: AngeloJacobo Date: Sun, 2 Jul 2023 06:38:33 +0800 Subject: [PATCH] verified precharge and activate cmds, fixed bug in write_calib cmd --- rtl/ddr3_controller.v | 320 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 259 insertions(+), 61 deletions(-) diff --git a/rtl/ddr3_controller.v b/rtl/ddr3_controller.v index 8866cc2..8122b76 100644 --- a/rtl/ddr3_controller.v +++ b/rtl/ddr3_controller.v @@ -222,7 +222,7 @@ module ddr3_controller #( `endif localparam READ_DELAY = $rtoi($floor((CL_nCK - (3 - READ_SLOT + 1))/4.0 )); localparam READ_ACK_PIPE_WIDTH = READ_DELAY + 1 + 2 + 1 + 1; - localparam MAX_ADDED_READ_ACK_DELAY = 2; + localparam MAX_ADDED_READ_ACK_DELAY = 16; localparam DELAY_BEFORE_WRITE_LEVEL_FEEDBACK = STAGE2_DATA_DEPTH + ns_to_cycles(tWLO+tWLOE) + 10; //plus 10 controller clocks for possible bus latency and //the delay for receiving feedback DQ from IOBUF -> IDELAY -> ISERDES /*********************************************************************************************************************************************/ @@ -729,7 +729,7 @@ module ddr3_controller #( {stage1_next_row , stage1_next_bank, stage1_next_col[COL_BITS-1:$clog2(serdes_ratio*2)] } <= i_wb_addr + MARGIN_BEFORE_ANTICIPATE; //anticipated next row and bank to be accessed stage1_data <= i_wb_data; end - else if(write_calib_stb) begin + else if(state_calibrate != DONE_CALIBRATE) begin stage1_pending <= write_calib_stb;//actual request flag stage1_we <= write_calib_we; //write-enable stage1_dm <= 0; @@ -1378,7 +1378,7 @@ module ddr3_controller #( state_calibrate <= START_WRITE_LEVEL; end end - ISSUE_WRITE_1: if(instruction_address == 22) begin + ISSUE_WRITE_1: if(instruction_address == 22 && !o_wb_stall_q) begin write_calib_stb <= 1;//actual request flag write_calib_aux <= 1; //AUX ID to determine later if ACK is for read or write write_calib_we <= 1; //write-enable @@ -1386,7 +1386,7 @@ module ddr3_controller #( write_calib_data <= { {LANES{8'h91}}, {LANES{8'h77}}, {LANES{8'h29}}, {LANES{8'h8c}}, {LANES{8'hd0}}, {LANES{8'had}}, {LANES{8'h51}}, {LANES{8'hc1}} }; state_calibrate <= ISSUE_WRITE_2; end - ISSUE_WRITE_2: begin + ISSUE_WRITE_2: if(!o_wb_stall_q) begin write_calib_stb <= 1;//actual request flag write_calib_aux <= 1; //AUX ID to determine later if ACK is for read or write write_calib_we <= 1; //write-enable @@ -1742,8 +1742,13 @@ module ddr3_controller #( end `else + //`define TEST_DATA // wires and registers used in this formal section - 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); + `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); + `else + localparam F_TEST_CMD_DATA_WIDTH = $bits(i_wb_addr) + $bits(i_wb_we); + `endif reg f_past_valid = 0; reg[$bits(instruction_address) - 1: 0] f_addr = 0, f_read = 0 ; reg[$bits(instruction) - 1:0] f_read_inst = INITIAL_RESET_INSTRUCTION; @@ -1753,8 +1758,17 @@ module ddr3_controller #( reg[5:0] f_counter = 0; reg[4:0] f_index_1 = 0; + reg[4:0] f_index_2 = 0; reg[F_TEST_CMD_DATA_WIDTH - 1:0] f_write_data; reg f_write_fifo = 0, f_read_fifo = 0; + reg[ROW_BITS-1:0] f_bank_active_row[(1< ISSUE_WRITE_1) begin - assert(stage2_aux == 1); - end - end - 4'b0101: begin //READ - if(state_calibrate == DONE_CALIBRATE) begin - f_read_data_col = {f_read_data[1 +: COL_BITS - $clog2(serdes_ratio*2)], 3'b000}; //column address must match - assert(cmd_d[f_index_1][CMD_ADDRESS_START:0] == f_read_data_col); + f_read_data_wb_sel = (f_read_data[$bits(i_wb_addr) + AUX_WIDTH + 1 +: $bits(i_wb_sel)]); + assert(stage2_dm_unaligned == ~f_read_data_wb_sel); //data mask mst match inverse of wb sel + assert(stage2_data_unaligned == f_read_data[$bits(i_wb_sel) + $bits(i_wb_addr) + AUX_WIDTH + 1 +: $bits(i_wb_data)]); //actual data must match + `endif - f_read_data_bank = f_read_data[(COL_BITS - $clog2(serdes_ratio*2)) + 1 +: BA_BITS]; //bank must match - assert(cmd_d[f_index_1][CMD_BANK_START:CMD_ADDRESS_START+1] == f_read_data_bank); - - f_read_data_aux = f_read_data[$bits(i_wb_addr) + 1 +: AUX_WIDTH]; //UAX ID must match - assert(stage2_aux == f_read_data_aux); - - assert(!f_read_data[0]); //i_wb_we must be low - f_read_fifo = 1; //advance read pointer to prepare for next read - end - else if(state_calibrate > ISSUE_WRITE_1) begin - assert(stage2_aux == 0); - end - end - `ifdef OKAY reg[ROW_BITS-1:0] f_bank_active_row_q[(1< ISSUE_WRITE_1) begin + assert(stage2_aux == 1); + end end + + if(cmd_d[READ_SLOT][CMD_CS_N:CMD_WE_N] == 4'b0101) begin //READ + if(state_calibrate == DONE_CALIBRATE) begin + assert(f_bank_status[cmd_d[READ_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1]] == 1'b1); //the bank that will be read must initially be active + f_read_data_col = {f_read_data[1 +: COL_BITS - $clog2(serdes_ratio*2)], 3'b000}; //column address must match + assert(cmd_d[READ_SLOT][CMD_ADDRESS_START:0] == f_read_data_col); + + f_read_data_bank = f_read_data[(COL_BITS - $clog2(serdes_ratio*2)) + 1 +: BA_BITS]; //bank must match + assert(cmd_d[READ_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1] == f_read_data_bank); + + `ifdef TEST_DATA + f_read_data_aux = f_read_data[$bits(i_wb_addr) + 1 +: AUX_WIDTH]; //UAX ID must match + assert(stage2_aux == f_read_data_aux); + `endif + + assert(!f_read_data[0]); //i_wb_we must be low + f_read_fifo = 1; //advance read pointer to prepare for next read + end + else if(state_calibrate > ISSUE_WRITE_1) begin + assert(stage2_aux == 0); + end + end + + if(cmd_d[PRECHARGE_SLOT][CMD_CS_N:CMD_WE_N] == 4'b0010) begin //PRECHARGE + if(state_calibrate == DONE_CALIBRATE && (instruction_address == 22 || instruction_address == 19)) begin + assert(f_bank_status[cmd_d[PRECHARGE_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1]] == 1'b1); //the bank that should be precharged must initially be active + end + end + + if(cmd_d[ACTIVATE_SLOT][CMD_CS_N:CMD_WE_N] == 4'b0011) begin //ACTIVATE + if(state_calibrate == DONE_CALIBRATE) begin + assert(f_bank_status[cmd_d[ACTIVATE_SLOT][CMD_BANK_START:CMD_ADDRESS_START+1]] == 1'b0); //the bank that should be activated must initially be precharged + end + end + if(reset_done) begin - assert(cmd_d[f_index_1][CMD_CKE] && cmd_d[f_index_1][CMD_RESET_N]); //cke and rst_n should stay high when reset sequence is already done + 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 end end if(state_calibrate == DONE_CALIBRATE) begin @@ -2116,6 +2161,89 @@ module ddr3_controller #( assert(state_calibrate == DONE_CALIBRATE); end end + + always @* begin + assert(f_bank_status == bank_status_q); + end + + (*keep*) reg[31:0] bank; + always @(posedge i_controller_clk, negedge i_rst_n) begin + if(!i_rst_n) begin + //reset bank status and active row + 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 #( // {{{ .AW(wb_addr_bits),