SDRAM interface slashes pin count
Many designs need deep buffering but don't require ultrahigh-memory bandwidth. Examples include image and audio processing, as well as some deep-FIFO applications. These designs often use a single ×8 SDRAM device that connects to an FPGA or ASIC. This approach solves the buffering problem but also burns a lot of valuable pins, which can be as many as 27 for a single SDRAM device. The design inFigure 1 takes advantage of the burst counter inside the SDRAM to reduce this pin count to 18 by multiplexing the lower eight address lines with the data. The efficiency loss is low; the design requires only one extra clock during the write burst. Figure 1uses an 8Mx8, 125-MHz SDRAM, but this technique works with any SDRAM.
The read- and write-cycle timing diagrams reveal the secret (Figure 2). The figureshows a burst of 4, but any power-of-2 burst works. These diagrams assume a 50-MHz system clock, a read latency of 2, and a full-page burst. During the read cycle (Figure 2a), the data bus is inactive during the initial portion of the cycle (when the row and column addresses are presented), so there's no problem with using the data bus to carry address data. A precharge command ends the burst and prepares the RAM for the next access.
For the write cycle, however, some trickery is necessary (Figure 2b). Normally, the first byte of write data is presented to the SDRAM with the Write command, along with the starting column address for that burst. By asserting the DQM (data-mask) signal, the SDRAM ignores the data lines during this phase, thus allowing them to be used for the column address.
Note that the DQM signal does not prevent the internal column address from incrementing, however. Thus, the write-column address presented with the Write command must be one less than the desired burst starting address. For FIFO designs, this requirement is trivial because you can initialize the write-address column counter to –1 rather than 0. The column-address counter in the SDRAM wraps around at the end of the column, so this approach works even at the beginning of a column.
You can download a simplified version of a FIFO controller that uses this technique, described in the Verilog language. The listing omits some of the details, such as SDRAM refresh/init cycles, and FIFO flags, to highlight the portions relevant to this design. This controller uses a simple eight-state finite-state machine to generate the SDRAM control signals and uses a pair of row/column counters to keep track of the FIFO put/get pointers. The special initialization and incrementing of the write row and column pointers satisfies the requirement that the write column start off one behind the desired write address. The code occupies 35% of a small Xilinx SpartanXL-S10 device, and runs at 50 MHz. For the sake of example, all of the outputs are combinatorial, but a true high-speed design should use registered I/O.
You can extend this idea to ×16 SDRAMs and to multiplex a few more of the address lines while getting a boost in memory bandwidth. If you do extend the idea, be careful with SDRAM line A10 because this line has special meaning during some SDRAM commands. You can also use this technique with double-data-rate SDRAMs.


