Update ddr3_controller.v
This commit is contained in:
parent
f3c4b1b465
commit
9be5b5a616
|
|
@ -61,8 +61,8 @@ module ddr3_controller #(
|
||||||
input wire i_aux, //for AXI-interface compatibility (given upon strobe)
|
input wire i_aux, //for AXI-interface compatibility (given upon strobe)
|
||||||
// Wishbone outputs
|
// Wishbone outputs
|
||||||
output reg o_wb_stall, //1 = busy, cannot accept requests
|
output reg o_wb_stall, //1 = busy, cannot accept requests
|
||||||
output reg o_wb_ack, //1 = read/write request has completed
|
output wire o_wb_ack, //1 = read/write request has completed
|
||||||
output reg[wb_data_bits - 1:0] o_wb_data, //read data, for a 4:1 controller data width is 8 times the number of pins on the device
|
output wire[wb_data_bits - 1:0] o_wb_data, //read data, for a 4:1 controller data width is 8 times the number of pins on the device
|
||||||
output reg o_aux, //for AXI-interface compatibility (returned upon ack)
|
output reg o_aux, //for AXI-interface compatibility (returned upon ack)
|
||||||
// PHY Interface (to be added later)
|
// PHY Interface (to be added later)
|
||||||
output wire ck_en, // CKE
|
output wire ck_en, // CKE
|
||||||
|
|
@ -98,7 +98,10 @@ module ddr3_controller #(
|
||||||
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)
|
||||||
A10_CONTROL = 25, //Command bit that determines if A10 AutoPrecharge will be high
|
A10_CONTROL = 25, //Command bit that determines if A10 AutoPrecharge will be high
|
||||||
CLOCK_EN = 24, //Clock-enable to DDR3
|
CLOCK_EN = 24, //Clock-enable to DDR3
|
||||||
RESET_N = 23; //Reset_n to DDR3
|
RESET_N = 23, //Reset_n to DDR3
|
||||||
|
DDR3_CMD_START = 22, //Start of DDR3 command slot
|
||||||
|
DDR3_CMD_END = 19, //end of DDR3 command slot
|
||||||
|
MRS_BANK_START = 18; //start of bank value in MRS value
|
||||||
|
|
||||||
// ddr3_metadata partitioning
|
// ddr3_metadata partitioning
|
||||||
localparam CMD_LEN = 4 + 3 + BA_BITS + ROW_BITS, //4 is the width of a single ddr3 command (precharge,actvate, etc.) plus 3 (ck_en, odt, reset_n) plus bank bits plus row bits
|
localparam CMD_LEN = 4 + 3 + BA_BITS + ROW_BITS, //4 is the width of a single ddr3 command (precharge,actvate, etc.) plus 3 (ck_en, odt, reset_n) plus bank bits plus row bits
|
||||||
|
|
@ -226,74 +229,77 @@ module ddr3_controller #(
|
||||||
function [27:0] read_rom_instruction(input[5:0] instruction_address);
|
function [27:0] read_rom_instruction(input[5:0] instruction_address);
|
||||||
case(instruction_address)
|
case(instruction_address)
|
||||||
|
|
||||||
4'd0: read_rom_instruction = {5'b01000 , CMD_NOP , ns_to_cycles(POWER_ON_RESET_HIGH)};
|
5'd0: read_rom_instruction = {5'b01000 , CMD_NOP , ns_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” anytime before RESET# being de-asserted (min. time 10 ns). .
|
||||||
|
|
||||||
4'd1: read_rom_instruction = {5'b01001 , CMD_NOP, ns_to_cycles(INITIAL_CKE_LOW)};
|
5'd1: read_rom_instruction = {5'b01001 , CMD_NOP, ns_to_cycles(POWER_ON_RESET_HIGH/*INITIAL_CKE_LOW*/)};
|
||||||
//1. After RESET# is de-asserted, wait for another 500 us until CKE becomes active. During this time, the
|
//1. After RESET# is de-asserted, wait for another 500 us until CKE becomes active. During this time, the
|
||||||
//DRAM will start internal state initialization; this will be done independently of external clocks.
|
//DRAM will start internal state initialization; this will be done independently of external clocks.
|
||||||
// .... Also, a NOP or Deselect command must be registered (with tIS set up time to clock) before
|
// .... Also, a NOP or Deselect command must be registered (with tIS set up time to clock) before
|
||||||
//CKE goes active.
|
//CKE goes active.
|
||||||
|
|
||||||
4'd2: read_rom_instruction = {5'b01011 , CMD_NOP, ns_to_cycles(tXPR)};
|
5'd2: read_rom_instruction = {5'b01011 , CMD_NOP, ns_to_cycles(tXPR)};
|
||||||
//2. After CKE is being registered high, wait minimum of Reset CKE Exit time, tXPR.
|
//2. After CKE is being registered high, wait minimum of Reset CKE Exit time, tXPR.
|
||||||
|
|
||||||
4'd3: read_rom_instruction = {5'b00011, CMD_MRS, MR2};
|
5'd3: read_rom_instruction = {{2'b00,MR2[10], 2'b11}, CMD_MRS, MR2};
|
||||||
//3. Issue MRS command to load MR2.
|
//3. Issue MRS command to load MR2.
|
||||||
|
|
||||||
4'd4: read_rom_instruction = {5'b01011, CMD_NOP, nCK_to_cycles(tMRD)};
|
5'd4: read_rom_instruction = {5'b01011, CMD_NOP, nCK_to_cycles(tMRD)};
|
||||||
//4. Delay of tMRD between MRS commands
|
//4. Delay of tMRD between MRS commands
|
||||||
|
|
||||||
4'd5: read_rom_instruction = {5'b00011, CMD_MRS, MR3_DIS};
|
5'd5: read_rom_instruction = {{2'b00,MR3_DIS[10], 2'b11}, CMD_MRS, MR3_DIS};
|
||||||
//5. All banks must first be in the idle state (all banks precharged and tRP met) before doing MPR calibration, thus issue first disabled MR3
|
//5. All banks must first be in the idle state (all banks precharged and tRP met) before doing MPR calibration, thus issue first disabled MR3
|
||||||
|
|
||||||
4'd6: read_rom_instruction = {5'b01011, CMD_NOP, nCK_to_cycles(tMRD)};
|
5'd6: read_rom_instruction = {5'b01011, CMD_NOP, nCK_to_cycles(tMRD)};
|
||||||
//6. Delay of tMRD between MRS commands
|
//6. Delay of tMRD between MRS commands
|
||||||
|
|
||||||
4'd7: read_rom_instruction = {5'b00011, CMD_MRS, MR1};
|
5'd7: read_rom_instruction = {{2'b00,MR1[10], 2'b11}, CMD_MRS, MR1};
|
||||||
//7. Issue MRS command to load MR1 and enable DLL.
|
//7. Issue MRS command to load MR1 and enable DLL.
|
||||||
|
|
||||||
4'd8: read_rom_instruction = {5'b01011, CMD_NOP, nCK_to_cycles(tMRD)};
|
5'd8: read_rom_instruction = {5'b01011, CMD_NOP, nCK_to_cycles(tMRD)};
|
||||||
//8. Delay of tMRD between MRS commands
|
//8. Delay of tMRD between MRS commands
|
||||||
|
|
||||||
4'd9: read_rom_instruction = {5'b00011, CMD_MRS, MR0};
|
5'd9: read_rom_instruction = {{2'b00,MR0[10], 2'b11}, CMD_MRS, MR0};
|
||||||
//9. Issue MRS command to load MR0 and reset DLL.
|
//9. Issue MRS command to load MR0 and reset DLL.
|
||||||
|
|
||||||
4'd10: read_rom_instruction = {5'b01011, CMD_NOP, tMOD};
|
5'd10: read_rom_instruction = {5'b01011, CMD_NOP, tMOD};
|
||||||
//10. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
|
//10. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
|
||||||
|
|
||||||
4'd11: read_rom_instruction = {5'b01011, CMD_ZQC, tZQinit};
|
5'd11: read_rom_instruction = {5'b01011, CMD_ZQC, tZQinit};
|
||||||
//11. ZQ Calibration command is used to calibrate DRAM Ron & ODT values. ZQCL command triggers the calibration engine
|
//11. ZQ Calibration command is used to calibrate DRAM Ron & ODT values. ZQCL command triggers the calibration engine
|
||||||
//inside the DRAM and, once calibration is achieved, the calibrated values area transferred from the calibration engine to
|
//inside the DRAM and, once calibration is achieved, the calibrated values area transferred from the calibration engine to
|
||||||
//DRAM IO, which gets reflected as updated output driver
|
//DRAM IO, which gets reflected as updated output driver
|
||||||
|
|
||||||
// Precharge all banks before enabling MPR
|
// Precharge all banks before enabling MPR
|
||||||
4'd12: read_rom_instruction = {5'b01011, CMD_PRE, ns_to_cycles(tRP)};
|
5'd12: read_rom_instruction = {5'b01111, CMD_PRE, ns_to_cycles(tRP)};
|
||||||
//12. 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.
|
//12. 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.
|
||||||
|
|
||||||
4'd13: read_rom_instruction = {5'b00011, CMD_MRS, MR3_EN};
|
5'd13: read_rom_instruction = {{2'b00,MR3_EN[10], 2'b11}, CMD_MRS, MR3_EN};
|
||||||
//13. Issue MRS command to load MR3. Prior to enabling the MPR for read calibration, all banks must be in the idle state (all banks
|
//13. Issue MRS command to load MR3. Prior to enabling the MPR for read calibration, all banks must be in the idle state (all banks
|
||||||
// precharged and tRP met). Once the MPR is enabled, any subsequent RD or RDA commands will be redirected to the MultiPurpose Register.
|
// precharged and tRP met). Once the MPR is enabled, any subsequent RD or RDA commands will be redirected to the MultiPurpose Register.
|
||||||
|
|
||||||
4'd14: read_rom_instruction = {5'b01011, CMD_NOP, tMOD};
|
5'd14: read_rom_instruction = {5'b01011, CMD_NOP, tMOD};
|
||||||
//14. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
|
//14. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
|
||||||
|
|
||||||
4'd15: read_rom_instruction = {5'b00011, CMD_NOP, READ_CAL_DELAY};
|
5'd15: read_rom_instruction = {5'b01011, CMD_NOP, DELAY_MAX_VALUE[DELAY_SLOT_WIDTH-1:0]};
|
||||||
//15. Delay for read/write calibration
|
//15. Delay for read/write calibration
|
||||||
|
|
||||||
|
5'd16: read_rom_instruction = {5'b01011, CMD_NOP, tMOD};
|
||||||
|
//16. Delay for read/write calibration
|
||||||
|
|
||||||
// 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 12 to 15 will be re-used for the refresh sequence)
|
||||||
4'd16: read_rom_instruction = {5'b01011, CMD_PRE, ns_to_cycles(tRP)};
|
5'd17: read_rom_instruction = {5'b01111, CMD_PRE, ns_to_cycles(tRP)};
|
||||||
//12. 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.
|
//12. 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.
|
||||||
|
|
||||||
4'd17: read_rom_instruction = {5'b01011, CMD_REF, ns_to_cycles(tRFC)};
|
5'd18: read_rom_instruction = {5'b01011, CMD_REF, ns_to_cycles(tRFC)};
|
||||||
//13. A delay between the Refresh Command and the next valid command, except NOP or DES, must be greater than or equal to the minimum
|
//13. A delay between the Refresh Command and the next valid command, except NOP or DES, must be greater than or equal to the minimum
|
||||||
//Refresh cycle time tRFC(min)
|
//Refresh cycle time tRFC(min)
|
||||||
|
|
||||||
4'd18: read_rom_instruction = {5'b11011, CMD_NOP, ns_to_cycles(tREFI)};
|
5'd19: read_rom_instruction = {5'b11011, CMD_NOP, ns_to_cycles(tREFI)};
|
||||||
//14. Reset ends now. The refresh interval also starts to count.
|
//14. Reset ends now. The refresh interval also starts to count.
|
||||||
|
|
||||||
4'd19: read_rom_instruction = {5'b01011, CMD_NOP, PRE_STALL_DELAY[DELAY_SLOT_WIDTH-1:0]};
|
5'd20: read_rom_instruction = {5'b01011, CMD_NOP, PRE_STALL_DELAY[DELAY_SLOT_WIDTH-1:0]};
|
||||||
// 15. 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)
|
// 15. 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)
|
||||||
|
|
||||||
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}}};
|
||||||
|
|
@ -303,12 +309,14 @@ module ddr3_controller #(
|
||||||
//initial reset instruction has low rst_n, low cke, and has delay of 5
|
//initial reset instruction has low rst_n, low cke, and has delay of 5
|
||||||
localparam INITIAL_RESET_INSTRUCTION = {5'b01000 , CMD_NOP , { {(DELAY_SLOT_WIDTH-3){1'b0}} , 3'd5} };
|
localparam INITIAL_RESET_INSTRUCTION = {5'b01000 , CMD_NOP , { {(DELAY_SLOT_WIDTH-3){1'b0}} , 3'd5} };
|
||||||
|
|
||||||
reg[3:0] instruction_address = 0; //address for accessing rom instruction
|
reg[4:0] instruction_address = 0; //address for accessing rom instruction
|
||||||
reg[27:0] instruction = INITIAL_RESET_INSTRUCTION; //instruction retrieved from reset instruction rom
|
reg[27:0] instruction = INITIAL_RESET_INSTRUCTION; //instruction retrieved from reset instruction rom
|
||||||
reg[ DELAY_COUNTER_WIDTH - 1:0] delay_counter = INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0]; //counter used for delays
|
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 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 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
|
||||||
|
wire issue_read_command;
|
||||||
|
reg issue_write_command = 0;
|
||||||
always @(posedge i_controller_clk, negedge i_rst_n) begin
|
always @(posedge i_controller_clk, negedge i_rst_n) begin
|
||||||
if(!i_rst_n) begin
|
if(!i_rst_n) begin
|
||||||
instruction_address <= 0;
|
instruction_address <= 0;
|
||||||
|
|
@ -323,8 +331,10 @@ module ddr3_controller #(
|
||||||
`ifndef FORMAL_COVER
|
`ifndef FORMAL_COVER
|
||||||
delay_counter <= instruction[DELAY_COUNTER_WIDTH - 1:0]; //retrieve delay value of current instruction, we count to zero thus minus 1
|
delay_counter <= instruction[DELAY_COUNTER_WIDTH - 1:0]; //retrieve delay value of current instruction, we count to zero thus minus 1
|
||||||
`else
|
`else
|
||||||
if(instruction[DELAY_COUNTER_WIDTH - 1:0] > `COVER_DELAY) delay_counter <= `COVER_DELAY; //use fixed low value delay to cover the whole reset seqeunce using formal verification
|
//if(instruction[DELAY_COUNTER_WIDTH - 1:0] > `COVER_DELAY) delay_counter <= `COVER_DELAY; //use fixed low value delay to cover the whole reset seqeunce using formal verification
|
||||||
else delay_counter <= instruction[DELAY_COUNTER_WIDTH - 1:0] ; //use delay from rom if that is smaller than the COVER_DELAY macro
|
//else delay_counter <= instruction[DELAY_COUNTER_WIDTH - 1:0] ; //use delay from rom if that is smaller than the COVER_DELAY macro
|
||||||
|
if(instruction[DELAY_COUNTER_WIDTH - 1:0]!= DELAY_MAX_VALUE) delay_counter <= 20;
|
||||||
|
else delay_counter <= instruction[DELAY_COUNTER_WIDTH - 1:0];
|
||||||
`endif
|
`endif
|
||||||
//RECEIVE THE COMMANDS
|
//RECEIVE THE COMMANDS
|
||||||
end
|
end
|
||||||
|
|
@ -334,10 +344,10 @@ module ddr3_controller #(
|
||||||
|
|
||||||
//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]) 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 == 4'd15)? 4'd12:instruction_address+1; //instruction_address 15 must wrap back to instruction_address 12 for the refresh sequence
|
instruction_address <= (instruction_address == 5'd20)? 5'd17:instruction_address+1; //instruction_address 15 must wrap back to instruction_address 12 for the refresh sequence
|
||||||
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 delay_counter_is_zero <=0;
|
||||||
|
|
@ -453,7 +463,7 @@ module ddr3_controller #(
|
||||||
CALIBRATE_DQS = 5,
|
CALIBRATE_DQS = 5,
|
||||||
BITSLIP_DQS_TRAIN_2 = 6,
|
BITSLIP_DQS_TRAIN_2 = 6,
|
||||||
DONE_CALIBRATE = 7;
|
DONE_CALIBRATE = 7;
|
||||||
localparam REPEAT_DQS = 3; //must be >= 2
|
localparam REPEAT_DQS = 5; //must be >= 2
|
||||||
|
|
||||||
wire[(DQ_BITS*LANES)-1:0] oserdes_data, odelay_data, idelay_data, read_dq;
|
wire[(DQ_BITS*LANES)-1:0] oserdes_data, odelay_data, idelay_data, read_dq;
|
||||||
wire[LANES-1:0] odelay_dqs, read_dqs, idelay_dqs;
|
wire[LANES-1:0] odelay_dqs, read_dqs, idelay_dqs;
|
||||||
|
|
@ -474,7 +484,7 @@ module ddr3_controller #(
|
||||||
|
|
||||||
reg[3:0] state_calibrate;
|
reg[3:0] state_calibrate;
|
||||||
reg[REPEAT_DQS*8-1:0] dqs_store = 0;
|
reg[REPEAT_DQS*8-1:0] dqs_store = 0;
|
||||||
reg[$clog2(REPEAT_DQS)-1:0] dqs_count_repeat = 0;
|
reg[$clog2(REPEAT_DQS):0] dqs_count_repeat = 0;
|
||||||
reg[$clog2(REPEAT_DQS*8)-1:0] dqs_start_index = 0;
|
reg[$clog2(REPEAT_DQS*8)-1:0] dqs_start_index = 0;
|
||||||
reg[$clog2(REPEAT_DQS*8)-1:0] dqs_target_index = 0;
|
reg[$clog2(REPEAT_DQS*8)-1:0] dqs_target_index = 0;
|
||||||
reg[1:0] train_delay;
|
reg[1:0] train_delay;
|
||||||
|
|
@ -486,7 +496,7 @@ module ddr3_controller #(
|
||||||
reg[3:0] added_read_pipe_max = 0;
|
reg[3:0] added_read_pipe_max = 0;
|
||||||
reg[3:0] added_read_pipe[LANES - 1:0];
|
reg[3:0] added_read_pipe[LANES - 1:0];
|
||||||
|
|
||||||
reg[(READ_DELAY + 1 + 2):0] shift_reg_read_pipe_q, shift_reg_read_pipe_d; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay
|
reg[(READ_DELAY + 1 + 2 + 1):0] shift_reg_read_pipe_q, shift_reg_read_pipe_d; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay
|
||||||
reg index_read_pipe; //tells which delay_read_pipe will be updated
|
reg index_read_pipe; //tells which delay_read_pipe will be updated
|
||||||
reg[1:0] index_wb_data; //tells which o_wb_data_q will be sent to o_wb_data
|
reg[1:0] index_wb_data; //tells which o_wb_data_q will be sent to o_wb_data
|
||||||
reg[3:0] delay_read_pipe[1:0]; //delay when each lane will retrieve iserdes_data
|
reg[3:0] delay_read_pipe[1:0]; //delay when each lane will retrieve iserdes_data
|
||||||
|
|
@ -496,7 +506,6 @@ module ddr3_controller #(
|
||||||
always @(posedge i_controller_clk, negedge i_rst_n) begin
|
always @(posedge i_controller_clk, negedge i_rst_n) begin
|
||||||
if(!i_rst_n ) begin
|
if(!i_rst_n ) begin
|
||||||
o_wb_stall <= 1'b1;
|
o_wb_stall <= 1'b1;
|
||||||
o_wb_ack <= 1'b0;
|
|
||||||
//set stage 1 to 0
|
//set stage 1 to 0
|
||||||
stage1_pending <= 0;
|
stage1_pending <= 0;
|
||||||
stage1_we <= 0;
|
stage1_we <= 0;
|
||||||
|
|
@ -535,9 +544,8 @@ module ddr3_controller #(
|
||||||
end
|
end
|
||||||
|
|
||||||
// can only start accepting requests when reset is done
|
// can only start accepting requests when reset is done
|
||||||
else if(1/*reset_done*/) begin
|
else if(reset_done) begin
|
||||||
o_wb_stall <= o_wb_stall_d;
|
o_wb_stall <= o_wb_stall_d;
|
||||||
o_wb_ack <= o_wb_ack_d;
|
|
||||||
|
|
||||||
//update delay counter
|
//update delay counter
|
||||||
for(index=0; index< (1<<BA_BITS); index=index+1) begin
|
for(index=0; index< (1<<BA_BITS); index=index+1) begin
|
||||||
|
|
@ -629,19 +637,16 @@ module ddr3_controller #(
|
||||||
for(index = 0; index < 2; index = index + 1) begin
|
for(index = 0; index < 2; index = index + 1) begin
|
||||||
o_wb_data_q[index] <= 0;
|
o_wb_data_q[index] <= 0;
|
||||||
end
|
end
|
||||||
o_wb_ack <= 0;
|
|
||||||
o_wb_data <= 0;
|
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
shift_reg_read_pipe_q <= shift_reg_read_pipe_d;
|
shift_reg_read_pipe_q <= shift_reg_read_pipe_d;
|
||||||
|
for(index = 0; index < 2; index = index + 1) begin
|
||||||
|
delay_read_pipe[index] <= (delay_read_pipe[index] == 0)? 0 : (delay_read_pipe[index] - 1);
|
||||||
|
end
|
||||||
if(shift_reg_read_pipe_q[1]) begin //delay is over and data is now strating to release from iserdes BUT NOT YET ALIGNED
|
if(shift_reg_read_pipe_q[1]) begin //delay is over and data is now strating to release from iserdes BUT NOT YET ALIGNED
|
||||||
index_read_pipe <= !index_read_pipe; //control which delay_read_pipe would get updated (we have 3 pipe to store read data)
|
index_read_pipe <= !index_read_pipe; //control which delay_read_pipe would get updated (we have 3 pipe to store read data)
|
||||||
delay_read_pipe[index_read_pipe] <= added_read_pipe_max; //update delay_read_pipe
|
delay_read_pipe[index_read_pipe] <= added_read_pipe_max; //update delay_read_pipe
|
||||||
end
|
end
|
||||||
for(index = 0; index < 2; index = index + 1) begin
|
|
||||||
delay_read_pipe[index] <= (delay_read_pipe[index] == 0)? 0 : (delay_read_pipe[index] - 1);
|
|
||||||
end
|
|
||||||
|
|
||||||
for(index = 0; index < LANES; index = index + 1) begin
|
for(index = 0; index < LANES; index = index + 1) begin
|
||||||
//if(delay_before_read_ack_q == (added_read_pipe_max - added_read_pipe[index] + 1)) begin //same lane
|
//if(delay_before_read_ack_q == (added_read_pipe_max - added_read_pipe[index] + 1)) begin //same lane
|
||||||
if(delay_read_pipe[0] == (added_read_pipe_max != added_read_pipe[index])) begin //same lane
|
if(delay_read_pipe[0] == (added_read_pipe_max != added_read_pipe[index])) begin //same lane
|
||||||
|
|
@ -672,11 +677,11 @@ module ddr3_controller #(
|
||||||
o_wb_ack_read_q[index] <= o_wb_ack_read_q[index+1];
|
o_wb_ack_read_q[index] <= o_wb_ack_read_q[index+1];
|
||||||
end
|
end
|
||||||
o_wb_ack_read_q[added_read_pipe_max] <= shift_reg_read_pipe_q[0];
|
o_wb_ack_read_q[added_read_pipe_max] <= shift_reg_read_pipe_q[0];
|
||||||
o_wb_ack = o_wb_ack_read_q[0];
|
|
||||||
o_wb_data = o_wb_data_q[index_wb_data];
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
assign o_wb_ack = o_wb_ack_read_q[0];
|
||||||
|
assign o_wb_data = o_wb_data_q[index_wb_data];
|
||||||
// DIAGRAM FOR ALL RELEVANT TIMING PARAMETERS:
|
// DIAGRAM FOR ALL RELEVANT TIMING PARAMETERS:
|
||||||
//
|
//
|
||||||
// tRTP
|
// tRTP
|
||||||
|
|
@ -711,9 +716,14 @@ module ddr3_controller #(
|
||||||
bank_status_d[index] = bank_status_q[index];
|
bank_status_d[index] = bank_status_q[index];
|
||||||
bank_active_row_d[index] = bank_active_row_q[index];
|
bank_active_row_d[index] = bank_active_row_q[index];
|
||||||
end
|
end
|
||||||
//set all cmd_d to NOP
|
//set cmd_0 to reset instruction, the remainings are NOP
|
||||||
for(index=0; index < 4; index=index+1) begin
|
//delay_counter_is_zero signifies start of new reset instruction (the time when the command must be issued)
|
||||||
cmd_d[index] = -1;
|
cmd_d[PRECHARGE_SLOT] = {(!delay_counter_is_zero), instruction[DDR3_CMD_START-1:DDR3_CMD_END], 1'b0, instruction[CLOCK_EN], instruction[RESET_N],
|
||||||
|
instruction[MRS_BANK_START:(MRS_BANK_START-BA_BITS+1)], instruction[ROW_BITS-1:0]};
|
||||||
|
cmd_d[READ_SLOT] = {(!issue_read_command), CMD_RD[2:0], cmd_odt, cmd_ck_en, cmd_reset_n, {{ROW_BITS+BA_BITS}{1'b0}}};
|
||||||
|
cmd_d[WRITE_SLOT] = {(!issue_write_command),CMD_WR[2:0], cmd_odt, cmd_ck_en, cmd_reset_n, {{ROW_BITS+BA_BITS}{1'b0}}};
|
||||||
|
cmd_d[ACTIVATE_SLOT] = -1;
|
||||||
|
for(index=1; index < 4; index=index+1) begin
|
||||||
cmd_d[index][CMD_ODT] = (delay_before_odt_off_q != 0)? 1'b1: 1'b0; //ODT remains the same value
|
cmd_d[index][CMD_ODT] = (delay_before_odt_off_q != 0)? 1'b1: 1'b0; //ODT remains the same value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -771,9 +781,9 @@ module ddr3_controller #(
|
||||||
delay_before_read_counter_d[stage2_bank] = READ_TO_READ_DELAY;
|
delay_before_read_counter_d[stage2_bank] = READ_TO_READ_DELAY;
|
||||||
delay_before_write_counter_d[stage2_bank] = READ_TO_WRITE_DELAY;
|
delay_before_write_counter_d[stage2_bank] = READ_TO_WRITE_DELAY;
|
||||||
//delay_before_read_ack_d = READ_DELAY + 1 + 2 + 1; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay
|
//delay_before_read_ack_d = READ_DELAY + 1 + 2 + 1; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay
|
||||||
delay_before_read_ack_d = READ_DELAY + 1 + 2 + 1 + added_read_pipe_max + 1; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay, 1 = to register output
|
delay_before_read_ack_d = READ_DELAY + 1 + 2 + 1; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay, 1 = to register output
|
||||||
|
|
||||||
shift_reg_read_pipe_d[READ_DELAY + 1 + 2] = 1'b1;
|
shift_reg_read_pipe_d[READ_DELAY + 1 + 2 + 1] = 1'b1;
|
||||||
//issue read command
|
//issue read command
|
||||||
if(COL_BITS <= 10) begin
|
if(COL_BITS <= 10) begin
|
||||||
cmd_d[READ_SLOT] = {1'b0, CMD_RD[2:0], cmd_odt, cmd_ck_en, cmd_reset_n, {{ROW_BITS+BA_BITS-4'd11}{1'b0}} , 1'b0 , stage2_col[9:0]};
|
cmd_d[READ_SLOT] = {1'b0, CMD_RD[2:0], cmd_odt, cmd_ck_en, cmd_reset_n, {{ROW_BITS+BA_BITS-4'd11}{1'b0}} , 1'b0 , stage2_col[9:0]};
|
||||||
|
|
@ -1420,6 +1430,9 @@ module ddr3_controller #(
|
||||||
dqs_bitslip_arrangement <= 0;
|
dqs_bitslip_arrangement <= 0;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
|
skip_reset_seq_delay = 0;
|
||||||
|
//issue_read_command = 0;
|
||||||
|
issue_write_command = 0;
|
||||||
train_delay <= (train_delay==0)? 0:(train_delay - 1);
|
train_delay <= (train_delay==0)? 0:(train_delay - 1);
|
||||||
delay_before_read_data <= (delay_before_read_data == 0)? 0: delay_before_read_data - 1;
|
delay_before_read_data <= (delay_before_read_data == 0)? 0: delay_before_read_data - 1;
|
||||||
for(index=0; index < LANES; index=index+1) begin
|
for(index=0; index < LANES; index=index+1) begin
|
||||||
|
|
@ -1440,7 +1453,7 @@ module ddr3_controller #(
|
||||||
|
|
||||||
// FSM
|
// FSM
|
||||||
case(state_calibrate)
|
case(state_calibrate)
|
||||||
IDLE: if(idelayctrl_rdy) begin
|
IDLE: if(idelayctrl_rdy && instruction_address == 16) begin //we are now inside instruction 15 with maximum delay
|
||||||
state_calibrate <= BITSLIP_DQS_TRAIN_1;
|
state_calibrate <= BITSLIP_DQS_TRAIN_1;
|
||||||
lane <= 0;
|
lane <= 0;
|
||||||
end
|
end
|
||||||
|
|
@ -1462,8 +1475,10 @@ module ddr3_controller #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
MPR_READ: if(instruction_address == 15) begin //align the incoming DQS during reads to the controller clock
|
MPR_READ: begin //align the incoming DQS during reads to the controller clock
|
||||||
cmd_reset_seq[0] <= {1'b0, CMD_RD[2:0], 1'b0, 1'b1, 1'b1, MR3_RD_ADDR}; //read command
|
//skip_reset_seq_delay = 1;
|
||||||
|
//cmd_reset_seq[0] = {1'b0, CMD_RD[2:0], 1'b0, 1'b1, 1'b1, MR3_RD_ADDR}; //read command
|
||||||
|
//issue_read_command = 1;
|
||||||
delay_before_read_data <= READ_DELAY + 1 + 2 + 1; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay
|
delay_before_read_data <= READ_DELAY + 1 + 2 + 1; ///1=issue command delay (OSERDES delay), 2 = ISERDES delay
|
||||||
state_calibrate <= COLLECT_DQS;
|
state_calibrate <= COLLECT_DQS;
|
||||||
dqs_count_repeat <= 0;
|
dqs_count_repeat <= 0;
|
||||||
|
|
@ -1501,6 +1516,7 @@ module ddr3_controller #(
|
||||||
BITSLIP_DQS_TRAIN_2: if(train_delay == 0) begin //train again the ISERDES to capture the DQ correctly
|
BITSLIP_DQS_TRAIN_2: if(train_delay == 0) begin //train again the ISERDES to capture the DQ correctly
|
||||||
if(test_Q[lane] == dqs_bitslip_arrangement) begin
|
if(test_Q[lane] == dqs_bitslip_arrangement) begin
|
||||||
if(lane == 7) begin
|
if(lane == 7) begin
|
||||||
|
skip_reset_seq_delay = 1;
|
||||||
state_calibrate <= DONE_CALIBRATE;
|
state_calibrate <= DONE_CALIBRATE;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
|
|
@ -1515,9 +1531,11 @@ module ddr3_controller #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
DONE_CALIBRATE: state_calibrate <= DONE_CALIBRATE;
|
DONE_CALIBRATE: state_calibrate <= DONE_CALIBRATE;
|
||||||
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
assign issue_read_command = (state_calibrate == MPR_READ);
|
||||||
//////////////////////////////////////////////////////////////////////// End of PHY Interface ////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////// End of PHY Interface ////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue