From fec8b5b3fca575799ec6fec033d69ad70bb51b39 Mon Sep 17 00:00:00 2001 From: Angelo Jacobo Date: Thu, 6 Apr 2023 19:01:02 +0800 Subject: [PATCH] Update ddr3_controller.v --- rtl/ddr3_controller.v | 602 ++++++++++++++++++++++++++---------------- 1 file changed, 379 insertions(+), 223 deletions(-) diff --git a/rtl/ddr3_controller.v b/rtl/ddr3_controller.v index 11b46cb..59a8e6f 100644 --- a/rtl/ddr3_controller.v +++ b/rtl/ddr3_controller.v @@ -89,8 +89,8 @@ module ddr3_controller #( localparam READ_SLOT = get_slot(CMD_RD), WRITE_SLOT = get_slot(CMD_WR), - ANTICIPATE_ACTIVATE_SLOT = get_slot(CMD_ACT), - ANTICIPATE_PRECHARGE_SLOT = get_slot(CMD_PRE); + ACTIVATE_SLOT = get_slot(CMD_ACT), + PRECHARGE_SLOT = get_slot(CMD_PRE); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -306,12 +306,12 @@ module ddr3_controller #( end end + //////////////////////////////////////////////////////// Track Bank Status and Active Row //////////////////////////////////////////////////////// - // + reg[(1< stage1 --> stage2 --> cmd + always @* begin - request_pending_d = request_pending_q; - o_wb_ack_d = 0; - cmd_d[0] = -1; - cmd_d[1] = -1; - cmd_d[2] = -1; - cmd_d[3] = -1; - delay_before_precharge_added_delay = 0; - delay_before_activate_added_delay = 0; - delay_before_write_added_delay = 0; - delay_before_read_added_delay = 0; - for(integer index=0; index < (1<= b) max = a; else max = b; endfunction - - //creates the added delay needed for the "delay_before_x" given an input slot number - function[31:0] added_delay(input[2:0] slot_number); - case(slot_number) - 0: added_delay = {{28{1'b1}},4'b1111}; - 1: added_delay = {{28{1'b1}},4'b1110}; - 2: added_delay = {{28{1'b1}},4'b1100}; - 3: added_delay = {{28{1'b1}},4'b1000}; - endcase - endfunction //Find the 3-bit value for the Mode Register 0 WR (Write recovery for auto-precharge) function[2:0] WRA_mode_register_value(input integer WRA); @@ -729,6 +757,22 @@ module ddr3_controller #( end endfunction + //find the delay to be used by delay_before_xxxx_counter. + // - delay_nCK = delay required between the two commands in DDR3 clock cycles + // - start_slot = slot number of the first command + // - end_slot = slot number of the second command + // returns the number of controller clock cycles to satisfy the delay required between the two commands + function integer find_delay(input integer delay_nCK, input integer start_slot, input integer end_slot); + integer k; //error: variable declaration assignments are only allowed at the module level + begin + k = 0; + while( ((4 - start_slot) + end_slot + 4*k) < delay_nCK) begin + k = k + 1; + end + find_delay = k; + end + endfunction + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// `ifndef YOSYS @@ -762,11 +806,6 @@ module ddr3_controller #( $display("\tns_to_cycles(14.875) = 4 = %0d [round-off]", nCK_to_ns(3) ); $display("\tns_to_cycles(13.875) = 7 = %0d [round-up]\n", nCK_to_ns(5) ); - $display("Test added_delay() function:"); - $display("\tadded_delay(0) = 0xffffffff = 0x%h", added_delay(0) ); - $display("\tadded_delay(1) = 0xfffffffe = 0x%h", added_delay(1) ); - $display("\tadded_delay(2) = 0xfffffffc = 0x%h", added_delay(2) ); - $display("\tadded_delay(3) = 0xfffffff8 = 0x%h\n", added_delay(3) ); $display("Test $floor() function:"); $display("\t$floor(5/2) = 2.5 = %0d", $floor(5/2) ); @@ -788,8 +827,8 @@ module ddr3_controller #( $display("READ_SLOT = %0d", READ_SLOT); $display("WRITE_SLOT = %0d", WRITE_SLOT); - $display("ANTICIPATE_ACTIVATE_SLOT = %0d", ANTICIPATE_ACTIVATE_SLOT); - $display("ANTICIPATE_PRECHARGE_SLOT = %0d", ANTICIPATE_PRECHARGE_SLOT); + $display("ACTIVATE_SLOT = %0d", ACTIVATE_SLOT); + $display("PRECHARGE_SLOT = %0d", PRECHARGE_SLOT); $display("\n\nDELAYS:"); $display("\tns_to_nCK(tRCD): %0d", ns_to_nCK(tRCD)); @@ -800,6 +839,17 @@ module ddr3_controller #( $display("\t(CWL_nCK + 3'd4 + ns_to_nCK(tWR)): %0d", (CWL_nCK + 3'd4 + ns_to_nCK(tWR))); $display("\t(CWL_nCK + 3'd4 + ns_to_nCK(tWTR)): %0d", (CWL_nCK + 3'd4 + ns_to_nCK(tWTR))); $display("\t$signed(4'b1100)>>>4: %b", $signed(4'b1100) >>> 4); + + $display("\n\nPRECHARGE_TO_ACTIVATE_DELAY = 3 = %0d", PRECHARGE_TO_ACTIVATE_DELAY); + $display("ACTIVATE_TO_WRITE_DELAY = 3 = %0d", ACTIVATE_TO_WRITE_DELAY); + $display("ACTIVATE_TO_READ_DELAY = 2 = %0d", ACTIVATE_TO_READ_DELAY); + $display("READ_TO_WRITE_DELAY = 2 = %0d", READ_TO_WRITE_DELAY); + $display("READ_TO_READ_DELAY = 0 = %0d", READ_TO_READ_DELAY); + $display("READ_TO_PRECHARGE_DELAY = 1 =%0d", READ_TO_PRECHARGE_DELAY); + $display("WRITE_TO_WRITE_DELAY = 0 = %0d", WRITE_TO_WRITE_DELAY); + $display("WRITE_TO_READ_DELAY = 4 = %0d", WRITE_TO_READ_DELAY); + $display("WRITE_TO_PRECHARGE_DELAY = 5 = %0d", WRITE_TO_PRECHARGE_DELAY); + end `endif @@ -956,34 +1006,35 @@ module ddr3_controller #( always @* begin //make sure each command has distinct slot number (except for read/write which can have the same or different slot number) - assert((WRITE_SLOT != ANTICIPATE_ACTIVATE_SLOT != ANTICIPATE_PRECHARGE_SLOT) && (READ_SLOT != ANTICIPATE_ACTIVATE_SLOT != ANTICIPATE_PRECHARGE_SLOT) ); + assert((WRITE_SLOT != ACTIVATE_SLOT != PRECHARGE_SLOT) && (READ_SLOT != ACTIVATE_SLOT != PRECHARGE_SLOT) ); //make sure slot number for read command is correct end //create a formal assertion that says during refresh ack should be low always //make an assertion that there will be no request pending before actual refresh starts at instruction 4'd12 - reg[24:0] f_wb_inputs[13:0]; + reg[24:0] f_wb_inputs[31:0]; reg[4:0] f_index = 0; reg[5:0] f_counter = 0; + reg[9:0] f_reset_counter = 0; initial begin - /* + /* f_wb_inputs[0] = {1'b0, {14'd0,3'd1, 7'd0}}; //read - f_wb_inputs[1] = {1'b0, {14'd0,3'd1, 7'd8}}; //read on same bank (tCCD) - f_wb_inputs[2] = {1'b1, {14'd0,3'd1, 7'd16}}; //write on same bank (tRTW) - f_wb_inputs[3] = {1'b1, {14'd0,3'd1, 7'd24}}; //write on same bank (tCCD) + f_wb_inputs[1] = {1'b0, {14'd0,3'd1, 7'd1}}; //read on same bank (tCCD) + f_wb_inputs[2] = {1'b1, {14'd0,3'd1, 7'd2}}; //write on same bank (tRTW) + f_wb_inputs[3] = {1'b1, {14'd0,3'd1, 7'd3}}; //write on same bank (tCCD) f_wb_inputs[4] = {1'b0, {14'd0,3'd2, 7'd0}}; //read on different bank - f_wb_inputs[5] = {1'b1, {14'd0,3'd2, 7'd8}}; //write on same bank (tRTW) - f_wb_inputs[6] = {1'b1, {14'd0,3'd1, 7'd32}}; //write on different bank (already activated) - f_wb_inputs[7] = {1'b1, {14'd0,3'd1, 7'd40}}; //write (tCCD) + f_wb_inputs[5] = {1'b1, {14'd0,3'd2, 7'd1}}; //write on same bank (tRTW) + f_wb_inputs[6] = {1'b1, {14'd0,3'd1, 7'd4}}; //write on different bank (already activated) + f_wb_inputs[7] = {1'b1, {14'd0,3'd1, 7'd5}}; //write (tCCD) f_wb_inputs[8] = {1'b1, {14'd1,3'd2, 7'd0}}; //write on different bank (already activated but wrong row) - f_wb_inputs[9] = {1'b1, {14'd1,3'd2, 7'd8}}; //write (tCCD) - f_wb_inputs[10] = {1'b1, {14'd1,3'd2, 7'd16}}; //write (tCCD) - f_wb_inputs[11] = {1'b0, {14'd2,3'd2, 7'd24}}; //read (same bank but wrong row so precharge first) - f_wb_inputs[12] = {1'b0, {14'd2,3'd2, 7'd32}}; //read (tCCD) - f_wb_inputs[13] = {1'b0, {14'd2,3'd2, 7'd40}}; //read (tCCD) + f_wb_inputs[9] = {1'b1, {14'd1,3'd2, 7'd1}}; //write (tCCD) + f_wb_inputs[10] = {1'b1, {14'd1,3'd2, 7'd2}}; //write (tCCD) + f_wb_inputs[11] = {1'b0, {14'd2,3'd2, 7'd0}}; //read (same bank but wrong row so precharge first) + f_wb_inputs[12] = {1'b0, {14'd2,3'd2, 7'd1}}; //read (tCCD) + f_wb_inputs[13] = {1'b0, {14'd2,3'd2, 7'd2}}; //read (tCCD) */ - + /* f_wb_inputs[0] = {1'b0, {14'd0,3'd1, 7'd0}}; //read f_wb_inputs[1] = {1'b0, {14'd0,3'd1, 7'd1}}; //read on same bank (tCCD) f_wb_inputs[2] = {1'b1, {14'd0,3'd2, 7'd0}}; //write on the anticipated bank @@ -993,24 +1044,129 @@ module ddr3_controller #( f_wb_inputs[6] = {1'b1, {14'd0,3'd7, 7'd0}}; //write on the un-anticipated idle bank (activate first) f_wb_inputs[7] = {1'b1, {14'd0,3'd1, 7'd1}}; //write on the un-anticipated active bank and row (write) f_wb_inputs[8] = {1'b1, {14'd1,3'd7, 7'd0}}; //write on the un-anticipated active bank but wrong row (precharge first) + */ + /* + f_wb_inputs[0] = {1'b0, {14'd0,3'd1, 7'd0}}; //read + f_wb_inputs[1] = {1'b0, {14'd0,3'd1, 7'd1}}; //read + f_wb_inputs[2] = {1'b0, {14'd0,3'd1, 7'd2}}; //read + f_wb_inputs[3] = {1'b0, {14'd0,3'd1, 7'd3}}; //read + f_wb_inputs[4] = {1'b0, {14'd0,3'd1, 7'd4}}; //read + f_wb_inputs[5] = {1'b0, {14'd0,3'd1, 7'd5}}; //read + f_wb_inputs[6] = {1'b0, {14'd0,3'd1, 7'd6}}; //write + f_wb_inputs[7] = {1'b0, {14'd0,3'd1, 7'd7}}; //write + f_wb_inputs[8] = {1'b0, {14'd0,3'd1, 7'd8}}; //write + f_wb_inputs[9] = {1'b0, {14'd0,3'd1, 7'd9}}; //write + f_wb_inputs[10] = {1'b0, {14'd0,3'd1, 7'd10}}; //write + f_wb_inputs[11] = {1'b0, {14'd0,3'd1, 7'd11}}; //write + */ + f_wb_inputs[0] = {1'b0, {14'd0,3'd1, 7'd0}}; //read + f_wb_inputs[1] = {1'b0, {14'd1,3'd1, 7'd1}}; //read on same bank (tCCD) + f_wb_inputs[2] = {1'b0, {14'd2,3'd1, 7'd2}}; //write on same bank (tRTW) + f_wb_inputs[3] = {1'b0, {14'd3,3'd1, 7'd3}}; //write on same bank (tCCD) + f_wb_inputs[4] = {1'b0, {14'd4,3'd1, 7'd0}}; //read on different bank + f_wb_inputs[5] = {1'b1, {14'd5,3'd1, 7'd1}}; //write on same bank (tRTW) + f_wb_inputs[6] = {1'b1, {14'd6,3'd1, 7'd4}}; //write on different bank (already activated) + f_wb_inputs[7] = {1'b1, {14'd0,3'd2, 7'd5}}; //write (tCCD) + f_wb_inputs[8] = {1'b1, {14'd1,3'd2, 7'd0}}; //write on different bank (already activated but wrong row) + f_wb_inputs[9] = {1'b1, {14'd2,3'd2, 7'd1}}; //write (tCCD) + f_wb_inputs[10] = {1'b1, {14'd3,3'd2, 7'd2}}; //write (tCCD) + f_wb_inputs[11] = {1'b0, {14'd4,3'd2, 7'd0}}; //read (same bank but wrong row so precharge first) + f_wb_inputs[12] = {1'b0, {14'd5,3'd2, 7'd1}}; //read (tCCD) + f_wb_inputs[13] = {1'b0, {14'd6,3'd2, 7'd2}}; //read (tCCD) + end always @(posedge i_clk) begin - if(o_wb_ack) begin + if(!o_wb_stall) begin f_index <= f_index + 1; f_counter <= 0; end else begin f_counter <= f_counter + 1; end + if(o_wb_stall && i_rst_n) begin + f_reset_counter = f_reset_counter + 1; + end + else f_reset_counter = 10; end always @* begin assume(i_wb_cyc == 1); assume(i_wb_stb == 1); - if(f_index>1) assume(i_rst_n); + if(f_past_valid) assume(i_rst_n); assume(i_wb_we == f_wb_inputs[f_index][24]); assume(i_wb_addr == f_wb_inputs[f_index][23:0]); - cover(f_index == 9); + cover(f_index == 5); + //cover(f_reset_counter == 10); end + + /* + fifo #(.W(4), .B(8)) f_fifo + ( + .clk(i_clk), + .rst_n(i_rst_n), + .wr(), + .rd(), + .wr_data(wr_data), + .rd_data(rd_data), + output reg full,empty + ); + */ `endif endmodule + + +`timescale 1ns / 1ps + +module fifo + #(parameter W=4,B=8) + ( + input clk,rst_n, + input wr,rd, + input[B-1:0] wr_data, + output[B-1:0] rd_data, + output reg full,empty + ); + initial begin + full=0; + empty=1; + end + reg[W-1:0] rd_ptr=0,wr_ptr=0; + reg[B-1:0] array_reg[2**W-1:0]; + + + //register file operation + always @(posedge clk) begin + if(wr && !full && !(wr&&rd&&empty)) array_reg[wr_ptr]=wr_data; + end + assign rd_data=array_reg[rd_ptr]; + + //fifo operation + always @(posedge clk,negedge rst_n) begin + if(!rst_n) begin + rd_ptr=0; + wr_ptr=0; + full=0; + empty=1; + end + else begin + case({rd,wr}) + 2'b01: if(!full) begin + wr_ptr=wr_ptr+1; + empty=0; + full=(wr_ptr==rd_ptr); + end + 2'b10: if(!empty) begin + rd_ptr=rd_ptr+1; + full=0; + empty=(rd_ptr==wr_ptr); + end + 2'b11: if(!empty && !full) begin + rd_ptr=rd_ptr+1; + wr_ptr=wr_ptr+1; + end + endcase + end + end + +endmodule +