[FPGA]SDRAM

module SDRAM(
input clk,
input rst_n,
input wr_req,
input rd_req,
input[21:0] addr_i,
input[15:0] wdata,
output reg wr_ack,
output reg rd_ack,
output reg[15:0] rdata,
output reg rdata_vld,

output reg cke,
output reg cs,
output reg ras,
output reg cas,
output reg we,
output reg[1:0] dqm,
output reg[11:0] addr_o,
output reg[1:0] bank,
inout[15:0] dq
);

reg[15:0] wdata_ff0;
reg[15:0] wdata_ff1;
reg[15:0] wdata_ff2;
reg[15:0] wdata_ff3;

reg[3:0] cmd;

reg read_flag_ff0;
reg read_flag_ff1;
reg read_flag_ff2;

reg[3:0] state_c;
reg[3:0] state_n;

reg init_flag;
reg resh_flag;
reg rd_flag;

reg rd_hty;

reg[1:0] resh_cnt;

reg[13:0] cnt;
reg[13:0] x;

reg[10:0] cnt1;
reg[21:0] addr_i_ff0;

parameter DATA_W =16;
parameter ADDR_W =22;
parameter CMD_W =4;

parameter INIT_NOP =4’b0001;
parameter PRECHARGE =4’b0010;
parameter REFRESH =4’b0011;
parameter MODE =4’b0100;
parameter IDLE =4’b0101;
parameter ACTIVE =4’b0110;
parameter WRITE =4’b0111;
parameter READ =4’b1000;

parameter NOP_CMD =4’b0111;
parameter PRECHARGE_CMD =4’b0010;
parameter REFRESH_CMD =4’b0001;
parameter MODE_CMD =4’b0000;
parameter ACTIVE_CMD =4’b0011;
parameter WRITE_CMD =4’b0100;
parameter READ_CMD =4’b0101;

parameter T_100US =10000;
parameter TRP =3;
parameter TRC =7;
parameter TMRD =2;
parameter TRCD =3;
parameter T_256 =256;
parameter MODE_VALUE =12’b000000110111;
parameter ALL_BANK =12’b001000000000;

