SDRAM接口练习4

SDRAM接口练习4

`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

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/08/03 19:53:57
// Design Name: 
// Module Name: work_4_test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module work_4_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 rd_req;
wire rd_ack;
wire rdata;
wire rdata_vld;
reg cke;
wire cs;
wire ras;
wire cas;
wire we;
wire dqm;
wire addr;
wire bank;
wire dq;
work_4 work_4_test(
.clk(clk),
.rst_n(rst_n),
.wr_req(wr_req),
.waddr(waddr),
.wdata(wdata),
.wr_ack(wr_ack),
.rd_req(rd_req),
.rd_ack(rd_ack),
.rdata(rdata),
.rdata_vld(rdata_vld),
.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'b0;
 rd_req=1'b1;
 #7 rst_n=1'b1;
end
endmodule

SDRAM接口练习4
SDRAM接口练习4

上一篇:SDRAM学习笔记(一) sdram_init


下一篇:0阶段-第二题-生成树与LCA