749 lines
24 KiB
Verilog
749 lines
24 KiB
Verilog
module sdram_ctrl #
|
|
(
|
|
parameter COL_WIDTH = 8 ,//2^8 = 256 addresses in each colum
|
|
parameter ROW_WIDTH = 12 ,//2^12 = 4096 addresses in each bank
|
|
parameter BANK_WIDTH = 2 ,//2^2 = 4 banks in a single chip
|
|
parameter DQ_WIDTH = 8 ,//8 bit Data Bus for one chip
|
|
parameter [12:0] SDRAM_MR = 13'h0037 //Full Page Burst,Latency=3,Burst Read and Burst Write,Standard mode
|
|
) (
|
|
clk ,//The main clock of the control system
|
|
rst_n,//A low voltage may bring the control system to an oringinal state,but the data in SDRAM may be damaged
|
|
|
|
user_command_req ,//The user want to send a read/write command,active HIGH
|
|
user_command_gnt ,//The state machine have accept the user's read/write command
|
|
user_rd0_wr1 ,//HIGH voltage means read and a low means write,synchronous to "user_command_req"
|
|
user_burst_length,//Express the read/write lenghth of each command,synchronous to "user_command_req"
|
|
user_start_addr ,//the user's read/write address,synchronous to "user_command_req"
|
|
Tx_fifo_rd_en ,//used in the user's write command,this port is synchronous to "clk"
|
|
Tx_fifo_rd_data ,//the user write data to the fifo,synchronous to "clk"
|
|
|
|
sdram_cke ,
|
|
sdram_cs_n ,
|
|
sdram_ras_n ,
|
|
sdram_cas_n ,
|
|
sdram_we_n ,
|
|
sdram_ba ,
|
|
sdram_addr ,
|
|
sdram_dq_out_en,
|
|
sdram_dqm ,
|
|
sdram_dq_out ,
|
|
sdram_dq_in ,
|
|
|
|
sdram_data_valid,//tell the user that valid read data is coming,active HIGH
|
|
sdram_rd_data //synchronous to sdram_data_valid
|
|
);
|
|
|
|
|
|
input clk;
|
|
input rst_n;
|
|
|
|
input user_command_req;
|
|
output user_command_gnt;
|
|
input user_rd0_wr1;
|
|
input [COL_WIDTH-1:0] user_burst_length;
|
|
input [BANK_WIDTH+ROW_WIDTH+COL_WIDTH-1 : 0] user_start_addr;
|
|
output Tx_fifo_rd_en;
|
|
input [DQ_WIDTH/8+DQ_WIDTH-1 :0 ] Tx_fifo_rd_data;
|
|
|
|
output sdram_cke;
|
|
output sdram_cs_n;
|
|
output sdram_ras_n;
|
|
output sdram_cas_n;
|
|
output sdram_we_n;
|
|
output [BANK_WIDTH-1 : 0] sdram_ba;
|
|
output [ROW_WIDTH-1 : 0] sdram_addr;
|
|
output sdram_dq_out_en;
|
|
output [DQ_WIDTH/8-1: 0] sdram_dqm;
|
|
output [DQ_WIDTH-1 : 0] sdram_dq_out;
|
|
input [DQ_WIDTH-1 : 0] sdram_dq_in;
|
|
|
|
output sdram_data_valid;
|
|
output [DQ_WIDTH-1 : 0] sdram_rd_data;
|
|
|
|
parameter [9:0] Refresh_Period = 10'd781;//when clk is 100MHz,8192 Refresh cycles happens very 64ms
|
|
|
|
reg [9:0] Refresh_cnt;
|
|
always @ (posedge clk)//account for Refresh_INT
|
|
begin
|
|
if(!rst_n)
|
|
Refresh_cnt <= 10'd0;
|
|
else if(Refresh_cnt != Refresh_Period)
|
|
Refresh_cnt <= Refresh_cnt + 1'b1;
|
|
else
|
|
Refresh_cnt <= 10'd0;
|
|
end
|
|
|
|
reg Refresh_INT;
|
|
wire Refresh_INT_clear;
|
|
always @ (posedge clk)//A refresh command should be excuted when Refresh_INT is High
|
|
begin
|
|
if(!rst_n)
|
|
Refresh_INT <= 1'b0;
|
|
else if(Refresh_cnt == Refresh_Period)
|
|
Refresh_INT <= 1'b1;
|
|
else if(Refresh_INT_clear)
|
|
Refresh_INT <= 1'b0;
|
|
end
|
|
|
|
wire user_INT;
|
|
assign user_INT = user_command_req;//A read/write command should be excuted when user_INT is High
|
|
|
|
reg user_command_gnt;
|
|
|
|
reg user_rd0_wr1_buf;
|
|
reg [COL_WIDTH-1:0] user_burst_length_buf;
|
|
reg [BANK_WIDTH+ROW_WIDTH+COL_WIDTH-1 : 0] user_start_addr_buf;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
begin
|
|
user_rd0_wr1_buf <= 1'b0;
|
|
user_burst_length_buf <= 1'b0;
|
|
user_start_addr_buf <= 1'b0;
|
|
end
|
|
else if(user_command_gnt)
|
|
begin
|
|
user_rd0_wr1_buf <= user_rd0_wr1;
|
|
user_burst_length_buf <= user_burst_length;
|
|
user_start_addr_buf <= user_start_addr;
|
|
end
|
|
end
|
|
|
|
parameter [3:0]
|
|
Initialize = 4'b0001,
|
|
Wait_Interrupt = 4'b0010,
|
|
Response_Refresh_INT = 4'b0100,
|
|
Response_user_INT = 4'b1000;
|
|
|
|
reg [3:0] SDRAM_state;
|
|
reg Initialize_done;
|
|
reg Response_Refresh_INT_done;
|
|
reg Response_user_INT_done;
|
|
always @ (posedge clk)//SDRAM state machine
|
|
begin
|
|
if(!rst_n)
|
|
SDRAM_state <= Initialize;
|
|
else
|
|
case(SDRAM_state)
|
|
Initialize :
|
|
if(Initialize_done)
|
|
SDRAM_state <= Wait_Interrupt;
|
|
Wait_Interrupt :
|
|
if(Refresh_INT)
|
|
SDRAM_state <= Response_Refresh_INT;
|
|
else if(user_INT)
|
|
SDRAM_state <= Response_user_INT;
|
|
else
|
|
SDRAM_state <= Wait_Interrupt;
|
|
Response_Refresh_INT :
|
|
if(Response_Refresh_INT_done)
|
|
SDRAM_state <= Wait_Interrupt;
|
|
else
|
|
SDRAM_state <= Response_Refresh_INT;
|
|
Response_user_INT :
|
|
if(Response_user_INT_done)
|
|
SDRAM_state <= Wait_Interrupt;
|
|
default:
|
|
SDRAM_state <= Initialize;
|
|
endcase
|
|
end
|
|
|
|
parameter
|
|
tRP_period = 8'd2,//3 clock period
|
|
tRC_period = 8'd11,//12 clock period
|
|
tMRD_period = 8'd1,//2 clock period
|
|
tRCD_period = 8'd2;//3 clock period
|
|
|
|
reg [COL_WIDTH-1:0] Delay_cnt;
|
|
reg cnt_overflow;
|
|
|
|
parameter [9:0]
|
|
Initialize_NOP_Command = 10'b00_0000_0001,
|
|
Initialize_Precharge_All_Bank = 10'b00_0000_0010,
|
|
Initialize_Precharge_tRP = 10'b00_0000_0100,
|
|
Initialize_Auto_Refresh_Command1 = 10'b00_0000_1000,
|
|
Initialize_Auto_Refresh_tRC1 = 10'b00_0001_0000,
|
|
Initialize_Auto_Refresh_Command2 = 10'b00_0010_0000,
|
|
Initialize_Auto_Refresh_tRC2 = 10'b00_0100_0000,
|
|
Load_Mode_Register_Command = 10'b00_1000_0000,
|
|
Load_Mode_Register_tMRD = 10'b01_0000_0000,
|
|
Initialize_Finish = 10'b10_0000_0000;
|
|
|
|
reg [9:0] Initialize_state;
|
|
always @ (posedge clk)//Initialize state machine
|
|
begin
|
|
if(!rst_n)
|
|
Initialize_state <= Initialize_NOP_Command;
|
|
else if(SDRAM_state == Initialize)
|
|
case(Initialize_state)
|
|
Initialize_NOP_Command ://A NOP Command before Precharge
|
|
Initialize_state <= Initialize_Precharge_All_Bank;
|
|
Initialize_Precharge_All_Bank ://Precharge Command,all banks
|
|
Initialize_state <= Initialize_Precharge_tRP;
|
|
Initialize_Precharge_tRP ://tRP period,with NOP Command
|
|
if(cnt_overflow)
|
|
Initialize_state <= Initialize_Auto_Refresh_Command1;
|
|
Initialize_Auto_Refresh_Command1 ://The Frist Auto Refresh Command
|
|
Initialize_state <= Initialize_Auto_Refresh_tRC1;
|
|
Initialize_Auto_Refresh_tRC1 ://tRC period,with NOP Command
|
|
if(cnt_overflow)
|
|
Initialize_state <= Initialize_Auto_Refresh_Command2;
|
|
Initialize_Auto_Refresh_Command2 ://The Second Auto Refresh Command
|
|
Initialize_state <= Initialize_Auto_Refresh_tRC2;
|
|
Initialize_Auto_Refresh_tRC2 ://tRC period,with NOP Command
|
|
if(cnt_overflow)
|
|
Initialize_state <= Load_Mode_Register_Command;
|
|
Load_Mode_Register_Command ://Load Mode Register
|
|
Initialize_state <= Load_Mode_Register_tMRD;
|
|
Load_Mode_Register_tMRD ://tMRD period,with NOP Command
|
|
if(cnt_overflow)
|
|
Initialize_state <= Initialize_Finish;
|
|
Initialize_Finish : ;
|
|
default:
|
|
Initialize_state <= Initialize_NOP_Command;
|
|
endcase
|
|
else
|
|
Initialize_state <= Initialize_NOP_Command;
|
|
end
|
|
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
Initialize_done <= 1'b0;
|
|
else if(Initialize_state==Initialize_Finish)
|
|
Initialize_done <= 1'b1;
|
|
else
|
|
Initialize_done <= 1'b0;
|
|
end
|
|
|
|
parameter [3:0]
|
|
Refresh_NOP_Command = 4'b0001,
|
|
Refresh_Auto_Refresh_Command = 4'b0010,
|
|
Refresh_Auto_Refresh_tRC = 4'b0100,
|
|
Refresh_Finish = 4'b1000;
|
|
|
|
reg [3:0] Refresh_Response_state;
|
|
always @ (posedge clk)//Refresh response state machine
|
|
begin
|
|
if(!rst_n)
|
|
Refresh_Response_state <= Refresh_NOP_Command;
|
|
else if(SDRAM_state == Response_Refresh_INT)
|
|
case(Refresh_Response_state)
|
|
Refresh_NOP_Command ://Exit Power-Down state(if it's in) with NOP Command
|
|
Refresh_Response_state <= Refresh_Auto_Refresh_Command;
|
|
Refresh_Auto_Refresh_Command ://Auto Refresh Command
|
|
Refresh_Response_state <= Refresh_Auto_Refresh_tRC;
|
|
Refresh_Auto_Refresh_tRC ://tRC period,with NOP Command
|
|
if(cnt_overflow)
|
|
Refresh_Response_state <= Refresh_Finish;
|
|
Refresh_Finish : ;
|
|
default:
|
|
Refresh_Response_state <= Refresh_NOP_Command;
|
|
endcase
|
|
else
|
|
Refresh_Response_state <= Refresh_NOP_Command;
|
|
end
|
|
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
Response_Refresh_INT_done <= 1'b0;
|
|
else if(Refresh_Response_state==Refresh_Auto_Refresh_tRC&&cnt_overflow)
|
|
Response_Refresh_INT_done <= 1'b1;
|
|
else
|
|
Response_Refresh_INT_done <= 1'b0;
|
|
end
|
|
|
|
assign Refresh_INT_clear = (Refresh_Response_state==Refresh_Auto_Refresh_Command);
|
|
|
|
parameter [6:0]
|
|
user_Response_start_NOP = 7'b0000001,
|
|
user_Response_Bank_activation = 7'b0000010,
|
|
user_Response_tRCD = 7'b0000100,
|
|
user_Response_Column_Selection = 7'b0001000,
|
|
user_Response_wait_Precharge1 = 7'b0010000,
|
|
user_Response_wait_Precharge2 = 7'b0100000,
|
|
user_Response_end_NOP = 7'b1000000;
|
|
|
|
reg [6:0] user_Response_state;
|
|
always @ (posedge clk)//user response state machine
|
|
begin
|
|
if(!rst_n)
|
|
user_Response_state <= user_Response_start_NOP;
|
|
else if(SDRAM_state == Response_user_INT)
|
|
case(user_Response_state)
|
|
user_Response_start_NOP ://Exit Power-Down state with NOP Command
|
|
user_Response_state <= user_Response_Bank_activation;
|
|
user_Response_Bank_activation ://Bank/Row activation
|
|
user_Response_state <= user_Response_tRCD;
|
|
user_Response_tRCD ://tRCD period,with NOP Command
|
|
if(cnt_overflow)
|
|
user_Response_state <= user_Response_Column_Selection;
|
|
user_Response_Column_Selection ://Column Selection
|
|
user_Response_state <= user_Response_wait_Precharge1;
|
|
user_Response_wait_Precharge1://Wait to Precharge, this state only generate precharge for burst read
|
|
if(cnt_overflow)
|
|
begin
|
|
if(!user_rd0_wr1_buf)//if is read busrt
|
|
user_Response_state <= user_Response_end_NOP;
|
|
else//write busrt
|
|
user_Response_state <= user_Response_wait_Precharge2;
|
|
end
|
|
user_Response_wait_Precharge2://This state is special for the precharge of busrt write
|
|
user_Response_state <= user_Response_end_NOP;
|
|
user_Response_end_NOP : ;
|
|
default :
|
|
user_Response_state <= user_Response_start_NOP;
|
|
endcase
|
|
else
|
|
user_Response_state <= user_Response_start_NOP;
|
|
end
|
|
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
Response_user_INT_done <= 1'b0;
|
|
else if(user_Response_state==user_Response_end_NOP&&SDRAM_state == Response_user_INT)
|
|
Response_user_INT_done <= 1'b1;
|
|
else
|
|
Response_user_INT_done <= 1'b0;
|
|
end
|
|
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
user_command_gnt <= 1'b0;
|
|
else
|
|
case(SDRAM_state)
|
|
Wait_Interrupt:
|
|
if(!Refresh_INT&&user_INT)
|
|
user_command_gnt <= 1'b1;
|
|
else
|
|
user_command_gnt <= 1'b0;
|
|
default:
|
|
user_command_gnt <= 1'b0;
|
|
endcase
|
|
end
|
|
|
|
reg [COL_WIDTH-1:0] Delay_set;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
Delay_set <= 1'b0;
|
|
else
|
|
case(SDRAM_state)
|
|
Initialize:
|
|
case(Initialize_state)
|
|
Initialize_NOP_Command ://load tRP period
|
|
Delay_set <= tRP_period;
|
|
Initialize_Precharge_tRP://load tRC period
|
|
if(cnt_overflow)
|
|
Delay_set <= tRC_period;
|
|
Initialize_Auto_Refresh_tRC1 ://load tRC period
|
|
if(cnt_overflow)
|
|
Delay_set <= tRC_period;
|
|
Initialize_Auto_Refresh_tRC2 ://load tMRD period
|
|
if(cnt_overflow)
|
|
Delay_set <= tMRD_period;
|
|
endcase
|
|
Response_Refresh_INT:
|
|
case(Refresh_Response_state)
|
|
Refresh_NOP_Command ://load tRC period
|
|
Delay_set <= tRC_period;
|
|
endcase
|
|
Response_user_INT:
|
|
case(user_Response_state)
|
|
user_Response_start_NOP://load tRCD period
|
|
Delay_set <= tRCD_period;
|
|
user_Response_tRCD ://load user burst length period
|
|
if(cnt_overflow)
|
|
Delay_set <= user_burst_length_buf;
|
|
endcase
|
|
endcase
|
|
end
|
|
|
|
always @ (posedge clk)//Delay_cnt
|
|
begin
|
|
if(!rst_n)
|
|
Delay_cnt <= 1'b0;
|
|
else
|
|
case(SDRAM_state)
|
|
Initialize:
|
|
case(Initialize_state)
|
|
Initialize_Precharge_All_Bank ,//cnt for tRP period
|
|
Initialize_Auto_Refresh_Command1 ,//cnt for tRC period
|
|
Initialize_Auto_Refresh_Command2 ,//cnt for tRC period
|
|
Load_Mode_Register_Command ://cnt for tMRD period
|
|
Delay_cnt <= Delay_cnt + 1'b1;
|
|
Initialize_Precharge_tRP ,//cnt for tRP period
|
|
Initialize_Auto_Refresh_tRC1 ,//cnt for tRC period
|
|
Initialize_Auto_Refresh_tRC2 ,//cnt for tRC period
|
|
Load_Mode_Register_tMRD ://cnt for tMRD period
|
|
if(cnt_overflow)
|
|
Delay_cnt <= 1'b0;
|
|
else
|
|
Delay_cnt <= Delay_cnt + 1'b1;
|
|
endcase
|
|
Response_Refresh_INT:
|
|
case(Refresh_Response_state)
|
|
Refresh_Auto_Refresh_Command ://cnt for tRC period
|
|
Delay_cnt <= Delay_cnt + 1'b1;
|
|
Refresh_Auto_Refresh_tRC ://cnt for tRC period
|
|
if(cnt_overflow)
|
|
Delay_cnt <= 1'b0;
|
|
else
|
|
Delay_cnt <= Delay_cnt + 1'b1;
|
|
endcase
|
|
Response_user_INT:
|
|
case(user_Response_state)
|
|
user_Response_Bank_activation ,//cnt for tRCD period
|
|
user_Response_Column_Selection ://cnt for user burst length
|
|
Delay_cnt <= Delay_cnt + 1'b1;
|
|
user_Response_tRCD ,//cnt for tRCD period
|
|
user_Response_wait_Precharge1 ://cnt for user burst length
|
|
if(cnt_overflow)
|
|
Delay_cnt <= 1'b0;
|
|
else
|
|
Delay_cnt <= Delay_cnt + 1'b1;
|
|
endcase
|
|
endcase
|
|
end
|
|
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
cnt_overflow <= 1'b0;
|
|
else if(Delay_cnt==Delay_set)
|
|
cnt_overflow <= 1'b1;
|
|
else
|
|
cnt_overflow <= 1'b0;
|
|
end
|
|
|
|
reg [3:0] sdram_data_valid_buff;
|
|
always @ (posedge clk)//sdram_data_valid_buff
|
|
begin
|
|
if(!rst_n)
|
|
sdram_data_valid_buff <= 4'b0;
|
|
else if(user_Response_state==user_Response_wait_Precharge1 && user_rd0_wr1_buf==1'b0)
|
|
sdram_data_valid_buff <= {sdram_data_valid_buff[2:0],1'b1};
|
|
else
|
|
sdram_data_valid_buff <= {sdram_data_valid_buff[2:0],1'b0};
|
|
end
|
|
|
|
reg sdram_data_valid;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(SDRAM_MR[5:4]==2'b11)//CAS Latency = 3
|
|
sdram_data_valid <= sdram_data_valid_buff[3];
|
|
else//other CAS Latency, treated it as 2
|
|
sdram_data_valid <= sdram_data_valid_buff[2];
|
|
end
|
|
|
|
reg [DQ_WIDTH-1:0] sdram_rd_data;
|
|
always @ (posedge clk)
|
|
begin
|
|
sdram_rd_data <= sdram_dq_in;
|
|
end
|
|
|
|
reg Tx_fifo_rd_en;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
Tx_fifo_rd_en <= 1'b0;
|
|
else if(user_rd0_wr1_buf)
|
|
case(user_Response_state)
|
|
user_Response_tRCD:
|
|
if(cnt_overflow)
|
|
Tx_fifo_rd_en <= 1'b1;
|
|
user_Response_Column_Selection,
|
|
user_Response_wait_Precharge1:
|
|
if(Delay_cnt==Delay_set)
|
|
Tx_fifo_rd_en <= 1'b0;
|
|
endcase
|
|
else
|
|
Tx_fifo_rd_en <= 1'b0;
|
|
end
|
|
|
|
reg sdram_dq_out_en;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
sdram_dq_out_en <= 1'b0;
|
|
else
|
|
sdram_dq_out_en <= Tx_fifo_rd_en;
|
|
end
|
|
|
|
assign sdram_dq_out = Tx_fifo_rd_data[DQ_WIDTH-1 : 0];
|
|
|
|
reg dqm_for_read_mask;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
dqm_for_read_mask <= 1'b0;
|
|
else
|
|
case(user_Response_state)
|
|
user_Response_Column_Selection:
|
|
if(!user_rd0_wr1_buf)
|
|
dqm_for_read_mask <= 1'b1;
|
|
user_Response_end_NOP:
|
|
dqm_for_read_mask <= 1'b0;
|
|
endcase
|
|
end
|
|
|
|
reg dqm_for_write_mask;
|
|
always @ (posedge clk)
|
|
begin
|
|
if(!rst_n)
|
|
dqm_for_write_mask <= 1'b0;
|
|
else
|
|
dqm_for_write_mask <= Tx_fifo_rd_en;
|
|
end
|
|
|
|
reg [DQ_WIDTH/8-1: 0] sdram_dqm;
|
|
always @ ( * )
|
|
begin
|
|
if(dqm_for_read_mask)
|
|
sdram_dqm <= {(DQ_WIDTH/8){1'b0}};
|
|
else if(dqm_for_write_mask)
|
|
sdram_dqm <= Tx_fifo_rd_data[DQ_WIDTH/8+DQ_WIDTH-1 :DQ_WIDTH];
|
|
else
|
|
sdram_dqm <= {(DQ_WIDTH/8){1'b1}};
|
|
end
|
|
|
|
reg sdram_cke;
|
|
reg sdram_cs_n;
|
|
reg sdram_ras_n;
|
|
reg sdram_cas_n;
|
|
reg sdram_we_n;
|
|
reg [BANK_WIDTH-1 : 0] sdram_ba;
|
|
reg [ROW_WIDTH-1 : 0] sdram_addr;
|
|
|
|
always @ (posedge clk)//call the tasks
|
|
begin
|
|
if(!rst_n)
|
|
begin
|
|
sdram_ba <= 1'b0;
|
|
sdram_addr <= 1'b0;
|
|
Device_Deselect(1'b0);
|
|
end
|
|
else
|
|
case(SDRAM_state)
|
|
Initialize:
|
|
case(Initialize_state)
|
|
Initialize_NOP_Command :
|
|
No_Operation(1'b1);//this task can be replaced by Precharge_Power_Down_Exit
|
|
Initialize_Precharge_All_Bank :
|
|
Precharge_All_Banks(1'b1);
|
|
Initialize_Precharge_tRP :
|
|
No_Operation(1'b1);
|
|
Initialize_Auto_Refresh_Command1 :
|
|
Auto_Refresh;
|
|
Initialize_Auto_Refresh_tRC1 :
|
|
No_Operation(1'b1);
|
|
Initialize_Auto_Refresh_Command2 :
|
|
Auto_Refresh;
|
|
Initialize_Auto_Refresh_tRC2 :
|
|
No_Operation(1'b1);
|
|
Load_Mode_Register_Command :
|
|
begin
|
|
sdram_ba <= 2'b0;
|
|
sdram_addr <= SDRAM_MR;
|
|
Mode_Register_Set(1'b1);
|
|
end
|
|
Load_Mode_Register_tMRD :
|
|
No_Operation(1'b1);
|
|
default : ;
|
|
endcase
|
|
Wait_Interrupt:
|
|
No_Operation(1'b0);//this task can be replaced by Precharge_Power_Down_Entry
|
|
Response_Refresh_INT:
|
|
case(Refresh_Response_state)
|
|
Refresh_NOP_Command :
|
|
No_Operation(1'b1);//this task can be replaced by Precharge_Power_Down_Exit
|
|
Refresh_Auto_Refresh_Command :
|
|
Auto_Refresh;
|
|
Refresh_Auto_Refresh_tRC :
|
|
No_Operation(1'b1);
|
|
default : ;
|
|
endcase
|
|
Response_user_INT:
|
|
case(user_Response_state)
|
|
user_Response_start_NOP :
|
|
No_Operation(1'b1);//this task can be replaced by Precharge_Power_Down_Exit
|
|
user_Response_Bank_activation :
|
|
begin
|
|
sdram_ba <= user_start_addr_buf[BANK_WIDTH+ROW_WIDTH+COL_WIDTH-1 : ROW_WIDTH+COL_WIDTH];
|
|
sdram_addr <= user_start_addr_buf[ROW_WIDTH+COL_WIDTH-1 : COL_WIDTH];
|
|
Bank_Active(1'b1);
|
|
end
|
|
user_Response_tRCD :
|
|
No_Operation(1'b1);
|
|
user_Response_Column_Selection :
|
|
begin
|
|
sdram_addr[COL_WIDTH-1 : 0] <= user_start_addr_buf[COL_WIDTH-1 : 0];
|
|
if(user_rd0_wr1_buf)
|
|
Write(1'b1);
|
|
else
|
|
Read(1'b1);
|
|
end
|
|
user_Response_wait_Precharge1 :
|
|
if(cnt_overflow&&!user_rd0_wr1_buf)//only generate precharge cmd when busrt read
|
|
Precharge_All_Banks(1'b1);//this task can be replaced by Precharge_selected_Bank(1'b1)
|
|
else
|
|
No_Operation(1'b1);
|
|
user_Response_wait_Precharge2 :
|
|
Precharge_All_Banks(1'b1);//this task can be replaced by Precharge_selected_Bank(1'b1)
|
|
user_Response_end_NOP :
|
|
No_Operation(1'b1);
|
|
endcase
|
|
default:
|
|
No_Operation(1'b1);
|
|
endcase
|
|
end
|
|
|
|
//the following tasks descript the TRUTH TABLE of SDRAM command//
|
|
task Device_Deselect;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b1111};
|
|
end
|
|
endtask
|
|
|
|
task No_Operation;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0111};
|
|
end
|
|
endtask
|
|
|
|
task Mode_Register_Set;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0000};
|
|
end
|
|
endtask
|
|
|
|
task Bank_Active;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0011};
|
|
end
|
|
endtask
|
|
|
|
task Precharge_selected_Bank;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0010};
|
|
sdram_addr[10] <= 1'b0;
|
|
end
|
|
endtask
|
|
|
|
task Precharge_All_Banks;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0010};
|
|
sdram_addr[10] <= 1'b1;
|
|
end
|
|
endtask
|
|
|
|
task Read;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0101};
|
|
sdram_addr[10] <= 1'b0;
|
|
end
|
|
endtask
|
|
|
|
task Read_with_Autoprecharge;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0101};
|
|
sdram_addr[10] <= 1'b1;
|
|
end
|
|
endtask
|
|
|
|
task Write;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0100};
|
|
sdram_addr[10] <= 1'b0;
|
|
end
|
|
endtask
|
|
|
|
task Write_with_Autoprecharge;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0100};
|
|
sdram_addr[10] <= 1'b1;
|
|
end
|
|
endtask
|
|
|
|
task Burst_stop;//CKE should be HIGH at the last clock period
|
|
input CKE;
|
|
begin
|
|
sdram_cke <= CKE;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0110};
|
|
end
|
|
endtask
|
|
|
|
task Auto_Refresh;//CKE should be HIGH at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b1;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0001};
|
|
end
|
|
endtask
|
|
|
|
task Self_Refresh_Entry;//CKE should be HIGH at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b0;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0001};
|
|
end
|
|
endtask
|
|
|
|
task Self_Refresh_Exit;//CKE should be LOW at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b1;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0111};
|
|
end
|
|
endtask
|
|
|
|
task Precharge_Power_Down_Entry;//CKE should be HIGH at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b0;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0111};
|
|
end
|
|
endtask
|
|
|
|
task Precharge_Power_Down_Exit;//CKE should be LOW at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b1;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b0111};
|
|
end
|
|
endtask//same with Self_Refresh_Exit
|
|
|
|
task Clock_Suspend_Entry;//CKE should be HIGH at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b0;
|
|
{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b1111};
|
|
end
|
|
endtask
|
|
|
|
task Clock_Suspend_Exit;//CKE should be LOW at the last clock period
|
|
begin
|
|
sdram_cke <= 1'b1;
|
|
//{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= {4'b1111};
|
|
end
|
|
endtask
|
|
//all tasks end here//
|
|
|
|
endmodule
|