[FPGA]SDRAM-2

module SDRAM(
input clk,
input rst_n,
input wr_rp,
input rd_rp,
input[23: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,
output debug
);

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[14:0] cnt;
reg[14:0] x;

reg[10:0] cnt1;

reg[23:0] addr_i_ff0;

//state_c
parameter INIT_NOP =4’b0001; //1
parameter PRECHARGE =4’b0010; //2
parameter REFRESH =4’b0011; //3
parameter MODE =4’b0100; //4
parameter IDLE =4’b0101; //5
parameter ACTIVE =4’b0110; //6
parameter WRITE =4’b0111; //7
parameter READ =4’b1000; //8

//cmd
parameter NOP_CMD =4’b0111; //7H
parameter PRECHARGE_CMD =4’b0010; //2H
parameter REFRESH_CMD =4’b0001; //1H
parameter MODE_CMD =4’b0000; //0H
parameter ACTIVE_CMD =4’b0011; //3H
parameter WRITE_CMD =4’b0100; //4H
parameter READ_CMD =4’b0101; //5H

parameter T_200US =15’d20000;
parameter TRP =14’d4;
parameter TRC =14’d7;
parameter TMRD =14’d2;
parameter TRCD =14’d3;
parameter T_256 =14’d256;
parameter MODE_VALUE =12’b000000110111;

//A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
// 0 0 0 0 0 0 1 1 0 1 1 1
//————————— ————– — —————
//突发读/写 潜伏期=3 顺序 全页
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; (* keep *)wire idl2act_start; 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_200US; 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==781-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(state_c == REFRESH)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 reg wr_hold; reg rd_hold; always @(posedge clk or negedge rst_n)begin if (!rst_n)begin wr_hold<=1'b0; end else begin if (wr_rp)begin wr_hold<=1'b1; end else if (state_c==WRITE)begin wr_hold<=1'b0; end end end always @(posedge clk or negedge rst_n)begin if (!rst_n)begin rd_hold<=1'b0; end else begin if (rd_rp)begin rd_hold<=1'b1; end else if (state_c==READ)begin rd_hold<=1'b0; end end end (* keep *) wire write_sel; (* keep *) wire read_sel; assign wr_req = wr_rp || wr_hold; assign rd_req = rd_rp || rd_hold; assign write_sel =idl2act_start &&((rd_hty==1'b0 &&rd_req==1'b0)||rd_hty==1'b1) &&wr_req; assign read_sel =idl2act_start &&((rd_hty==1'b1 &&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[23:22]; end else if(act2wrt_start ||act2red_start)begin bank<=addr_i_ff0[23:22]; 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[21:10]; end else if(act2wrt_start ||act2red_start)begin addr_o<={addr_i_ff0[9: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 (* keep *) wire dq_en; assign dq_en =state_c ==WRITE; assign dq =dq_en?wdata_ff3:16'hzzzz; /* (* preserve *) reg dq_en_debug; always @(posedge clk) dq_en_debug <= dq_en; */ always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin cke<=0; 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

[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