SDRAM总结
使用的流程
W9825G6JH winbond sdram 4M words X 4banks X 16bits=.
Accesses to the SDRAM are burst oriented.
Up to 200MHz
CAS Latency 2 and 3
Burst Length 1,2,4,9 and Full page
BUrst Read, Single Writes Mode
8K Refresh Cycles/64mS
1 After power up, an initial pause of 200uS is required followed by a precharge of all banks using the precharge commmand.DQM and CKE held high during the pause.
2 Once all banks have been precharged ,the Mode Register Set Command must be issued to initialize the Mode Register.
All banks must be in a precharged state and CKE must be high at least one cycle before the Mode Register Set Command can be issued. ()A delay equals to must be waited when the next command can be issued.
3 An Additional eight Auto Refresh cycles are also requred before or after programming the Mode Register .
4 Bank Active Command
before any read or write command
5 Read and Write Access Modes
6 Burst Read Command
7 Burst Write Command
8 Auto-precharge Command
9 Precharge Command
10 Self Refresh Command
11 NOP
`timescale 1ns/1ps ////////////////////////////////////////////////////////////////////////////////
// Company :
// Engineer : Yang Li yangli0534@gmail.com
// Create Date : 2015.01.20
// Design Name :
// Module Name : sdram
// Project Name :
// Target Device: Spartan 6
// Tool versions: ISE 14.7
// Description : SDRAM control
// read or write one word a time
// the sdram is WINBOND W9825G6JH
// Revision : V1.0 created
// Additional Comments :
//
////////////////////////////////////////////////////////////////////////////////
module sdram(
input clk_i, //clock 100M ,
input rst_n_i, // reset ,active low input wr_req_i, // write request
input rd_req_i, // read request
output wr_ack_o, //write ack
output rd_ack_o, //read ack input [:] wr_addr_i, // address to write
input [:] wr_data_i, //data to write input [:] rd_addr_i, // read address
output [:] rd_data_o, // read data
output rd_data_valid_o,// data output valid
output busy_sdram_o, // sdram is busy , unable to be operated // SDRAM interface
output [:] SDRAM_ADDR,
output SDRAM_BA_0,
output SDRAM_BA_1,
output SDRAM_CAS_N,
output SDRAM_CKE,
// output SDRAM_CLK,
output SDRAM_CS_N,
inout [:] SDRAM_DQ,
output SDRAM_LDQM,
output SDRAM_UDQM,
output SDRAM_RAS_N,
output SDRAM_WE_N
);
//Timing parameters of SDRAM winbond W9825G6JH
localparam T_200us='d20000,
T_RC='d6-15'd1,//60ns Ref/Active to Ref/Active Command Period
T_RCD='d3-15'd1,//15ns Active to Read/Write Command Delay Time
T_RP='d2-15'd1,//15ns Precharge to Active Command Period
T_RSC='d3-15'd1,//////Mode register set cycle time
T_LATENCY='d3-15'd2,//column to data valid latency
T_WR='d2-15'd1;// Write recovery time
//SDRAM command
localparam CMD_INIT = 'b01111 ,// power on
CMD_NOP = 'b10111 ,// nop command
CMD_ACTIVE = 'b10011 ,// active command
CMD_READ = 'b10101 ,// read commadn
CMD_WRITE = 'b10100 ,// write command
CMD_B_STOP = 'b10110 ,// burst stop
CMD_PRECHARGE= 'b10010 ,// precharge
//CMD_A_REF = 5'b10001 ,// aoto refresh
CMD_A_REF = 'b10010 ,// aoto refresh
CMD_LMR = 'b10000 ;// lode mode register
//fsm of initialization
localparam
INIT_WAIT ='b00000001 ,//power on ,and wait 200us
INIT_PRECHARGE ='b00000010, //precharge
INIT_TRP ='b00000100, //wait precharge to be done, Trp
INIT_AUTO_REFRESH ='b00001000, // Auto Refresh for 8 times
INIT_TRC ='b00010000, //Refresh-to-Refresh interval
INIT_MRS ='b00100000, //load the Mode Register
INIT_TRSC ='b01000000, //wait the MRS
INIT_DONE ='b10000000; //initialization done
//fsm of normal operation
localparam IDLE ='b000000000001, //wait to fresh or read\write
WORK_ACTIVE ='b000000000010, //active the ROW
WORK_TRCD ='b000000000100, //Row-to-Column delay
WORK_READ ='b000000001000 ,//read
WORK_LATENCY ='b000000010000, //column latency
WORK_READ_DATA ='b000000100000, //read data from DQ bus
//WORK_WAIT =12'b000001000000,
WORK_WRITE ='b000010000000, //write
WORK_TWR ='b000100000000,//write recovery delay
WORK_TRP ='b001000000000,//precharge to active command period
WORK_AUTO_REFRESH='b010000000000, //refresh
WORK_TRC ='b100000000000;// Ref/Act to Ref/Act delay ,unused reg[:] init_state_reg, init_state_next; // SDRAM initialization state
reg[:] init_timer_reg, init_timer_next; // delay timer
reg [:] ref_cnt_reg, ref_cnt_next; // repeat timer //------------------------------------------------------------------------------
//SDRAM initialization state transition begin here
//------------------------------------------------------------------------------ always @(posedge clk_i or negedge rst_n_i)
if(!rst_n_i) begin
init_state_reg <= INIT_WAIT;
init_timer_reg <= T_200us;
ref_cnt_reg <= 'd0;
end
else begin
init_state_reg <= init_state_next;
init_timer_reg <= init_timer_next;
ref_cnt_reg <= ref_cnt_next;
end always @* begin
init_state_next = init_state_reg;
init_timer_next = init_timer_reg;
ref_cnt_next = ref_cnt_reg;
if(init_timer_reg != 'd0)
init_timer_next = init_timer_reg - 'd1; case(init_state_reg)
INIT_WAIT: begin
if(init_timer_reg=='d0)
init_state_next = INIT_PRECHARGE;
end
INIT_PRECHARGE: begin
init_state_next = INIT_TRP;
init_timer_next = T_RP;
end
INIT_TRP: begin
if(init_timer_reg=='d0) begin
init_state_next = INIT_AUTO_REFRESH;
ref_cnt_next = 'd8;
end
end
INIT_AUTO_REFRESH: begin
init_state_next = INIT_TRC;
init_timer_next = T_RC;
end
INIT_TRC: begin
if(init_timer_reg == 'd0) begin
if(ref_cnt_reg == 'd0) begin
init_state_next = INIT_MRS;
end
else begin
ref_cnt_next = ref_cnt_reg - 'd1;
init_state_next = INIT_AUTO_REFRESH;
end
end end
INIT_MRS: begin
init_state_next = INIT_TRSC;
init_timer_next = T_RSC;
end
INIT_TRSC: begin
if(init_timer_reg == 'd0)
init_state_next = INIT_DONE;
end
INIT_DONE : begin
init_state_next = INIT_DONE;
end
endcase
end
//SDRAM initialization state transition end here
reg[:] work_timer_reg, work_timer_next; // delay timer
reg[:] work_state_reg, work_state_next; // SDRAM normal operation state
assign sdram_init_done = (init_state_reg == INIT_DONE);
//------------------------------------------------------------------------------
//self refresh every 7 us
//------------------------------------------------------------------------------
reg sdram_ref_req; // SDRAM self refresh request
wire sdram_ref_ack; // SDRAM elf refresh ack
reg[:] cnt_7us; // always @ (posedge clk_i or negedge rst_n_i)
if(!rst_n_i) cnt_7us <= 'd0;
else if(cnt_7us < 'd700) cnt_7us <= cnt_7us+11'b1; // 60ms(64ms)/8192=7.9us
else cnt_7us <= 'd0; always @ (posedge clk_i or negedge rst_n_i)
if(!rst_n_i) sdram_ref_req <= 'b0;
else if(cnt_7us == 'd699) sdram_ref_req <= 1'b1; //refresh request
else if(sdram_ref_ack) sdram_ref_req <= 'b0; //request has been acknowledged //------------------------------------------------------------------------------
//SDRAM normal operation state transition begin here
//------------------------------------------------------------------------------
reg wr_ctrl_reg, wr_ctrl_next;
always @(posedge clk_i or negedge rst_n_i)
if(!rst_n_i) begin
work_state_reg <= IDLE;
wr_ctrl_reg <= 'b0;
work_timer_reg <= 'd0;
end
else begin
work_state_reg <= work_state_next;
wr_ctrl_reg <= wr_ctrl_next;
work_timer_reg <= work_timer_next;
end
//SDRAM normal operation state transition end here always @* begin
work_state_next = work_state_reg;
wr_ctrl_next = wr_ctrl_reg;
if(sdram_init_done & work_timer_reg != 'd0)
work_timer_next = work_timer_reg - 'd1;
else work_timer_next = work_timer_reg;
case(work_state_reg)
IDLE: begin
if(sdram_init_done & sdram_ref_req) begin
work_state_next = WORK_AUTO_REFRESH;
end
else if(sdram_init_done & wr_req_i) begin
work_state_next = WORK_ACTIVE;
wr_ctrl_next = 'b0;//write
end
else if(sdram_init_done & rd_req_i) begin
work_state_next = WORK_ACTIVE;
wr_ctrl_next = 'b1;//read
end
else begin
work_state_next = IDLE;
wr_ctrl_next = 'b1;
end
end
WORK_ACTIVE: begin
work_state_next = WORK_TRCD;
work_timer_next = T_RCD;
end
WORK_TRCD : begin
if(work_timer_reg == 'd0) begin
if(wr_ctrl_reg == 'b0)
work_state_next = WORK_WRITE;
else
work_state_next = WORK_READ;
end end
//write
WORK_WRITE: begin
work_state_next = WORK_TWR;
work_timer_next = T_WR;
end
WORK_TWR: begin
if(work_timer_reg=='d0) begin
work_state_next = WORK_TRP;
work_timer_next = T_RP;
end
end
WORK_TRP: begin
if(work_timer_reg == 'd0)
work_state_next = IDLE;
end //read
WORK_READ: begin
work_state_next = WORK_LATENCY;
work_timer_next = T_LATENCY;
end
WORK_LATENCY:begin
if(work_timer_reg == 'd0)
work_state_next = WORK_READ_DATA;
end
WORK_READ_DATA: begin
work_state_next=WORK_TRP;
work_timer_next= 'b1;
end //refresh
WORK_AUTO_REFRESH: begin
work_state_next = WORK_TRC;
work_timer_next = T_RC;
end
WORK_TRC: begin
if(work_timer_reg=='d0)
work_state_next = IDLE;
end
endcase
end assign busy_sdram_o = (sdram_init_done && work_state_reg == IDLE) ? 'b0 : 1'b1;
assign sdram_ref_ack =(work_state_reg == WORK_AUTO_REFRESH);
assign rd_ack_o = (work_state_reg ==WORK_READ_DATA);
assign rd_data_valid_o = (work_state_reg == WORK_TRP)&(wr_ctrl_reg == 'b1)&(work_timer_reg==15'd0);
assign wr_ack_o = (work_state_reg == WORK_TWR) ; reg[:] sdram_cmd_r; // SDRAM command
reg[:] sdram_ba_r;
reg[:] sdram_addr_r; assign {SDRAM_CKE,SDRAM_CS_N,SDRAM_RAS_N,SDRAM_CAS_N,SDRAM_WE_N} = sdram_cmd_r;
assign {SDRAM_BA_1, SDRAM_BA_0} = sdram_ba_r;
assign SDRAM_ADDR = sdram_addr_r;
assign SDRAM_LDQM = (init_state_reg == INIT_WAIT)? 'b1 : 1'b0;
assign SDRAM_UDQM = (init_state_reg == INIT_WAIT)? 'b1 :1'b0;
//-------------------------------------------------------------------------------
//SDRAM command
always @ (posedge clk_i or negedge rst_n_i) begin
if(!rst_n_i) begin
sdram_cmd_r <= CMD_INIT;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'hfff;
end
else
case (init_state_reg)
INIT_WAIT, INIT_TRP,INIT_TRC,INIT_TRSC: begin
sdram_cmd_r <= CMD_NOP;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
INIT_PRECHARGE: begin
sdram_cmd_r <= CMD_PRECHARGE;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
INIT_AUTO_REFRESH: begin
sdram_cmd_r <= CMD_A_REF;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
INIT_MRS: begin //
sdram_cmd_r <= CMD_LMR;
sdram_ba_r <= 'b00; // Reserved
sdram_addr_r <= {
'b00, //Reserved
'b0, //Wite Mode Burst Read and Burst Write
'b00, //
'b011, // CAS Latency,{A6,A5,A4}=011
'b0, //Adressing Mode,A3=b0
'b000 //Brust Length(1,{A2,A1,A0}=000)
};
end
INIT_DONE:
case (work_state_reg)
IDLE,WORK_TRCD,WORK_LATENCY,WORK_TRC,WORK_READ_DATA,WORK_TWR,WORK_TRP: begin
sdram_cmd_r <= CMD_NOP;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
WORK_ACTIVE: begin
sdram_cmd_r <= CMD_ACTIVE;
if(wr_ctrl_reg=='b0)begin
sdram_ba_r <= wr_addr_i[:]; //L-Bank address
sdram_addr_r <= wr_addr_i[:]; //row address
end
else begin
sdram_ba_r <= rd_addr_i[:]; //L-Bank address
sdram_addr_r <= rd_addr_i[:]; //row address
end
end
WORK_READ: begin
sdram_cmd_r <= CMD_READ;
sdram_ba_r <= rd_addr_i[:]; //L-Bank address
sdram_addr_r <= {
'b0010, // A10=1,precharge
rd_addr_i[:] //column address
};
end
WORK_WRITE: begin
sdram_cmd_r <= CMD_WRITE;
sdram_ba_r <= wr_addr_i[:]; //L-Bank address
sdram_addr_r <= {
'b0010, // A10=1,precharge
wr_addr_i[:] //column address
};
end
WORK_AUTO_REFRESH: begin
sdram_cmd_r <= CMD_A_REF;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
default: begin
sdram_cmd_r <= CMD_NOP;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
endcase
default: begin
sdram_cmd_r <= CMD_NOP;
sdram_ba_r <= 'b11;
sdram_addr_r <= 'h1fff;
end
endcase
end // write data control
reg [:] sdr_din;
reg sdr_dlink;
always @ (posedge clk_i or negedge rst_n_i)
if(!rst_n_i) sdr_din <= 'd0; //
else if((work_state_reg == WORK_WRITE) | (work_state_reg == WORK_TWR)) sdr_din <= wr_data_i;
always @ (posedge clk_i or negedge rst_n_i)
if(!rst_n_i) sdr_dlink <= 'b0;
else if((work_state_reg == WORK_WRITE) | (work_state_reg == WORK_TWR)) sdr_dlink <= 'b1;
else sdr_dlink <= 'b0;
assign SDRAM_DQ = sdr_dlink ? sdr_din : 'hzzzz; // read data control
reg[:] sdr_dout;
always @ (posedge clk_i or negedge rst_n_i)
if(!rst_n_i) sdr_dout <= 'd0;
//else if((work_state_reg == WORK_READ_DATA)| (work_state_reg == WORK_LATENCY)) sdr_dout <= SDRAM_DQ;
else if ( (work_state_reg == WORK_READ_DATA)| (work_state_reg == WORK_LATENCY)) sdr_dout <= SDRAM_DQ;
assign rd_data_o = sdr_dout; endmodule
仿真波形:
初始化状态机:
工作状态机:
SDRAM总结的更多相关文章
- 【iCore3 双核心板_FPGA】实验二十八:基于SDRAM 的VGA 驱动器的设计
本实验设计的VGA显示驱动完全基于FPGA实现,用SDRAM做缓存设备,通过ARM控制VGA显示的内容.ARM 通过FSMC总线向FPGA发送数据,由于总线的速度和VGA的显示速度与SDRAM的读写速 ...
- (三)内存 SDRAM 驱动实验 (杨铸 130 页)(勉强能懂个大概)
SDRAM 芯片讲解: 地址: 行地址 (A0-A12) 列地址 (A0-A8) 片选信号(BA0 BA1)(L-BANK)(因为SDRAM有 4片) 两片SDRAM 连线唯一区别在 UDQM ...
- SDRAM控制器的Verilog建模之一
前言:作为经典存储器的三剑客中的flash和sram已经建模测试过了,虽然现在都已经ddr2,ddr3,667MHZ.1333MHZ的天下了,但是接下这周来准备写一下sdram的controller. ...
- SDRAM的主要参数
(1) 容量.SDRAM的容量经常用XX存储单元×X体×每个存储单元的位数来表示.例如某SDRAM芯片的容量为4M×4×8bit,表明该存储器芯片的容量为16 M字节.或128 M bit. (2) ...
- SDRAM,DRAM,SRAM,DDR的概念
一:SDRAM SDRAM(Synchronous Dynamic Random Access Memory),同步动态随机存储器,同步是指 Memory工作需要同步时钟,内部的命令的发送与数据的传输 ...
- RAM,SRAM,DRAM,SDRAM,DDR RAM,ROM,PROM,EPROM,EEPROM,NAND FLASH,NOR FLASH的区别
RAM:由字面意思就可以理解,SDRAM SRAM DRAM(下面蓝色字体的这几种)都可以统称RAM,random access memory(随机存取存储器)的缩写,下面是51hei.com为大家整 ...
- 调试2440 RAM拷贝至SDRAM遇到的问题
汇编代码主要是初始化一些寄存器,关狗,初始化时钟,初始化存储管理器以便访问内存,然后将SoC上4k RAM数据拷贝至SDRAM,然后在SRAM里面运行,由于代码未正常跑起来,于是使用JLinkExe来 ...
- ARM学习篇 SDRAM理解
1.SDRAM单管存储单元 SDRAM单管电路图 C记忆单元 T控制门管 Z字线 W位线 注:图示为N沟道耗尽型MOS管 写入:Z加高电平,MOS导通,W状态决定了电容C的状态 读出:Z加高电平,MO ...
- SDRAM和dcfifo的联合
SDRAM和dcfifo的联合 设计原理 在"SDRAM突发读写页"实验中,留下了一个问题,就是从SDRAM读取数据的速度要与SDRAM的驱动时钟同步,这就造成了读出的数据的速率过 ...
- SDRAM读写一字(下)
SDRAM读写一字 SDRAM控制模块 上电后进行初始化状态,初始化完成后进入空闲状态,在此进行判断如下判断: 如果自刷新时间到,则进行自刷新操作,操作完成后重新进入空闲状态: 如果读使能有效则进行读 ...
随机推荐
- csharp: Data binding in WPF DataGrid control
<Window x:Class="WpfProjectDemo.MainWindow" xmlns="http://schemas.microsoft.com/wi ...
- [PHP] url的pathinfo模式加载不同控制器的实现
使用自动加载和解析url的参数,实现调用到不同的控制器,实现了pathinfo模式和普通的url模式 文件结构: |--Controller |--Index |--Index.php |--Appl ...
- ASP.NET WebAPI 07 路由
WebAPI的中路由设计与ASP.NET相似,但又是独立的一套框架. HttpRoute HttpRoute主要提供了路由模板,用于匹配url,生成virtualPath. public interf ...
- [mysql] timestamp自动更新和初始化
1.概述 在我们设计表的时候,考虑将行数据的创建时间和最后更新时间记录下来是很好的实践.尤其是可能需要做数据同步或者对数据新鲜度有要求的表.举些应用场景,更新距上次更新超过2小时的行数据,或者是将一个 ...
- iScroll-js—“smooth scrolling for the web”
原文地址: http://bigdots.github.io/2015/12/15/iScroll-js%E2%80%94%E2%80%94smooth%20scrolling%20for%20the ...
- Fix Internet Explorer Crashes with SharePoint 2013 Online Presence Indicators
IE中,只要是鼠标浮动到人名字上面的状态的时候,这个状态是与Lync相连接的,IE就会出现停止工作. 以下是解决方法. Until the other day when I figured this ...
- 转:Eclipse 一直不停 building workspace... 完美解决总结
原文地址: Eclipse 一直不停 building workspace... android开发论坛 juapk 完美解决总结 一.产生这个问题的原因多种 1.自动升级 2.未正确关闭 3.ma ...
- 转 asp.net中如何退出整个框架(frameset),回到登录界面
如: <frameset rows= "74,*,0,0 " cols= "* " frameborder= "NO " border ...
- STL--双端队列(deque)和链表(list)
双端队列(deque容器类): #include<deque>与vector 类似,支持随机访问和快速插入删除,它在容器中某一位置上的操作所花费的是线性时间. 与vector不同的是:de ...
- 无需cygwin,使用NDK进行开发
NDK从7开始自带编译器,在windows上无需配置cygwin的环境. 在eclips中配置NDK路径 在eclipse中点击菜单栏window-Perferences,配置NDK的路径. 在工程中 ...