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. 【转载】selenium之 定位以及切换frame(iframe)

    更多关于python selenium的文章,请关注我的专栏:Python Selenium自动化测试详解 总有人看不明白,以防万一,先在开头大写加粗说明一下: frameset不用切,frame需层 ...

  2. 码源中国.gitignore忽略文件配置

    码源中国.gitignore忽略文件配置 ## Ignore Visual Studio temporary files, build results, and ## files generated ...

  3. Photon3Unity3D.dll 解析一

    IPhotonPeerListener  Photon客户端回调接口 1: //只要有来自Photon Server的事件就触发 2: public virtual void OnEvent( Eve ...

  4. HDU3974 Assign the task(多叉树转换为线段+线段树区间染色)

    题目大意:有n个人,给你他们的关系(老板和员工),没有直属上司的人就是整个公司的领导者,这意味着n个人形成一棵树(多叉树).当一个人被分配工作时他会让他的下属也做同样的工作(并且立即停止手头正在做的工 ...

  5. csu 1550(字符串处理思路题)

    1550: Simple String Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 481  Solved: 211[Submit][Status][ ...

  6. Reverse Nodes in k-Group——简单的指针问题

    Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If ...

  7. MySQL增删改数据

    1.增加数据 ,); /*插入所有字段.一定依次按顺序插入--字符串与日期需要加单引号,数字不需要,各个字段之间用逗号分隔*//*注意不能少或者多字段值*/ ,) /*按字段名插入数据,中间用逗号隔开 ...

  8. 诺基亚9 PureView正式发布

    [手机中国新闻]当地时间2月24日下午16点,HMD在西班牙巴塞罗那正式发布了诸多新品,其中最吸睛的莫过于Nokia 9 PureView.作为全球首款五摄新机,Nokia 9 PureView后置五 ...

  9. win2008 r2 服务器php+mysql+sqlserver2008运行环境配置(从安装、优化、安全等)

    这篇文章主要介绍了win2008 r2 服务器php+mysql+sqlserver2008运行环境配置(从安装.优化.安全等),需要的朋友可以参考下 win2008 r2 安装 http://www ...

  10. go chapter 10 函数 方法 struct的方法

    1. struct的方法 // 定义struct type MyStruct struct{} // 定义方法 (那个对象可以回调)方法名(参数) 返回值 {} (s *MyStruct) FillS ...