;*********************************************************************************
; di2659.txt
;
; LISTING - FIFO CONTROLLER
;
; "SDRAM interface slashes pin count," EDN, March , , pg
; http://www.ednmag.com/ednmag/reg/2001/03292001/designideas.htm#07di4
;********************************************************************************* `timescale ns / ns /*
** Minimal-pin SDRAM controller with FIFO address counters. This
** has a simple do_write/wr_ok, do_read/rd_ok handshake for data input &
** output. The 'rst_fifo' signal syncronously resets the fifo
**
** Author: Tim Hellman, M&M Consulting
*/
module sdctl(clk, reset_, rst_fifo, do_write, do_read, wr_data_in, /* Fifo I/O */
wr_ok, rd_ok, rd_data_out, sd_ras_, sd_cas_, sd_we_, sd_dqm, sd_bank, /* SDRAM signals */
sd_addr_hi, sd_data
); input clk, reset_, do_write, do_read, rst_fifo;
input [:] wr_data_in; output wr_ok, rd_ok, sd_ras_, sd_cas_, sd_we_, sd_dqm;
output [:] rd_data_out;
output [:] sd_bank;
output [:] sd_addr_hi; inout [:] sd_data; /*
** States
*/
parameter StIdle = , StActive = , StRdWr = , StData1 = ,
StData2 = , StData3 = , StRdPrech = , StWrPrech = ; reg [:] State;
reg [:] RdRow, WrRow;
reg [:] RdCol, WrCol;
reg sd_data_ena, doing_write; always @(posedge clk or negedge reset_)
if (!reset_) begin
RdRow <= ; WrRow <= ; RdCol <= ; WrCol <= 'h7f;
sd_data_ena <= ; State <= StIdle; doing_write <= ;
end
else begin /*
** State machine. Once kicked off, run through all states
*/
if (State == StIdle && (do_write | do_read)) begin
doing_write <= # do_write;
State <= # State + ;
end
else if (State != StIdle) State <= # State + ; /*
** Read/write counters (note that write col counter starts
** one behind read). The Write row also increments when
** WrCol == '7e (because WrCol is always one behind)
*/
if (rst_fifo) {RdRow,RdCol} <= # ;
else if (State == StWrPrech && !doing_write)
{RdRow,RdCol} <= # {RdRow,RdCol} + ; if (rst_fifo) WrCol <= # 'h7f;
else if (State == StWrPrech && doing_write) WrCol <= # WrCol + ; if (rst_fifo) WrRow <= # ;
else if (State == StWrPrech && doing_write && WrCol == 'h7e)
WrRow <= # WrRow + ; if (State == StIdle && (do_read | do_write)) sd_data_ena <= # ;
else if (doing_write && (State == StRdPrech)
|| !doing_write && (State == StRdWr)) sd_data_ena <= # ; end /*
** Generate the SDRAM 'command' bits (combinatorially)
*/
reg [:] SdCmd;
always @(State or doing_write) begin
case (State)
StActive: SdCmd = ;
StRdWr: SdCmd = doing_write ? : ;
StRdPrech: SdCmd = doing_write ? : ;
StWrPrech: SdCmd = doing_write ? : ;
default: SdCmd = ; // NOP
endcase
end
assign {sd_ras_, sd_cas_, sd_we_} = SdCmd; /*
** Data output is either address or data
*/
wire [:] ColAddr = doing_write ? {WrCol, 'b11} : {RdCol, 2'b00};
wire [:] RowAddr = doing_write ? WrRow : RdRow; assign wr_ok = (State >= StData1 && State <= StRdPrech) & doing_write;
assign rd_ok = (State >= StData2 && State <= StWrPrech) & !doing_write; /* Upper bits of column. address must equal 0 */
wire [:] MuxAddr = (State == StActive) ? RowAddr : {'b0,ColAddr}; assign sd_bank = RowAddr[:];
assign sd_addr_hi = MuxAddr[:];
wire [:] DataOut = (State == StActive || State == StRdWr) ?
MuxAddr[:] : wr_data_in; assign sd_data = sd_data_ena ? DataOut : 'hz;
assign rd_data_out = sd_data; assign sd_dqm = doing_write ? (State == StRdWr | State == StWrPrech) :
(State == StRdPrech); endmodule
SDRAM interface slashes pin count的更多相关文章
- LPC(Low Pin Count) 与SIO(Super IO)
记录bios学习的点点滴滴,虽然已经学了很长时间才发出来,但就当是温故而知新吧,由于水平有限,难免存在错误,望指正,同时感谢CSDN提供的平台. 1.LPC 定义: Intel所定义的PC接口,将以 ...
- PatentTips - Invalidating TLB entries in a virtual machine system
BACKGROUND This invention relates to virtual machines. In particular, the invention relates to trans ...
- FPGA4U FPGA SDRAM Controller
-- https://fpga4u.epfl.ch/wiki/FPGA4U_Description -- The SDRAM bits data ..> signals, -- one ..&g ...
- JTAG 引脚自动识别 JTAG Finder, JTAG Pinout Tool, JTAG Pin Finder, JTAG pinout detector, JTAGULATOR, Easy-JTAG, JTAG Enumeration
JTAG Finder Figuring out the JTAG Pinouts on a Device is usually the most time-consuming and frustra ...
- SDRAM总结
使用的流程 W9825G6JH winbond sdram 4M words X 4banks X 16bits=. Accesses to the SDRAM are burst oriented. ...
- sdram控制2
芯片手册要求sdram需要在64ms内刷新8K次,否则里面的数据会丢失,因此在64ms分成8192次,每次刷新充一次电,然后给两次自动刷新命令即可. /*----------------------- ...
- Java8 函数式接口-Functional Interface
目录 函数式接口: JDK 8之前已有的函数式接口: 新定义的函数式接口: 函数式接口中可以额外定义多个Object的public方法一样抽象方法: 声明异常: 静态方法: 默认方法 泛型及继承关系 ...
- Java 8函数式接口functional interface的秘密
Java 8函数式接口functional interface的秘密 2014年10月29日 17:52:55 西瓜可乐520 阅读数:3729 目录 [−] JDK 8之前已有的函数式接口 新定 ...
- Open Source Universal 48 pin programmer design
http://www.edaboard.com/thread227388.html Hi, i have designed a 48 pin universal programmer but need ...
随机推荐
- 无状态Http
无状态的根本原因 浏览器和服务器使用socket通信,服务器将请求结果返回给浏览器后,会关闭当前socket连接.而且服务器会在处理页面完毕后销毁页面对象. 应用层面的原因 浏览器和服务器之间通信都遵 ...
- 关于U3D中的移动和旋转
关于移动,其实很简单,就是移动: 第一个参数标识移动的距离,是一个矢量:第二个参数是因为游戏对象有自己的坐标系,还有一个世界坐标系,使用的坐标系不同将导致运动的结果不同: function Trans ...
- Jmeter组件和属性(二)
Jmeter脚本开发原则 简单.正确.高效.简单:去除无关的组件,同时能复用的尽量复用.正确:对脚本或者业务正确性进行必要的判断,不能少也不能多.(200),业务错误的情况下,也可能返回200,必须用 ...
- csu 1547(01背包)
1547: Rectangle Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 996 Solved: 277[Submit][Status][Web ...
- Jmeter----连接mysql数据库及常见问题处理
jmeter要链接mysql数据库,首先得下载mysql jdbc驱动包,(注:驱动包的版本一定要与你数据库的版本匹配,驱动版本低于mysql版本有可能会导致连接失败报错) 本人的数据为5.7.18, ...
- webapi调用post时自动匹配参数
[HttpPost] public async Task<string> Post() { dynamic model = await Request.Content.ReadAsAsyn ...
- Javascript、C#、php、asp、python 等语言的链式操作的实现
一.什么是链式操作 把需要的下一步操作的对象通过上一步操作返回回来.使完成某些功能具有持续性. 二.链式操作优点 代码更精简优雅.链式操作能大大精简代码量,多项操作一行代码一气呵成,搞定: 链式操作应 ...
- vue引入自己写的js文件
话不多说,直接上代码呀~ 先来个结构图: 中规中矩的vue-cli就写了一个自己的js文件 那么我想要引入到vue组件里. 1.首先写我的js文件 2.引入到vue组件!!!一定要用{}把方法名拿过来 ...
- 字符串处理strcpy strcat函数的用法
C语言函数字符串处理strcpy strcat函数的用法: 1)strcat是用来连接两个字符串的,原型是char *strcat(char *dest,char *src),作用是把src所指字符串 ...
- 第二章:监控属性(Observables)
关于Knockout的3个重要概念(Observables,DependentObservables,ObservableArray),本人无法准确表达它的准确含义,所以暂定翻译为(监控属性.依赖监控 ...