异步FIFO的VHDL设计(一)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
异步FIFO的VHDL设计(一)
FIFO(先进先出队列)是一种在电子系统得到广泛应用的器件,通常用于数据的缓存和用于容纳异步信号的频率或相位的差异。
FIFO 的实现通常是利用双口RAM和读写地址产生模块来实现的。
FIFO 的接口信号包括异步的写时钟(wr_clk)和读时钟(rd_clk)、与写时钟同步的写有效(wren)和写数据(wr_data)、与读时钟同步的读有效(rden)和读数据(rd_data)。
为了实现正确的读写和避免FIFO的上溢或下溢,通常还应该给出与读时钟和写时钟同步的FIFO的空标志(empty)和满标志(full)以禁止读写操作。
1 异步FIFO功能描述
图1给出了FIFO的接口信号和内部模块图。
由图1可以看出,写地址产生模块根据写时钟和写有效信号产生递增的写地睛,读地址产生模块根据读时钟和读有效信号产生递增的读地址。
FIFO的操作如下:在写时钟wr_clk的升沿,当wren有效时,将wr_data写入双口RAM中写地址对应的位置中;始终将读地址对应的双口RAM中的数据输出到读数据总线上。
这样就实现了先进先出的功能。
写地址产生模块还根据读地址和写地址关系产生FIFO的满标志。
当wren有效时,若写地址2=读地址时,full为1;当wren无效时,若写地址1=读地址时,full为1。
读地址产生模块还根据读地址
和写地址的差产生FIFO的空标志。
当rden有效时,若写地址-1=读地址时,empty为1;当rden无效时,若写地址=读地址时,empty 为1。
按照以上方式产生标志信号是为了提前一个时钟周期产生对应的标志信号。
由于空标志和满标志控制了FIFO的操作,因此标志错误会引起操作的错误。
如上所述,标志的产生是通过对读写地址的比较产生的,当读写时钟完全异步时,对读写地址进行比较时,可能得出错误的结果。
例如,在读地址变化过程中,由于读地址的各位变化并不同步,计算读写地址的差值,可能产生错误的差值,导致产生错误的满标志信号。
若将未满标志置为满标志时,可能降低了应用的性能,降低写数据速率;而将满置标志置为未满时,执行一次写操作,则可能产生溢出错误,这对于实际应用来说是绝对应该避免的。
空标志信号的产生也可能产生类似的错误。
2 异步FIFO的改进设计
从以上分析中可以看出,异步FIFO之所以会发生错误是国为在地址变化时,由于多位地址各位变化时间不同,异步时钟对其进行采样时数值可能为不同于地址变化丧后数值的其他值,异步产生错误的空标志和满标志,以致于产生FIFO的操作错误。
格雷码是一种在相邻计数值之间只有一位发生变化的编码方式。
可以看出,若读写地址采用格雷码编码方式,就可以解决上面的问题。
为了应用的灵活,还增加了两个标志信号,将满(almosf_full)
标志和空(almost_empty)标志分别定义如下:当写地址与读地址的距离小于某个预先定义数值时,almost_full为1;当读地址与写地址的距离小于这个预先定义的数值时,almost_empty为1。
3 异步FIFO的VHDL实现
硬件描述语言VHDL(V ery-high speed IC Hardware Description Language)是一种应用于电路设计的高层次描述语言,具有行为级、寄存器传输级和门级等多层次描述,并且具有简单、易读、易修改和与工艺无关等优点。
目前VHDL语言已经得到多种EDA工具的支持,综合工具得到迅速发展,VHDL语言的行为级综合也已经得到支持和实现,因此利用VHDL语言进行电路设计可以节约开发成本和周期。
首先给出格雷码和普通自然码之间的转换模块的VHDL程序。
程序1:自然码码到格雷码的转换程序
entity norm_to_gery is
generic(width:integer:=8);
port(
din:in std_logic_vector(width-1 downto 0);
dout:out std_logic_vector(width-1 downto 0);
end norm_to_grey;
architecture norm_to_grey of norm_to_grey is begin
dout<=din xor(‘0’ & din(width-1 downto 1));
end norm_to_grey;
程序2:格雷码到自然码的转换程序
process(din)
variable tempd:std_logic;
begin
for i in width-1 downto 0 loop tempd:=‘0’;。