概述
1.首先了解一下什么是控制交互信号?
答:控制交互信号用于作为控制指示信号,比如当某个电路模块有数据输入端口data,但是电路不可能每个时钟周期都对端口输入的数据做处理,那一般上一级电路会同时给出一个指示信号,比如in_valid,用于表示当前端口data输入的数据是有效的,电路需要对其进行采集或做运算处理。同样的对于电路模块输出数据时,也需要给出类似的信号,表明当前输出端口的数据是否有效,例如o_valid信号等。还有就是比如像FIFO,RAM的读写使能信号,用于控制FIFO,RAM是否需要正常进行工作;读写控制信号用于指示是读还是写操作行为。以及总线的一系列控制信号等,CPU的指令等等,都可以说是控制信号。常用于作为控制模块产生控制信号的就是状态机。总结一下,就是没有控制信号只有运算电路,电路就是块板砖,我行我素,无任何意义,当我们设计电路模块的时候,往往最先需要搞明白的就是本电路模块的交互控制接口的时序。
2.同步和异步FIFO的设计和验证
FIFO:FIFO 是一种先进先出的数据缓存器,一般用在两边读写带宽不一致,或者位宽不一样的地方。
使用场景:数据的缓冲、时钟域的隔离(跨时钟域多bit数据的同步)、用于不同宽度的数据接口达到数据宽度匹配的目的。
FIFO的模块:双端口的RAM(用来存储数据)、读/写地址产生模块、读/写地址同步模块。
空满地址是根据读地址和写地址的比较产生的,而读写地址位于不同的时钟域,所以需要同步电路进行同步;复位时,空有效,满无效,此时只能写数据,禁止读数据,在写满的时候,满有效,空无效,此时只能读数据,禁止写数据。
a.FIFO的信号:
w:写时钟域一方的信号
r:读时钟域一方的信号
wclk: 写时钟
wrst_n: 写复位
rclk: 读时钟
rrst_n: 读复位
winc(wen): 外部输入的写使能信号
rinc(ren): 外部输入的读使能信号
wdata: 要写进的数据,即要写进FIFO里面存储的数据
rdata: 读数据,从FIFO里面读出来的数据
wfull: 写满的状态信号
rempty: 读空的状态信号
wclken: RAM的允许写信号,在这个信号有效的情况下,才可以往进写数据
rclken: RAM的允许读信号,在这个信号有效的情况下,才可以读的出数据
waddr: RAM的写地址
raddr: RAM的读地址
wptr: 要同步到写时钟的读指针
rptr: 要同步到读时钟的写指针
wq2_rptr: 读地址rptr同步到写时钟域的写地址
rq2_wqtr: 写地址wptr同步到读时钟域的读地址
syn_r2w: 读同步到写触发器链中间信号
syn_w2r: 写同步到读触发器链中间信号
b.FIFO的常见参数:
FIFO的宽度:FIFO一次读写操作的数据位
FIFO的深度:如果宽度为N,FIFO可以存储的N位数据的个数
满标志:FIFO 已满或将要满时由 FIFO 的状态电路送出的一个信号,以阻止 FIFO 的写操作继续向FIFO 中写数据而造成溢出(overflow)
空标志: FIFO 已空或将要空时由 FIFO 的状态电路送出的一个信号,以阻止 FIFO 的读操作继续从 FIFO 中读出数据而造成无效数据的读出(underflow)
写指针:总是指向下一个将要被写入的单元,在复位时,指向第一个单元
读指针:总是指向当前要读出的数据,在复位时,指向第一个单元
c.FIFO的空满检测:
当读写指针相等时,FIFO为空(读空),此种情况可能发生在复位操作时,或者当读指针读出最后一个字后追上了写指针。当读写指针再次相等时,表明FIFO为满(写满),这种情况发生在当写指针转了一圈,折回来又追上了读指针。
d.同步FIFO的空满检测方法:
利用计数器,用计数器来指示当前FIFO中的数据个数。当FIFO读和写使能同时有效时,count不加也不减,此时表示FIFO在同时进行读写操作。如果写使能有效并且full=0,则count+1,表示写操作且FIFO未满的时候,FIFO中的数据增加了1。如果读使能有效且 empty=0,则 count-1,表示FIFO未满时候在进行读操作,FIFO 中的数据个数减少了1。
当count=0时,此时FIFO为空,需要设置empty的值1,如果count的值等于深度的值,表明此时FIFO已满,需要设置full的值为1。
e.同步FIFO的设计思路:思路1:利用计数器来判断空满
假如FIFO的深度为8,我们设计一个计数器,用该计数器来指示当前FIFO中的数据个数。复位的时候,count =0;如果读使能和写使能同时有效的时候,count不加也不减,表示同时对FIFO进行读写操作的时候,FIFO中的数据个数不变;如果写使能有效且非满的时候,则 count+1,表示进行写操作且FIFO未满时候,FIFO中的数据个数增加了1;如果读使能有效且非空的时候,则count-1; 表示读操作且FIFO 未满时候,FIFO 中的数据个数减少了 1;需要注意,如果 count=0 的时候,表示FIFO为空,需要设置empty=1;如果count=8 的时候,表示 FIFO现在已经满,需要设置 full=1。
f.思路2:利用拓展地址位的方式判断空满
假如FIFO的深度为8,23=8即原始的地址为3比特,这时我们就可以定义两个4比特的地址(一个读地址,一个写地址),并且利用拓展的地址来判断空满。
我们来考虑几种情况,假如FIFO的宽度为3,拓宽的读写地址为4比特,此时往里边写了8个数据而且没有往出读,则写地址为1000,读地址为0000,此时FIFO已满,写地址与读地址最高位相同,低三位相反;第二种情况,假如写了8个数据,并且读了8个数据·,此时读写地址都为1000,要产生空信号,随后我们又继续写数据,当写了7个数据的时候,写地址为1111,若再写1个数据·,此时的写地址为0000,而读地址为1000,已经写满,可以看到,写地址与读地址最高位相同,低三位相反。所以我们就可以把地址拓宽一位,并根据最高位相反,其余位相等的方法来判断空满。比如一个宽度为3的FIFO此时写地址为0110,读地址为1110,可以判断此时已满,具体来分析可能是这个样子的:先写了8个数据,并且随后读了8个数据·,又继续写了8个数据,这次只读了6个,等于又空出来了6个位置,那就可以继续写6个数据,若没有读出,此时可以看出已经写满。补充一下,若读和写的地址相同,说明此时的信号为空。
补充:
reg [7:0] RAM [15:0]; //RAM的深度为16,位宽为8位;
RAM[wp[3:0]] <= iData;
oData_reg <= RAM[rp[3:0]]; //在进行寻址操作;
g.异步FIFO的空满检测方法:
异步FIFO的检测方法与同步FIFO利用拓展位判断空满的方法相同,但是需要注意,异步FIFO的读写时钟不同,判断空满属于跨时钟域的问题,这时我们就需要用格雷码来做空满判断。为什么二进制码不适合做空满判断呢,因为二进制的读写指针在增减时,经常多位发生突变,比如四位地址1111会在下一个时刻变成0000,而在实际的电路中,这个变化状态要持续很长一段时间,1111会经历四个状态转变到0000,比如1111-1101-1100-0100-0000,由于写时钟与读时钟不同步,所以异步的写时钟可能会在某个不稳定的状态采样,这样就会得到错误上午指针,进而做出错误的状态判断,导致系统异常,而且由于多位同时突变,根据概率论的知识我们可以知道,发生错误的概率很大。为了避免这个问题的发生,我们选用格雷码,格雷码在状态跳变时每次只有一位发生变化,这样即使在中间状态进行采样,结果也不外乎两种,递增前的原指针和递增后的新指针,在采样时如果采样到递增后的新指针,那么和我们的预期是一致的,如果采样到递增前的指针,我们来分析一下,假如现在采样读指针,可能把已经读出判断为没有读出,那么最坏的情况就是把不满判断成了满,使得原先被允许的写操作被禁止,但是这并不会对逻辑产生影响,只是带来了写操作的延时。另外一种情况,假如现在采样写指针,可能把已经写入判断为没有写入,那么最坏的情况就是把不空判断成了空,使得原先被允许的读操作被禁止,但是这也并不会对逻辑产生影响,只是带来了读操作的延时。
异步FIFO的模块:
除了RAM模块,读写控制模块之外,异步FIFO还有二进制转格雷码模块和两级同步模块共五大模块。
注意:
异步判断空满时使用的是格雷码,若为空状态时,每一位都相同,若为满状态时,应是高两位相反,其余位相同。
最后附上老师常说的一句话:纸上得来终觉浅,绝知此事要躬行
转自公众号:于博士Jacky
最后
以上就是欢呼小海豚为你收集整理的同步异步FIFO相关问题的全部内容,希望文章能够帮你解决同步异步FIFO相关问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复