always@(posedge clk or negedge rst_n)begin
if(rst_n==1’b0)begin
state_c<=INIT_NOP; end else begin state_c<=state_n; end end always@(*)begin case(state_c) INIT_NOP:begin if(ini2pre_start)begin state_n =PRECHARGE; end else begin state_n =state_c; end end PRECHARGE:begin if(pre2ref_start)begin state_n =REFRESH; end else if(pre2idl_start)begin state_n =IDLE; end else begin state_n =state_c; end end REFRESH:begin if(ref2ref_start)begin state_n =REFRESH; end else if(ref2mod_start)begin state_n =MODE; end else if(ref2idl_start)begin state_n =IDLE; end else begin state_n =state_c; end end MODE:begin if(mod2idl_start)begin state_n =IDLE; end else begin state_n =state_c; end end IDLE:begin if(idl2ref_start)begin state_n =REFRESH; end else if(idl2act_start)begin state_n =ACTIVE; end else begin state_n =state_c; end end ACTIVE:begin if(act2wrt_start)begin state_n =WRITE; end else if(act2red_start)begin state_n =READ; end else begin state_n =state_c; end end WRITE:begin if(wrt2pre_start)begin state_n =PRECHARGE; end else begin state_n=state_c; end end READ:begin if(red2pre_start)begin state_n =PRECHARGE; end else begin state_n =state_c; end end default:begin state_n =INIT_NOP; end endcase end assign ini2pre_start =state_c ==INIT_NOP &&end_cnt; assign wrt2pre_start =state_c ==WRITE &&end_cnt; assign red2pre_start =state_c ==READ &&end_cnt; assign pre2ref_start =state_c ==PRECHARGE &&end_cnt &&init_flag; assign pre2idl_start =state_c ==PRECHARGE &&end_cnt &&init_flag==0; assign ref2ref_start =state_c ==REFRESH &&end_cnt &&resh_cnt==0 &&init_flag; assign ref2mod_start =state_c ==REFRESH &&end_cnt &&resh_cnt==1 &&init_flag; assign ref2idl_start =state_c ==REFRESH &&end_cnt &&init_flag==0; assign mod2idl_start =state_c ==MODE &&end_cnt; assign idl2act_start =state_c ==IDLE &&resh_flag==0 &&(rd_req || wr_req); assign idl2ref_start =state_c ==IDLE &&(resh_flag || end_cnt1); assign act2wrt_start =state_c ==ACTIVE &&end_cnt &&rd_flag==0; assign act2red_start =state_c ==ACTIVE &&end_cnt &&rd_flag==1; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin cnt<=0; end else if(add_cnt)begin if(end_cnt)begin cnt<=0; end else begin cnt<=cnt+1'b1; end end end assign add_cnt =state_c!=IDLE; assign end_cnt =add_cnt&&cnt==x-1; always @(*)begin if(state_c ==INIT_NOP)begin x =T_100US; end else if(state_c==PRECHARGE)begin x =TRP; end else if(state_c==REFRESH)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 || state_c ==READ)begin x =T_256; end else begin x =0; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin cnt1 <=0; end else if(add_cnt1)begin if(end_cnt1)begin cnt1<=0; end else begin cnt1<=cnt1 +1'b1; end end end assign add_cnt1 =init_flag==1'b0; assign end_cnt1 =add_cnt1 &&cnt1==1562-1; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin resh_flag<=1'b0; end else if(end_cnt1)begin resh_flag<=1'b1; end else if(idl2ref_start)begin resh_flag<=1'b0; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin init_flag<=1; end else if(mod2idl_start)begin init_flag<=0; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin resh_cnt<=0; end else if(add_resh_cnt)begin if(end_resh_cnt)begin resh_cnt<=0; end else begin resh_cnt<=resh_cnt +1'b1; end end end assign add_resh_cnt =init_flag &&state_c ==REFRESH &&end_cnt; assign end_resh_cnt =add_resh_cnt &&resh_cnt ==2-1; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin rd_hty<=1'b0; end else if(pre2idl_start)begin rd_hty<=rd_flag; end end assign write_sel =idl2act_start &&((rd_hty==1'b0 &&rd_req==1'b0)||rd_hty) &&wr_req; assign read_sel =idl2act_start &&((rd_hty &&wr_req==1'b0)||rd_hty==1'b0) &&rd_req; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin rd_flag<=1'b0; end else if(write_sel)begin rd_flag<=1'b0; end else if(read_sel)begin rd_flag<=1'b1; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin addr_i_ff0<=0; end else begin addr_i_ff0<=addr_i; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin bank <=2'b00; end else if(idl2act_start)begin bank<=addr_i[21:20]; end else if(act2wrt_start ||act2red_start)begin bank<=addr_i_ff0[21:20]; end else begin bank<=2'b00; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin addr_o<=0; end else if(ref2mod_start)begin addr_o<=MODE_VALUE; end else if(ini2pre_start ||wrt2pre_start ||red2pre_start)begin addr_o<=ALL_BANK; end else if(idl2act_start)begin addr_o<=addr_i[19:8]; end else if(act2wrt_start ||act2red_start)begin addr_o<={addr_i_ff0[7:0]}; end else begin addr_o<=0; end end always @(*)begin rd_ack=read_sel; end assign read_flag =state_c==READ; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin read_flag_ff0<=1'b0; read_flag_ff1<=1'b0; read_flag_ff2<=1'b0; end else begin read_flag_ff0 <=read_flag; read_flag_ff1 <=read_flag_ff0; read_flag_ff2 <=read_flag_ff1; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin rdata<=0; end else if(read_flag_ff2)begin rdata<=dq; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin rdata_vld<=0; end else if(read_flag_ff2)begin rdata_vld<=1; end else if(pre2idl_start &&rd_flag)begin rdata_vld<=0; end end always @(*)begin wr_ack =write_sel; end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin wdata_ff0<=0; wdata_ff1<=0; wdata_ff2<=0; wdata_ff3<=0; end else begin wdata_ff0<=wdata; wdata_ff1<=wdata_ff0; wdata_ff2<=wdata_ff1; wdata_ff3<=wdata_ff2; end end assign dq_en =state_c ==WRITE; assign dq =dq_en?wdata_ff3:16'hzzzz; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin cke<=1; end else begin cke<=1; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin cmd<=NOP_CMD; end else if(ini2pre_start ||wrt2pre_start ||red2pre_start)begin cmd<=PRECHARGE_CMD; end else if(pre2ref_start ||ref2ref_start ||idl2ref_start)begin cmd<=REFRESH_CMD; end else if(ref2mod_start)begin cmd<=MODE_CMD; end else if(act2wrt_start)begin cmd<=WRITE_CMD; end else if(act2red_start)begin cmd<=READ_CMD; end else if(idl2act_start)begin cmd<=ACTIVE_CMD; end else begin cmd<=NOP_CMD; end end always @(*)begin {cs,ras,cas,we}=cmd; end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin dqm<=2'b00; end else if(dqm_en)begin dqm<=2'b11; end else begin dqm<=2'b00; end end assign dqm_en =state_c==init_flag; endmodule

发表评论

邮箱地址不会被公开。 必填项已用*标注