SDRAM接口练习2
在SDRAM接口练习1的基础上,补充写状态。
- 当初始化完成后,处于IDLE状态,此时如接口wr_req为1,则表示需要进行写操作。
- 写模式为全页模式,该模式在写完成时,给出预充电命令结束。datasheetP52
- 为简化,自动刷新不打断写操作。1562-1300
写(写激活、写操作、预充电)一共256+3+3=262
`timescale 1ns / 1ns
//:
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2021/07/01 12:47:44
// Design Name:
// Module Name: work_2
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module work_2(clk,rst_n,wr_req,waddr,wdata,wr_ack,cke,cs,ras,cas,we,dqm,addr,bank,dq);
input clk;
input rst_n;
input wr_req;
input [21:0] waddr;// without [21:0], bank<=waddr[21:20] error
input [15:0] wdata;
output wr_ack;
input cke;
output cs;
output ras;
output cas;
output we;
output dqm;
output addr;
output bank;
output dq;
parameter T=10;
parameter T_NOP=10000;
parameter TRP=2;
parameter TRC=6;
parameter TMRD=2;
parameter TRCD=3;
parameter MODE_VALUE = 12'b0000_0010_0111;
//7???
parameter INIT_NOP = 1;//
parameter INIT_CHARGE = 2;//
parameter INIT_REF1 = 3;//
parameter INIT_REF2 = 4;//
parameter INIT_MODE = 5;//
parameter ST_IDLE = 6;//
parameter ST_REF = 7;//
parameter WR_ACTIVE = 8;
parameter WR_WRITE = 9;
parameter WR_CHARGE = 10;
reg cs;
reg ras;
reg cas;
reg we;
reg wr_ack;
reg [1:0] dqm;
reg [11:0] addr;
reg [1:0] bank;
reg [15:0] dq;
reg [3:0] state_c;//10
reg [3:0] state_n;
reg [13:0] count;
reg [13:0] x;//2^14=2048*8>10000
reg [10:0] count1;//2^11=2048
reg [3:0] command;
wire INIT_NOP2CHARGE;
wire INIT_CHARGE2REF1;
wire INIT_REF12REF2;
wire INIT_REF22MODE;
wire MODE2IDLE ;
wire ST_IDLE2REF;
wire ST_REF2IDLE;
wire IDLE2ACTIVE;
wire WR_ACTIVE2WRITE;
wire WR_WRITE2CHARGE ;
wire CHARGE2IDLE ;
assign INIT_NOP2CHARGE = (state_c == INIT_NOP) && (count==1);
assign INIT_CHARGE2REF1= (state_c == INIT_CHARGE) && (count==1);
assign INIT_REF12REF2 = (state_c == INIT_REF1) && (count==1);
assign INIT_REF22MODE = (state_c == INIT_REF2) && (count==1);
assign MODE2IDLE = ((state_c == INIT_MODE) && (count==1));
assign ST_IDLE2REF = (state_c == ST_IDLE) && (count1==1) && (wr_req==0);//
assign ST_REF2IDLE = (state_c == ST_REF) && (count==1) ;//
assign IDLE2ACTIVE = (state_c == ST_IDLE) && (count==1) && (wr_req==1);
assign WR_ACTIVE2WRITE = (state_c == WR_ACTIVE) && (count==1);
assign WR_WRITE2CHARGE = (state_c == WR_WRITE) && (count==1);
assign CHARGE2IDLE = (state_c == WR_CHARGE) && (count==1);
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_c<=INIT_NOP;
end
else begin
state_c<=state_n;
end
end
always @ (*) begin
if (!rst_n) begin
state_n=state_c;
end
else begin
case (state_c)
INIT_NOP : begin//1
if (INIT_NOP2CHARGE) begin
state_n=INIT_CHARGE;
end
else begin
state_n=state_c;
end
end
INIT_CHARGE : begin//2
if (INIT_CHARGE2REF1) begin
state_n=INIT_REF1;
end
else begin
state_n=state_c;
end
end
INIT_REF1 : begin//3
if (INIT_REF12REF2) begin
state_n=INIT_REF2;
end
else begin
state_n=state_c;
end
end
INIT_REF2 : begin//4
if (INIT_REF22MODE) begin
state_n=INIT_MODE;
end
else begin
state_n=state_c;
end
end
INIT_MODE : begin//5
if (MODE2IDLE) begin
state_n=ST_IDLE;
end
else begin
state_n=state_c;
end
end
ST_IDLE : begin//6
if (ST_IDLE2REF) begin
state_n=ST_REF;
end
else if (IDLE2ACTIVE) begin
state_n=WR_ACTIVE;
end
else begin
state_n=state_c;
end
end
ST_REF : begin//7
if (ST_REF2IDLE) begin
state_n=ST_IDLE;
end
else begin
state_n=state_c;
end
end
WR_ACTIVE : begin//8
if (WR_ACTIVE2WRITE) begin
state_n=WR_WRITE;
end
else begin
state_n=state_c;
end
end
WR_WRITE : begin//9
if (WR_WRITE2CHARGE) begin
state_n=WR_CHARGE;
end
else begin
state_n=state_c;
end
end
WR_CHARGE : begin//10
if (CHARGE2IDLE) begin
state_n=ST_IDLE;
end
else begin
state_n=state_c;
end
end
default : begin//default
state_n=INIT_NOP;
end
endcase
end
end
//
always @(*)begin
if(state_c==INIT_CHARGE || state_c==WR_CHARGE) begin//2 10
x = TRP;
end
else if(state_c==INIT_REF1 || state_c==INIT_REF2 || state_c==ST_REF)begin// 347
x = TRC;
end
else if(state_c==INIT_MODE)begin//5
x = TMRD;
end
else if(state_c==WR_ACTIVE)begin//8
x = TRCD;
end
else if(state_c==WR_WRITE)begin//9
x = 256;
end
else begin
x = T_NOP;//1
end
end
//count
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
count<= T_NOP-1;
end
else begin
if (count==0)
count<= x-1;
else
count<=count-1;
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
count1<=1300-1;
end
else if (state_c==ST_IDLE) begin//6
if (count==0)
count1<= 1300-1;
else
count1<=count-1;
end
else begin
count1<= 1300-1;
end
end
//command
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
command<=4'b0111;
end
else begin
if (INIT_NOP2CHARGE)
command<=4'b0010;
else if (INIT_CHARGE2REF1||INIT_REF12REF2||ST_IDLE2REF)
command<=4'b0001;
else if (INIT_REF22MODE)
command<=4'b0000;
else if (IDLE2ACTIVE)
command<=4'b0011;
else if (WR_ACTIVE2WRITE)
command<=4'b0100;
else
command<=4'b0111;
end
end
//assign {cs,ras,cas,we}=command;
always @(*) begin
cs=command[3];
ras=command[2];
cas=command[1];
we=command[0];
end
//dqm
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
dqm<=2'b00;
end
else begin
if (state_c==INIT_NOP||state_c==INIT_CHARGE||state_c==INIT_REF1||state_c==INIT_REF2||state_c==INIT_MODE)
dqm<=2'b11;
else
dqm<=2'b00;
end
end
//addr
always @(*) begin
if (!rst_n) begin
addr=12'b0000_0000_0000;
end
else begin
if (state_c==INIT_MODE)
addr=MODE_VALUE;
else if (state_c==INIT_CHARGE)
addr=12'b0100_0000_0000;
else if (state_c==WR_WRITE)
addr=waddr[7:0];
else if (state_c==WR_ACTIVE)
addr=waddr[19:8];
else
addr=12'b0;
end
end
//bank
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
bank<=2'b00;
end
else begin
if (WR_ACTIVE2WRITE || IDLE2ACTIVE)
bank<=waddr[21:20];
else
bank<=2'b00;
end
end
//dq
always @(*) begin
if (!rst_n) begin
dq=16'hzzzz;
end
else if (state_c==WR_WRITE) begin//
dq=wdata;
end
else
dq=16'hzzzz;
end
//wr_ack assign wr_ack=wr_active_start
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
wr_ack<=0;
end
else begin
if (WR_ACTIVE2WRITE) //(state_c == WR_ACTIVE) && (count==1)
wr_ack<=1;
else
wr_ack<=0;
end
end
endmodule
`timescale 1ns / 1ns
//
module work_2_test();
reg clk;
reg rst_n;
reg wr_req;
reg [21:0] waddr;// without [21:0], bank<=waddr[21:20] error
reg [15:0] wdata;
wire wr_ack;
reg cke;
wire cs;
wire ras;
wire cas;
wire we;
wire dqm;
wire addr;
wire bank;
wire dq;
work_2 work_2_test(
.clk(clk),
.rst_n(rst_n),
.wr_req(wr_req),
.waddr(waddr),
.wdata(wdata),
.wr_ack(wr_ack),
.cke(cke),
.cs(cs),
.ras(ras),
.cas(cas),
.we(we),
.dqm(dqm),
.addr(addr),
.bank(bank),
.dq(dq)
);
initial begin
clk=1'b0;
forever #5 clk=~clk;
end
initial begin
rst_n=1'b0;
cke=1'b1;
waddr=22'b01_0001_0111_0000_0001_1010;
wdata=16'b0111_0000_0001_1010;
wr_req=1'b1;
#7 rst_n=1'b1;
end
endmodule