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的更多相关文章

  1. LPC(Low Pin Count) 与SIO(Super IO)

    记录bios学习的点点滴滴,虽然已经学了很长时间才发出来,但就当是温故而知新吧,由于水平有限,难免存在错误,望指正,同时感谢CSDN提供的平台. 1.LPC 定义:​ Intel所定义的PC接口,将以 ...

  2. PatentTips - Invalidating TLB entries in a virtual machine system

    BACKGROUND This invention relates to virtual machines. In particular, the invention relates to trans ...

  3. FPGA4U FPGA SDRAM Controller

    -- https://fpga4u.epfl.ch/wiki/FPGA4U_Description -- The SDRAM bits data ..> signals, -- one ..&g ...

  4. 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 ...

  5. SDRAM总结

    使用的流程 W9825G6JH winbond sdram 4M words X 4banks X 16bits=. Accesses to the SDRAM are burst oriented. ...

  6. sdram控制2

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

  7. Java8 函数式接口-Functional Interface

    目录 函数式接口: JDK 8之前已有的函数式接口: 新定义的函数式接口: 函数式接口中可以额外定义多个Object的public方法一样抽象方法: 声明异常: 静态方法: 默认方法 泛型及继承关系 ...

  8. Java 8函数式接口functional interface的秘密

    Java 8函数式接口functional interface的秘密 2014年10月29日 17:52:55 西瓜可乐520 阅读数:3729   目录 [−] JDK 8之前已有的函数式接口 新定 ...

  9. Open Source Universal 48 pin programmer design

    http://www.edaboard.com/thread227388.html Hi, i have designed a 48 pin universal programmer but need ...

随机推荐

  1. HOJ 1108

    题目链接:HOJ-1108 题意为给定N和M,找出最小的K,使得K个N组成的数能被M整除.比如对于n=2,m=11,则k=2. 思路是抽屉原理,K个N组成的数modM的值最多只有M个. 具体看代码: ...

  2. Xcode及模拟器SDK下载

    http://blog.csdn.net/zhangao0086/article/details/38491271 吐槽下,百度打着无限分享的旗号,却又让分享资源过期,让分享者持续维护 如果你嫌在Ap ...

  3. 出现ERROR: While executing gem ... (Gem::FilePermissionError)这种错误的解决办法

    重新安装ruby即可解决 brew install ruby

  4. Linux下通过源码编译安装程序(configure/make/make install的作用,然后在/etc/profile文件里修改PATH环境变量)

    一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件:就是通常我们见到的lib目录下的文件 配置文件:这个不必多说,都知道 帮助文档:通常是我们在 ...

  5. Hadoop(一):概述

    一.Hadoop是什么? Hadoop是一个由Apache基金会所开发的分布式系统基础架构.Hadoop框架最核心的设计包含两个方面,一是分布式文件系统(Hadoop Distributed File ...

  6. 洛谷 P1568赛跑 题解

    题目传送门 这道题非常的水,只要你能搞清楚题意,将SH.KC不要混起来即可(所以我使用了结构体) #include<bits/stdc++.h> using namespace std; ...

  7. ASP.NET Zero--4.不使用谷歌字体,提升加载速度

    jtable控件样式中会使用到谷歌字体,每次访问都特别慢 1.打开jtable.css文件 [..\MyCompanyName.AbpZeroTemplate.Web\libs\jquery-jtab ...

  8. poj3414 Pots(BFS)

    题目链接 http://poj.org/problem?id=3414 题意 有两个杯子,容量分别为A升,B升,可以向杯子里倒满水,将杯子里的水倒空,将一个杯子里的水倒到另一个杯子里,求怎样倒才能使其 ...

  9. 转:Meltdown Proof-of-Concept

    转:https://github.com/IAIK/meltdown Meltdown Proof-of-Concept What is the difference between Meltdown ...

  10. Linux内存管理中的slab分配器

    转载自:http://edsionte.com/techblog/archives/4019 Linux内核中基于伙伴算法实现的分区页框分配器适合大块内存的请求,它所分配的内存区是以页框为基本单位的. ...