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. leetcode Two Sum II - Input array is sorted <面试常考题>

    题目描述 //二分查找的变形   用头尾两个指针进行  面试考察题 class Solution { public: vector<int> twoSum(vector<int> ...

  2. (二) Mysql 数据类型简介

    第一节:整数类型.浮点数类型和定点数类型 1,整数类型 2,浮点数类型和定点数类型 M 表示:数据的总长度(不包括小数点): D 表示:小数位: 例如 decimal(5,2)      123.45 ...

  3. Python全栈开发之7、模块和几种常见模块以及format知识补充

    一.模块的分类 Python流行的一个原因就是因为它的第三方模块数量巨大,我们编写代码不必从零开始重新造轮子,许多要用的功能都已经写好封装成库了,我们只要直接调用即可,模块分为内建模块.自定义的模块. ...

  4. Loadrunner脚本开发规范

    Loadrunner脚本开发规范 目录 1.一般约定... 3 2.代码注释约定... 4 3.格式化代码... 5 1.一般约定 1.1具体脚本规则,必须在具体代码中加注释,以便脚本开发人员阅读和理 ...

  5. 十三oracle --控制结构(分支,循环,控制)

    .使用各种if语句2.使用循环语句3.使用控制语句——goto和null(goto语句不推荐使用): 二.条件分支语句pl/sql中提供了三种条件分支语句if—then,if–then–else,if ...

  6. 快速提高 Vi/Vim 使用效率的原则与途径

    Vi/Vim 是所有 Unix/Linux 操作系统默认配备的编辑器.因其强大的功能和高效的操作,Vi/Vim 也成为众多 Unix/Linux 用户.管理员必须掌握并熟练使用的编辑工具之一.尤其是在 ...

  7. 【转】eval()函数用法

    eval 功能:将字符串str当成有效的表达式来求值并返回计算结果. 语法: eval(source[, globals[, locals]]) -> value 参数: source:一个Py ...

  8. 牛客练习赛9 F - 珂朵莉的约数

    题目描述 珂朵莉给你一个长为n的序列,有m次查询 每次查询给两个数l,r 设s为区间[l,r]内所有数的乘积 求s的约数个数mod 1000000007 输入描述: 第一行两个正整数n,m第二行一个长 ...

  9. 堆优化Dijkstra计算最短路+路径计数

    今天考试的时候遇到了一道题需要路径计数,然而蒟蒻从来没有做过,所以在考场上真的一脸懵逼.然后出题人NaVi_Awson说明天考试还会卡SPFA,吓得我赶紧又来学一波堆优化的Dijkstra(之前只会S ...

  10. 洛谷P3803 【模板】多项式乘法 [NTT]

    题目传送门 多项式乘法 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字, ...