嵌入式系统数据共享存储器的实现Luo Hao (罗昊),Wang Zhihua (王志华)清华大学电子工程系北京 100084摘要:使用静态存储器(SRAM)和可编程逻辑器件(PLD)可以模拟共享存储器的行为,实现低成本、高速、大容量共享存储。
在实际应用中模拟共享存储器会遇到操作冲突的问题,这需要使用仲裁的办法加以解决。
正确选择SRAM和PLD能提高模拟共享存储器的速度。
关键字:共享存储器可编程逻辑嵌入式系统Implementation of Shared Memories in Embedded Systems Abstract: Use SRAM and PLD can simulate DPRAM to satisfy the need for high volume, high speed data switching. Collisions will arise when operate shared memory, some arbitration will be used to solve the problem. Select the right SRAM and PLD can improve the speed of the shared memory.Key word: DPRAM PLD EMBEDDED引言:有的嵌入式系统中需要使用共享存储器进行数据交换,常用的共享存储器有DPRAM (双口内存)、PRAM(多口内存)、FIFO等。
传统的DPRAM虽然简单易用,但是容量小,成本高。
使用SRAM和PLD可以方便地构成共享存储器。
1. 常见的双口内存在商用芯片中,常用的双口内存如IDT7133/4[1],容量为2K*16,异步操作,操作延迟时间20~90ns不等。
存储阵列通过左右两端的地址线独立寻址。
任意一端的接口方式与普通静态存储器完全一样。
每端有独立的片选、读出、写入信号,因为7133的数据宽度为16b,为了实现字节操作,还提供了字节读出使能,可以通过字节读出使能对其进行字节操作。
在实际的使用过程中,如果两侧同时对同一存储单元进行操作,任一侧为写入,都会使另一侧产生BUSY信号。
表示此时的操作无效,或是会出现不正常的结果。
在实际应用中这种情况是需要避免的。
2. 如何构造模拟双口内存如果在实际应用中遇到需要的双口内存容量远大于现有的双口内存的情形,可以使用多片双口内存并联的方案。
使用这种方案会使费用急剧增加,并且还需要增大存储控制器的扇出能力,增加的总线缓冲器或总线驱动器还会增加线路上的延时。
可以考虑使用一个替代的办法:使用一片或多片大容量静态存储器(SRAM)或动态存储器(DRAM)作为存储单元,使用一些外部逻辑生成两个端口,构成一个模拟双口内存。
使用类似操作双口内存的方法来操作这个模拟双口内存。
在文献[2]中有一个类似的方案,它使用SRAM实现共享存储。
图1中描绘了这种方案的实现方法。
存储阵列由SRAM构成,与SRAM操作相关的信号为数据总线,地址总线,读写控制和片选。
仲裁器由可编程逻辑实现,仲裁器的输入为两边端口送来的片选信号,读写控制信号,输出为控制存储阵列的片选及读写信号,送至处理器的等待信号和数据地址开关控制信号。
数据开关为双向三态开关,地址开关为单向三态开关。
理论上,数据和地址开关也可以集成到可编程器件中。
考虑到仲裁器的逻辑并不复杂,而数据和地址开关集成到仲裁器后,需要占用大量的可编程器件的I/O资源,从而需要选用容量较大的可编程器件。
这样会使得在实际应用中变得不太经济,所以数据地址开关采用外接的方案。
图1 模拟双口内存方案为叙述方便起见,现在两个端口分别命名为R端和L端。
理论上R端和L端是平等的,不存在任何优先的问题。
3. 基本原理当处理器需要对双口内存的一端进行读写时,将产生片选信号,仲裁器对这个片选信号进行仲裁,如果当前的状态可以允许对此端进行操作,仲裁器产生SRAM读写时序,并打开此端的数据地址开关。
从该端口写入或读出数据,如果条件不允许,仲裁器产生等待,通知处理器等待一段时间。
等待完毕后,再进行读写。
4. 如何处理冲突与双口内存不同的是,当在任一端对这个模拟双口内存进行操作,这个操作不论是读或是写,另一端都无法对这个模拟双口内存进行操作,如果正好在另一端需要对模拟双口内存进行操作,就会产生冲突,导致另一端无法立即写入或读出。
解决这个问题的有三个方法。
1、软件避免冲突保证任何时刻不会有两端同时操作模拟双口内存。
这可以再在这个模拟双口内存的基础上再附加一些处理器之间的握手。
当一端在进行操作时,另一端不操作。
这样做好好处是仲裁逻辑简单。
读写速度快。
缺点是,不能适用于某些需要实时交换数据的应用。
2、插入等待当R端需要操作模拟双口内存时,正好L端正在操作,这时可以在R端插入等待,让R 端等待一个或多个时钟周期,直到L端完成操作。
这在某些具有准同步总线的处理器上是可行的,如INTEL X86系列。
这种方式可优点是速度快,缺点是电路定时需要与处理器仔细匹配。
3、应答方式传输在任一端进行操作时,由仲裁器产生一个应答信号,告知处理器数据操作完毕。
如POWERPC处理器具有这样的传输方式。
比如当处理器需要在R端进行操作,而此时L端正在操作,仲裁器使R端的应答信号无效,一直等到L端操作完毕,并且完成R端的操作后,才送出R端操作完毕的应答信号,通知处理器操作完毕。
在这个应答的操作方式实际上隐含了等待。
能获得方式2的相同结果。
这种方法的优点是,可以以异步的方式传输数据。
实现的逻辑比较简单。
5. 仲裁机制如果模拟双口内存两端同时有操作请求,这时候会产生一个先后问题,根据不同的应用要求,可以采用固定优先级的仲裁机制,也可以采用轮流优先的仲裁机制。
6. 实现方法在这里应答方式传输避免冲突,固定仲裁优先级的方法实现模拟双口内存。
模拟双口内存的仲裁器使用两个有限状态机,分别命名为状态机0与状态机1。
状态机的时钟分别为各端的总线时钟,也就是说,两个状态机是异步的。
状态机之间依靠读取对方的状态进行通信。
如图2所示,每个状态机都有三个状态,依次为空闲态,请求态与忙态。
当复位时,两个状态机都进入空闲状态,当0端需要数据操作时,0端的片选信号变为有效,状态机0进入请求态,如果此时状态机1不处于忙态,则状态机0的下一状态为忙,否则重新进入闲态等待。
状态机在忙状态时对存储阵列进行操作。
操作完毕后等待片选信号变为无效重新进入空闲状态。
状态机1也以类似的方式运作,只是当状态机1在请求态时,因0端的优先级高,只有在状态机0为闲态时,才能进入忙态。
状态机在忙时产生存储器读写时序,并打开相应的数据和地址开关。
状态机0状态机1图2 模拟双口内存仲裁器状态机7. 具体电路在实际的电路中,存储阵列由2片NEC公司的U PD444012A,128K*16b 静态存储器构成,数据宽度为32b,总容量为512KB。
仲裁器使用了ALTERA公司EPM7032,数据开关和地址开关都使用74LVT16245三态双向缓冲器。
数据开关的方向使用写信号控制。
8. 仿真结果在MAX PLUS II中,对仲裁器进行仿真,仿真的结果如图3,从图中可以看出,不论是何端需进行数据操作,该端的CSxb有效(x为1或2),在确定的时间内能保证完成,并产生TAxb信号,作为与处理器的应答。
当两个CSxb同时有效即产生冲突时,仲裁器将按一定的先后顺序确保数据可靠传送。
在图中Taxb信号在无效时为高阻状态,这是为了适应处理器的总线操作的要求。
图3 模拟双口内存仿真结果9. 性能分析当总线时钟为66Mhz时,不发生冲突的情况下从一端读写一个数据需要的时间为:1个仲裁时钟 + 数据地址开关时延 + 存储器读写时延≈15 + 5 + 55 = 75ns也就是说无冲突时延为75ns。
发生冲突时,最坏的情况下读写一个数据需要的时间为:1个仲裁时钟+ 2 * 无冲突时延≈ 15 + 2*75 = 165ns在有冲突时,最坏的情况下需要有165ns才能读出或写入一个数据。
如果能提高总线时钟,可以减小仲裁期所占用的时间,如果选用速度更快的静态存储器,减少读写时间,有希望将最坏情况下的延时减小。
在表1中对双口内存和模拟双口内存作了一个比较表1 双口内存和模拟双口内存比较双口内存IDT7133 模拟双口内存备注速度 20ns~90ns 75ns~165ns2片32位容量 8KB 512KB成本≈100RMB≈100RMB10. 硬件测试应用模拟双口内存测试使用两块鑫微[3]MPC855T[4]标准板,模拟双口内存接在本地总线扩展口上,总线频率为60Mhz。
使用GPCM[4]与模拟双口内存接口。
MPC855T的Bootloader 为U-BOOT-1.0.2。
处理器相应的定时信息由U-BOOT完成,在U-BOOT监视命令行对模拟双口内存进行操作。
在一端使用存储器测试命令,对该端口进行不间断写入和读出,结果无误。
同时在另一端读出相应位置的模拟双口内存的内容。
结果也很正常。
说明读写冲突问题已经解决。
该硬件已在某型网络安全设备上得到应用,经长时间运行证明性能稳定可靠,达到了设计要求。
11. 结论在需要大容量快速数据交换的嵌入式系统中,为了获得较高的性价比,可以使用大容量静态存储器,配合一些外围逻辑实现本文所介绍的模拟双口内存。
模拟双口内存与嵌入式系统的接口方式跟常规的双口内存类似。
主要区别是需要在嵌入式硬件中处理冲突。
相同的思路也可以用于大容量的FIFO或多口内存。
12. 参考文献[1] HIGH-SPEED 2K x 16 CMOS DUAL-PORT STATIC RAMS [J/OE]IDT, Inc.[2] Implementing Shared Memory Interface with a TMS320C54x DSP [J/OE] TI co.[3] [4] MPC855T User’s Manual Integrated Communications Microprocessor freescale co.附录:CPLD代码(Verilog HDL)//--------------------------------------------------------------------------------------------------//// Title : ps_dpram// Design : ps_dpram// Author : Robert Luo// Company : Sinovee Microsystem////-------------------------------------------------------------------------------------------------//// File : ps_dpram.v// Generated : Thu Jan 29 15:38:15 2004//-------------------------------------------------------------------------------------------------//// Description :2 FSM be used to control each data operation// the state of each FSM as the input of the other FSM//-------------------------------------------------------------------------------------------------`timescale 1ps / 1psmodule ps_dpram ( DATAEN1b ,TA1b ,DATAEN2b ,TA2b ,CS1b ,CS2b ,RST1b ,ADEN1b ,RST2b ,CLK1 ,ADEN2b ,CLK2,//COLb,//OP1b,OP2b,DP1EN0b,DP1EN1b,DP1EN2b,DP1EN3b,DP2EN0b,DP2EN1b,DP2EN2b,DP2EN3b);input CS1b,CS2b,RST1b,RST2b,CLK1,CLK2 ;wire CS1b,CS2b,RST1b,RST2b,CLK1,CLK2 ;output DATAEN1b,TA1b,DATAEN2b,TA2b,ADEN1b,ADEN2b;output DP1EN0b,DP1EN1b,DP1EN2b,DP1EN3b;output DP2EN0b,DP2EN1b,DP2EN2b,DP2EN3b;reg DATAEN1b,DATAEN2b,ADEN1b,ADEN2b;tri TA1b,TA2b;tri DP1EN0b,DP1EN1b,DP1EN2b,DP1EN3b;tri DP2EN0b,DP2EN1b,DP2EN2b,DP2EN3b;wire DP1EN,DP2EN; //tri-state control of DP1ENb and DP2ENb;//output COLb; //OP1b,OP2b,//wire COLb; //OP1b,OP2b,reg TA1EN,TA2EN;reg bDATAEN1b,bDATAEN2b;reg CurState1,CurState2;parameter idle = 1'b0;parameter busy = 1'b1;//parameter op = 2'b10;parameter EN = 1'b0;parameter DIS = 1'b1;//counter signalsreg LOAD1,EN1;reg [3:0] CNTQ1;reg LOAD2,EN2;reg [3:0] CNTQ2;// State machine 1 //always @ (posedge CLK1 or negedge RST1b)beginif (RST1b == 1'b0)DATAEN1b = 1'b1; ADEN1b = 1'b1;TA1EN = 1'b1; CurState1 = idle; //COUNT CONTROL LOAD1 = 1'b0; EN1 = 1'b0; endelseif (CS1b == 1'b0) beginif ((CurState1 == idle) && (CurState2 != busy))beginCurState1 = busy;LOAD1 = 1'b1; EN1 = 1'b1;//ADEN1b = 1'b0;endelseif (CurState1 == busy) begin ADEN1b = 1'b0; LOAD1 = 1'b0; DATAEN1b = 1'b0; if (CNTQ1 == 1)TA1EN = 1'b0;if (CNTQ1 == 0)begin DATAEN1b = 1'b1; ADEN1b = 1'b1; TA1EN = 1'b1;CurState1 = idle;LOAD1 = 1'b0;EN1 = 1'b0;end end end end //State machine 2 //always @ (posedge CLK2 or negedge RST2b) beginif (RST2b == 1'b0)DATAEN2b = 1'b1; ADEN2b = 1'b1;TA2EN = 1'b1; CurState2 = idle; LOAD2 = 1'b0; EN2 = 1'b0; endelse if (CS2b == 1'b0) beginif ((CurState2 == idle) && (CurState1 != busy))beginCurState2 = busy;LOAD2 = 1'b1; EN2 = 1'b1; //ADEN2b = 1'b0; endelse if (CurState2 == busy && (CurState1 != busy))beginADEN2b = 1'b0; LOAD2 = 1'b0; DATAEN2b = 1'b0; if (CNTQ2 == 1)TA2EN = 1'b0;if (CNTQ2 == 0)begin DATAEN2b = 1'b1; ADEN2b = 1'b1; TA2EN = 1'b1;CurState2 = idle;LOAD2 = 1'b0;EN2 = 1'b0;end end elseCurState2 = idle;end endparameter CNTNUM = 4'b0011;//CNTNUM CAN BE CHANGED ACCORDING TO THE SRAM'S SPEED//COUNTER1always @ (posedge CLK1 or posedge LOAD1) beginif (LOAD1 == 1'b1)CNTNUM;=CNTQ1else if (EN1 == 1'b1)CNTQ1 = CNTQ1 - 1;end//COUNTER2always @ (posedge CLK2 or posedge LOAD2) beginif (LOAD2 == 1'b1)CNTNUM;=CNTQ2else if (EN2 == 1'b1)CNTQ2 = CNTQ2 - 1;endassign DP1EN = RST1b & ~DATAEN1b; assign DP2EN = RST2b & ~DATAEN2b;//assign OP1b = 1'b0;//assign OP2b = 1'b0;//assign COLb = CS1b | CS2b;assign TA1b = (TA1EN == 1'b0)? 1'b0 : 1'bZ; assign TA2b = (TA2EN == 1'b0)? 1'b0 : 1'bZ; assign DP1EN0b = (DP1EN == 1'b1)?1'b0 : 1'bZ; assign DP1EN1b = (DP1EN == 1'b1)?1'b0 : 1'bZ; assign DP1EN2b = (DP1EN == 1'b1)?1'b0 : 1'bZ; assign DP1EN3b = (DP1EN == 1'b1)?1'b0 : 1'bZ; assign DP2EN0b = (DP2EN == 1'b1)?1'b0 : 1'bZ; assign DP2EN1b = (DP2EN == 1'b1)?1'b0 : 1'bZ; assign DP2EN2b = (DP2EN == 1'b1)?1'b0 : 1'bZ; assign DP2EN3b = (DP2EN == 1'b1)?1'b0 : 1'bZ; endmodule。