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 ...
随机推荐
- 「caffe编译bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11
CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD ...
- Mybatis Common Mapper文件
表名/条件/字段 都可以传入进去 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mappe ...
- 13.Python3标准库--互联网
(一)urllib.parse:分解url urllib.parse模块提供了一些函数,可以管理URL以及组成部分 1.解析 from urllib.parse import urlparse ''' ...
- 部署weblogic 12c的几点收获
最近刚编写完weblogic12c的部署脚本,这里将过程中的几点收获进行记录: 1.windows下编写的脚本在linux环境下运行需要dos2unix进行格式转换 2.weblogic安装环境检测需 ...
- java并发-同步容器类
java平台类库包含了丰富的并发基础构建模块,如线程安全的容器类以及各种用于协调多个相互协作的线程控制流的同步工具类. 同步容器类 同步容器类包括Vector和Hashtable,是早期JDK的一部分 ...
- Python+Selenium 自动化实现实例-模块化调用
public 目录存一些公共模块,供用例调用.login.py 内容如下: # coding=utf-8 import time # login def login(driver): driver.f ...
- 转载:C++ typename的起源与用法
转载:http://feihu.me/blog/2014/the-origin-and-usage-of-typename/#typename 侯捷在Effective C++的中文版译序中提到: C ...
- EasyUi – 6.easyui常见问题
1.进度条 2.JQuery EasyUI弹出对话框解决Asp.net服务器控件无法执行后台代码的方法 3. 三张表的连接查询现在到datagrid里 4.日期组合框DateBox设置readonly ...
- HTML5 Canvas 初探
仅仅只是一个简单的hello world. js代码很简单: <!DOCTYPE HTML> <html lang="cn"> <head> & ...
- 几道坑人的PHP面试题 试试看看你会不会也中招
这篇文章主要介绍了几道坑人的PHP面试题,试试看看你会不会也中招,这些题目都用了一些障眼法,需要你有一双火眼金睛哦,需要的朋友可以参考下 这几道题是在德问上看到的,感觉挺有意思,拿来给大家分享其中的陷 ...