sdram控制2

时间:2023-03-09 19:22:00
sdram控制2

sdram控制2

芯片手册要求sdram需要在64ms内刷新8K次,否则里面的数据会丢失,因此在64ms分成8192次,每次刷新充一次电,然后给两次自动刷新命令即可。

/*-----------------------------------------------------------------------

Date                :        2017-08-29
Description : Design for auto refresh. -----------------------------------------------------------------------*/ module sdram_afreh
(
//global clock
input clk, //system clock
input rst_n, //sync reset //init interface
input flag_init_end, //auto_freh interface
input ref_en,
output reg ref_req,
output reg flag_ref_end, //sdram interface
output reg [:] aref_cmd,
output reg [:] aref_addr
// output [1:0] aref_bank ); //--------------------------------
//Funtion :
parameter CMD_END = 'd10,
DELAY_7US = 'd350,
NOP = 'b0111,
PRECHARGE = 'b0010,
AREF = 'b0001; reg [:] cnt_7us;
reg flag_ref; //处于自刷新阶段标志
reg flag_start; //自刷新启动标志
reg [:] cnt_cmd; //--------------------------------
//Funtion : flag_start always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
flag_start <= 'd0;
else if(flag_init_end)
flag_start <= 'd1;
end //--------------------------------
//Funtion : 7us always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_7us <= 'd0;
else if(cnt_7us == DELAY_7US)
cnt_7us <= 'd0;
else if(flag_start)
cnt_7us <= cnt_7us + 'b1;
end //--------------------------------
//Funtion : flag_ref always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
flag_ref <= 'd0;
else if(cnt_cmd == CMD_END)
flag_ref <= 'd0;
else if(ref_en)
flag_ref <= 'd1;
end //--------------------------------
//Funtion : cnt_cmd always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_cmd <= 'd0;
else if(flag_ref)
cnt_cmd <= cnt_cmd + 'b1;
else
cnt_cmd <= 'd0;
end //--------------------------------
//Funtion : flag_ref_end always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
flag_ref_end <= 'd0;
else if(cnt_cmd == CMD_END)
flag_ref_end <= 'd1;
else
flag_ref_end <= 'd0;
end //--------------------------------
//Funtion : cmd_reg always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
aref_cmd <= NOP;
else case(cnt_cmd)
'd0 :
begin
if(flag_ref)
aref_cmd <= PRECHARGE;
else
aref_cmd <= NOP;
end 'd1 :
begin
aref_cmd <= AREF;
end 'd5 :
begin
aref_cmd <= AREF;
end default :
aref_cmd <= NOP; endcase
end //--------------------------------
//Funtion : sdram_addr always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
aref_addr <= 'd0;
else case(cnt_cmd) 'd0 :
begin
if(flag_ref)
aref_addr <= 'b0_0100_0000_0000;
else
aref_addr <= 'd0;
end default : aref_addr <= 'd0;
endcase
end //--------------------------------
//Funtion : ref_req always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
ref_req <= 'b0;
else if(ref_en)
ref_req <= 'd0;
else if(cnt_7us == DELAY_7US)
ref_req <= 'b1;
end //--------------------------------
//Funtion : bank //assign aref_bank = 2'd0; endmodule

最重要的时仲裁模块,它负责各个模块之间的协调,模块之间控制有三个信号,分别是请求信号requst ,使能信号en ,还有结束标志信号flag_end

flag_end   : 结束信号,负责一个状态的结束,比如写模块结束后,该信号就会拉高,时间很短暂,由计数器控制,自己会归0,当结束信号置1时,仲裁模块

里面的状态机就会跳转到仲裁模块,然后跳到下一个模块。

request     :请求模块,当该模块里面的数据已经准备好,并且现在的状态机在执行别的状态时,该模块就可以向状态机发送请求,不过当多个模块向状态机发送

请求时这时候就需要一个优先级的概念,在该程序中设定的优先级 刷新  》  写模块  》 读模块

en             :使能模块 , 当请求模块发挥作用时,仲裁模块把使能寄存器拉高,代表已经工作在该状态,同时把请求模块置0

地址和命令寄存器在三个模块是通用的,所以就要i用case语句进行选择,考虑时序逻辑有延时,所以用的组合逻辑

sdram_dq是双向端口:当不对该端口赋值的时候需要将该端口变成高阻态

代码

/*-----------------------------------------------------------------------

Date                :        2017-08-29
Description : Design for sdram_manage . -----------------------------------------------------------------------*/ module sdram_manage
(
//global clock
input clk, //system clock
input rst_n, //sync reset //sdram interface
output sdram_clk,
output sdram_cke,
output sdram_cas_n,
output sdram_cs_n,
output [:] sdram_dqm,
output [:] sdram_bank,
output sdram_ras_n,
output sdram_we_n,
output reg [:] sdram_addr,
inout [:] sdram_dq, //afresh interface
input ref_req,
output reg ref_en ,
input flag_ref_end,
input [:] aref_cmd,
input [:] aref_addr,
// input [1:0] aref_bank, //init interface
input [:] init_cmd,
input [:] init_addr,
// input [1:0] init_bank,
input flag_init_end, //write interface
output reg wr_en,
input wr_req,
input flag_wr_end,
input [:] wr_cmd,
input [:] wr_addr,
// input [1:0] wr_bank,
input [:] wr_dq,
output reg wr_wrig, //read interface
output reg rd_en,
input rd_req,
input flag_rd_end,
input [:] rd_cmd,
input [:] rd_addr,
// input [1:0] rd_bank,
output reg rd_wrig,
output reg [:] state ); //--------------------------------
//Funtion : 参数定义
localparam IDLE = 'b0_0001;
localparam ARBIT = 'b0_0010;
localparam AREF = 'b0_0100;
localparam WRITE = 'b0_1000;
localparam READ = 'b1_0000; parameter DELAY_10US = 'd500;
//reg [4:0] state;
reg [:] cnt_10us;
reg [:] cmd_reg; //--------------------------------
//Funtion : 读触发 和 写触发 //delay
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_10us <= 'd0;
else if(cnt_10us == DELAY_10US - 'b1)
cnt_10us <= 'd0;
else
cnt_10us <= cnt_10us + 'b1;
end always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
wr_wrig <= 'd0;
else if(cnt_10us == DELAY_10US - 'b1)
wr_wrig <= ~wr_wrig;
end always @(posedge clk)
begin
rd_wrig <= ~wr_wrig;
end //--------------------------------
//Funtion wr_en always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
wr_en <= 'b0;
else if(state == ARBIT && ref_req == 'b0 && wr_req)
wr_en <= 'b1;
else
wr_en <= 'b0;
end //--------------------------------
//Funtion ref_en always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
ref_en <= 'b0;
else if(state == ARBIT && ref_req)
ref_en <= 'b1;
else
ref_en <= 'b0;
end //--------------------------------
//Funtion rd_en 优先级 刷新 > 写请求 > 读请求 always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
rd_en <= 'b0;
else if(state == ARBIT && ref_req == 'b0 && wr_req == 1'b0 && rd_req == 'b1)
rd_en <= 'b1;
else
rd_en <= 'b0;
end //--------------------------------
//Funtion : 仲裁状态机 always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
state <= IDLE;
else
case(state) IDLE :
begin
if(flag_init_end)
state <= ARBIT;
else
state <= IDLE;
end
//仲裁
ARBIT :
begin
if(ref_en)
state <= AREF;
else if(wr_en)
state <= WRITE;
else if(rd_en)
state <= READ;
else
state <= ARBIT;
end
//刷新
AREF :
begin
if(flag_ref_end)
state <= ARBIT;
else
state <= AREF;
end
//write
WRITE :
begin
if(flag_wr_end)
state <= ARBIT;
else
state <= WRITE;
end
//read
READ :
begin
if(flag_rd_end)
state <= ARBIT;
else
state <= READ;
end default :
state <= IDLE;
endcase
end //--------------------------------
//Funtion : cmd addr 组合逻辑不会有延时 always @(*)
begin
case(state)
IDLE :
begin
cmd_reg = init_cmd;
sdram_addr = init_addr;
end AREF :
begin
cmd_reg = aref_cmd;
sdram_addr = aref_addr;
end WRITE :
begin
cmd_reg = wr_cmd;
sdram_addr = wr_addr;
end READ :
begin
cmd_reg = rd_cmd;
sdram_addr = rd_addr;
end default :
begin
cmd_reg = 'b0111;
sdram_addr = 'd0;
end endcase
end //--------------------------------
//Funtion : others assign sdram_clk =~ clk;
assign sdram_cke = 'b1;
assign sdram_dqm = 'd0;
assign {sdram_cs_n , sdram_ras_n , sdram_cas_n , sdram_we_n} = cmd_reg;
assign sdram_dq = (state == WRITE) ? wr_dq : {{'bz}};
assign sdram_bank = 'd0; endmodule

最后把sigtab的图片贴上来

sdram控制2

sdram控制2

在写数据写的是1000 - 4000 然后把它读出来