sdram简易控制器设计

本文介绍了作者耗时一周完成的FPGA SDRAM简易控制器设计,详细讲述了设计过程中遇到的关键问题,如仲裁模块的if/else顺序、刷新、写、读操作的时序控制,以及读写状态后的PRE命令重要性。文中提供了初始化、刷新、写、读模块及顶层模块的代码,并附有时序图仿真结果,期待与读者交流讨论。
摘要由CSDN通过智能技术生成

耗时一周,终于完成sdram简易控制器的所有代码设计,其中感谢开源骚客 – 邓堪文老师在b站发布的相关视频学习教材;其中仿真模块及所使用到的sdram仿真文件来源于开源骚客;

因为时间较为紧迫,其中就不做代码的一些注释;

在设计中,总结一哈要主要的几个问题:

1. 仲裁模块中if/else语句中的先后顺序很重要,其中根据仿真的时序图经过多次修改;

2. 仲裁模块决定刷新/写/读操作的重要部分,要重点理清楚各模块产生请求信号后产生使能信号的先后顺序;

3. 读/写状态结束后应及时赋予PRE命令,否则导致读数据有误(具体可查看芯片手册相关介绍);

本设计中采用写3行数据后进行数据的读取,代码如下:

 初始化init模块:

module sdram_init(
sys_clk,
sys_rst_n,
init_cmd,
init_addr,
init_end
);

input 					   	sys_clk,sys_rst_n;
output reg  [3:0] 	init_cmd;
output wire [12:0]  init_addr;
output wire 				init_end;

reg [13:0] cnt_200us;
wire       flag_200us;
reg [3:0]  cnt_cmd;

localparam delay_200us = 10000; //200us
//SDRAM init_cmd//
localparam NOP  = 4'b0111; 
localparam PRE  = 4'b0010; 
localparam AREF = 4'b0001; 
localparam MSET = 4'b0000; 

always@(posedge sys_clk or negedge sys_rst_n)
begin 
	if(!sys_rst_n)
		cnt_200us <= 0;
	else if (flag_200us == 0)
		cnt_200us <= cnt_200us+1;
end

assign flag_200us = (cnt_200us >= delay_200us) ? 1'b1:1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
begin 
	if(!sys_rst_n)
	cnt_cmd <= 0;
	else if ((flag_200us == 1) && (init_end == 0))
	cnt_cmd <= cnt_cmd+1;
end

always@(posedge sys_clk or negedge sys_rst_n)
begin 
	if(!sys_rst_n)
	init_cmd <= NOP ;
	else if (flag_200us == 1)
	case (cnt_cmd)
		0: init_cmd <= PRE;
		1: init_cmd <= AREF;
		5: init_cmd <= AREF;
		9: init_cmd <= MSET;
		default:init_cmd <= NOP;
	endcase
end




//sdram addr//
//always@(posedge sys_clk or negedge sys_rst_n)
//begin 
//	if(!sys_rst_n)
//	init_addr <= 0;
//	else if (flag_200us == 1)
//	case (cnt_init_cmd)

assign init_addr = (init_cmd == MSET) ? 13'b0_0000_0011_0010:12'b0_0100_0000_0010;
assign init_end = (cnt_cmd >= 'd10) ? 1'b1:1'b0;

endmodule

刷新模块代码:

module sdram_aref(
sys_clk,
sys_rst_n,
init_end,
ref_en,
ref_req,
ref_end,
ref_cmd,
ref_addr
);

input 		      sys_clk,sys_rst_n,ref_en,init_end;
output  reg     ref_req;
output  wire    ref_end;
output  reg [3:0]   ref_cmd;
output     [12:0]  ref_addr;  //4M*4banks*16bit//

localparam Delay_15us  = 399;
localparam NOP  = 4'b0111; 
localparam PRE  = 4'b0010; 
localparam AREF = 4'b0001; 


reg     [3:0] 	cnt_cmd;
reg     [9:0] 	cnt_ref;
reg             ref_flag;

always@(posedge sys_clk or negedge sys_rst_n)
begin
	if (!sys_rst_n)
		cnt_ref <= 1'b0;
	else if (cnt_ref == Delay_15us)
		cnt_ref <= 1'b0;
	else if (init_end == 1'b1)
		cnt_ref <= cnt_ref + 1'b1;
end

always@(posedge sys_clk or negedge sys_rst_n)
begin
	if (!sys_rst_n)
		ref_req <= 0;
	else if (ref_en == 1 && ref_req == 1)
		ref_req <= 0;
	else if (cnt_ref >= Delay_15us)
		ref_req <= 1;
end
//assign ref_req = (cnt_ref == Delay_15us) ? 1'b1:1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
begin
	if (!sys_rst_n)
		ref_flag <= 0;
	else if (ref_en == 1)
		ref_flag <= 1;
	else if (ref_end == 1)
		ref_flag <= 0;
end
		
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if (!sys_rst
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值