`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/08/03 09:39:06
// Design Name:
// Module Name: work_4
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module work_4(clk,rst_n,wr_req,waddr,wdata,wr_ack,rd_req,rd_ack,rdata,rdata_vld,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 rd_req;
output rd_ack;
output rdata;
output rdata_vld;
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=2;
parameter Tread=256;
parameter Twrite=256;
parameter Tidle=2;
parameter MODE_VALUE = 12'b0000_0010_0111;//M9 = 0 burst模式 M6 M5 M4 = 3'b010 输出延时为2个时钟周期;M3 = 0 burst类型(连续模式) M2 M1 M0 = 3'b111 全页模式
//
parameter NOP = 1;//
parameter CHARGE = 2;//
parameter REF = 3;//
parameter MODE = 4;//
parameter IDLE = 5;//
parameter ACTIVE = 6;
parameter WRITE = 7;
parameter READ = 8;
parameter REF2 = 9;
reg cs;
reg ras;
reg cas;
reg we;
reg wr_ack;
reg rd_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;
reg rdata_vld;
wire NOP2CHARGE;
wire CHARGE2REF;
wire REF2REF2;
wire REF22MODE;
wire MODE2IDLE ;
wire IDLE2REF;
wire REF2IDLE;
wire IDLE2ACTIVE;
wire ACTIVE2WRITE;
wire WRITE2CHARGE ;
wire CHARGE2IDLE ;
wire ACTIVE2READ;
wire READ2CHARGE;
wire resh_req;
reg init_flag;
wire wr_flag;
wire rd_flag;
//reg init_resh_cnt;//初始化过程自动刷新计数 区分REF2REF 还是REF2MODE
assign wr_flag= (wr_req==1) && (rd_req==0);
assign rd_flag= (rd_req==1);
assign resh_req= (wr_req==1 || rd_req==1);
assign NOP2CHARGE = (state_c == NOP) && (count==1) ;
assign CHARGE2REF= (state_c == CHARGE) && (count==1) && init_flag==1;
assign REF2REF2 = (state_c == REF) && (count==1) && (init_flag==1) ;
assign REF22MODE = (state_c == REF2) && (count==1) && (init_flag==1) ;
assign MODE2IDLE = (state_c == MODE) && (count==1);
assign IDLE2REF = (state_c == IDLE) && (count1==1) ;//
assign REF2IDLE = (state_c == REF) && (count==1) && (init_flag==0) ;//
assign IDLE2ACTIVE = (state_c == IDLE) && (count==1) && ( (wr_flag==1)||(rd_flag==1) ) ;
assign ACTIVE2WRITE = (state_c == ACTIVE) && (count==1)&& (wr_flag==1);
assign WRITE2CHARGE = (state_c == WRITE) && (count==1);
assign CHARGE2IDLE = (state_c == CHARGE) && (count==1) && ( (wr_flag==1)||(rd_flag==1) );
assign ACTIVE2READ = (state_c == ACTIVE) && (count==1)&& (rd_flag==1) ;
assign READ2CHARGE = (state_c == READ) && (count==1);
always @(posedge clk or negedge rst_n) begin
if (rst_n==1'b0) begin
init_flag <= 1;
end
else if (MODE2IDLE) begin
init_flag <= 0;
end
end
//always @(posedge clk or negedge rst_n) begin
// if (rst_n==1'b0) begin
// init_resh_cnt <= 0;
// end
// else if (REF2REF) begin
// init_resh_cnt <= 1;
// end
// else if (REF2MODE) begin
// init_resh_cnt <= 0;
// end
//end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_c<=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)
NOP : begin//1
if (NOP2CHARGE) begin
state_n=CHARGE;
end
else begin
state_n=state_c;
end
end
CHARGE : begin//2
if (CHARGE2REF) begin
state_n=REF;
end
else if (CHARGE2IDLE) begin
state_n=IDLE;
end
else begin
state_n=state_c;
end
end
REF : begin//3
if (REF2IDLE) begin
state_n=IDLE;
end
else if (REF2REF2) begin
state_n=REF2;
end
else begin
state_n=state_c;
end
end
REF2 : begin//3
if (REF22MODE) begin
state_n=MODE;
end
else begin
state_n=state_c;
end
end
MODE : begin//
if (MODE2IDLE) begin
state_n=IDLE;
end
else begin
state_n=state_c;
end
end
IDLE : begin//
if (IDLE2REF) begin
state_n=REF;
end
else if (IDLE2ACTIVE) begin
state_n=ACTIVE;
end
else begin
state_n=state_c;
end
end
ACTIVE : begin//
if (ACTIVE2WRITE) begin
state_n=WRITE;
end
else if (ACTIVE2READ) begin
state_n=READ;
end
else begin
state_n=state_c;
end
end
WRITE : begin
if (WRITE2CHARGE) begin
state_n=CHARGE;
end
else begin
state_n=state_c;
end
end
READ : begin
if (READ2CHARGE) begin
state_n=CHARGE;
end
else begin
state_n=state_c;
end
end
default : begin//default
state_n=NOP;
end
endcase
end
end
//
always @(*)begin
if(state_c==CHARGE) begin
x = TRP;
end
else if(state_c==REF || state_c==REF2 )begin
x = TRC;
end
else if(state_c==MODE)begin
x = TMRD;
end
else if(state_c==ACTIVE )begin
x = TRCD;
end
else if(state_c==WRITE )begin
x = Twrite;
end
else if(state_c== READ )begin
x = Tread;
end
else if(state_c== IDLE && (wr_flag==0 || rd_flag==0))begin
x = Tidle;
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==IDLE && wr_flag==0 && rd_flag==0 ) 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 (NOP2CHARGE||WRITE2CHARGE ||READ2CHARGE)
command<=4'b0010;
else if (CHARGE2REF || IDLE2REF)
command<=4'b0001;
else if (REF22MODE)
command<=4'b0000;
else if (IDLE2ACTIVE)
command<=4'b0011;
else if (ACTIVE2WRITE)
command<=4'b0100;
else if (ACTIVE2READ)
command<=4'b0101;
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==NOP||state_c==CHARGE|| state_c==REF ||state_c==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==MODE)
addr=MODE_VALUE;
else if (state_c==CHARGE)
addr=12'b0100_0000_0000;
else if (state_c==WRITE || state_c==READ)
addr=waddr[7:0];
else if (state_c==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 (ACTIVE2WRITE || IDLE2ACTIVE || ACTIVE2READ || 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==WRITE) begin//
dq=wdata;
end
else if (state_c==READ) begin//
dq=rdata;
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 (ACTIVE2WRITE) //(state_c == WR_ACTIVE) && (count==1)
wr_ack<=1;
else
wr_ack<=0;
end
end
//rd_ack
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rd_ack<=0;
end
else begin
if (ACTIVE2READ) //(state_c == WR_ACTIVE) && (count==1)
rd_ack<=1;
else
rd_ack<=0;
end
end
//rdata_vld
always @(*) begin
if (!rst_n) begin
rdata_vld=0;
end
else begin
if (state_c==READ) //(state_c == WR_ACTIVE) && (count==1)
rdata_vld=1;
else
rdata_vld=0;
end
end
endmodule