首页 » 互联网 » 为什么FPGA调试中双口RAM的读写冲突老是隐藏的很深很深_状况_冲突

为什么FPGA调试中双口RAM的读写冲突老是隐藏的很深很深_状况_冲突

神尊大人 2025-01-08 23:18:21 0

扫一扫用手机浏览

文章目录 [+]

FPGA调试本身便是挺辛劳的一件事情,尤其是在刚开始调试FPGA的时候,无论培训的时候如何强调一些把稳事变,如跨时钟域问题,如接口问题,以及RAM读写冲突问题,但一旦做起项目来,每每还是有同学必须要亲自往这些坑里面跳一次才真正懂得这些BUG的含义。

这么多年了,每届学生都是如此。

为什么FPGA调试中双口RAM的读写冲突老是隐藏的很深很深_状况_冲突 互联网

双口RAM读写冲突的问题,每每在性能的边界极限测试的时候才暴露出来。
每每分为不宜重现和可重现两种。
虽然可重现,但一步步根据缺点征象进行旗子暗记追踪到出问题的双口RAM时,已经由去了一周或数周的韶光。
不宜重现的问题则更加麻烦,有时候几个小时还不出一次问题。
避免这种问题的的根本办理办法便是戒备于未然,在代码的仿真阶段就对各个双口RAM进行读写冲突的防护方法。

双口RAM对同一个地址同时读写、对同一个地址写的冲突,每年都要跟这个问题斗争一两次,每次少则几天,多则几周韶光。

下面是一个经由了数天定位到的一个问题,双口RAM两侧同时向同一个地址写入数据导致出错的Vivado调试波形截图。
(ZL)

案例1(TK)

1、问题征象:

以行列步队信息中的行列步队等分组个数的值为例,由于更新缺点导致当行列步队中实际为空(即分组个数为0),而行列步队信息显示行列步队分组个数不为0,导致输出错误数据帧。

2、问题剖析

起初是固定的单次发帧,由于没有出入队的连续更新的情形未涌现问题。
后来在连续发随机帧的时候涌现问题。
排查到后来看到创造行列步队帧数计数有问题。

行列步队信息,如帧数目记录在双口RAM中,每次出队和入队都要更新这个值。
此处考虑以下两个问题 :

(1) 会不会同时进入 updating,即两口不能同时对同一地址进行写操作。

(2) 会不会接续写 :由于更新因此当前值为根本,入队时分组数更新数值为 当前值+1,出队时-1,一个端口写入后下一个时钟才能读出,故不能两口在连续的两个时钟进行更新。

3、办理方法

RAM包括如下三种操作模式:

no-change :写过程中 输出不变read:写入的先放入存储器内,输出数据线上数据不变。
(上个周期写入的,这个周期先读出之前的值)write:写入的,立马放在输出的数据线上

我们可以知道,在写优先的情形下,可以最快得到更新值。
因此,双端口RAM的行列步队信息更新要担保至少要间隔一个钟(且为写优先的情形)。

以下是在三种操作模式下的双端口RAM更新举例,以分组个数为例,出队更新值为输出值-1,入队更新值为输出值+1。

终极办理创造例化IP核时,没有设置成写优先,其默认为no-change,其余在设计过程中,由于流水线设计对时钟数哀求没那么严格的情形下,对付RAM的输出值可以延迟一拍输出,得到更稳当的输出值。

案例2(ZHF)问题:

行列步队长度信息RAM a b口读写非常,更新出错。

征象:

端口卡去世,某行列步队长度达到最大门限,但是发送调度显示行列步队为空,新数据帧入队申请,不知足门限哀求而丢弃,输出没有调度结果,也不能出队操作;

图5.9 双口RAM a b口读写非常

剖析定位:

根据征象中停滞发送,对行列步队长度信息更新干系旗子暗记进行Debug测试,定位出问题的根源位置如图5.9所示,该队里进行入队操作后,行列步队长度信息被入队调度通过行列步队信息RAM a口更新写入长度13,此时出队操作正在实行,在获取行列步队长度信时,在a口刚写入后的一个clk,读取得到行列步队长度信息为12,再经由1个clk,数据稳定在13;但是非常数据12被出队操作获取到并用于出队号行列步队长度的更新,行列步队长度更新出错,多少次操作后,当末了一帧出队完成后,会将行列步队长度更新为负数,如图5.10所示,FPGA中不操作负数,即二进制中很大的正数,远大于行列步队最大门限,后面再进行入队操作时,入队操作不知足门限哀求,无法入队操作,同时出队操作认为行列步队为空,不会调度该行列步队出队操作,进入卡去世状态;行列步队长度13的二进制表示为1101’b,12的二进制表示为1100’b,解释涌现了单bit翻转缺点的问题。

图5.10 行列步队长度信息更新涌现负数

办理方法:

首先考虑对RAM输出加寄存操作,但是这样会整体引入操作时延,纵然入队和出队操作不是同一行列步队,每次在RAM读数据情形下都须要多等一个clk,为理解决该问题,采取的方法是在出队操作须要读行列步队长度时,如果前一个时候a口刚更新该行列步队,此时a口晚一个clk再用数据,担保第二个clk读出的数据是a口写入稳定输出的,其他情形下不引入时延。

交流机中地址学习表老化韶光更新地址冲突预防(LCR)

更新模块:用于根据同步更新表项内容同时更新多路并行的内外层MAC地址查找模块与内外层MAC地址学习模块的地址表。
当同步更新表缓存器不为空时,读取同步更新表缓存器中的同步更新表项,从中获取要更新的表项地址和地址表,并同时查询多路并行的内外层MAC地址查找模块与内外层MAC地址学习模块正在读取的表项地址,判断这两个地址分别与要更新的表项地址是否为同一地址:如果不是同一地址,即没有发生读写冲突,则将地址表同时传入多路并行的内外层MAC地址查找模块与MAC地址学习模块,如果发生读写冲突,更新模块等待冲突结束后更新地址表。

冲突检测模块设计(FXY)

冲突检测模块的紧张浸染是防止地址表发生读写冲突。
所谓的读写冲突是指对双口RAM内某一地址同时进行读写操作,涌现此种情形会导致RAM内该冲突地址处的数据涌现不可预见的变革。
虽然现阶段FPGA内天生双口RAM时会选择读优先还是写优先来规避此类问题,但是结合实验室的多次上板测试履历来看,并不能彻底办理读写冲突导致数据非常的问题。
因此为了实现在CPU配置地址表的同时仍能进行查表自学习操作,本设计中增加了一个冲突检测模块,通过该模块判断读写操作是否在同一地址上,从而彻底避免因读写冲突导致数据非常的征象。

传统的冲突检测中采取的方法是:先读取一项配置信息,然后检测是否冲突,如果没有冲突再进行更新,接着读取下一项配置信息。
此种方法至少须要3个时钟才能更新一份表项信息,速率相对较慢,但是状态跳转很大略。
为了适应往后更高的数据速率,本设计中采取了一种基于预读取办法的冲突检测的方法,实现高速的读写冲突检测。
详细的方法是:先读取一项配置信息,然后对该配置信息进行冲突检测,在检测的同时预读取一项新的配置信息,当完成前配置信息的检测更新后,直接对新的配置信息进行检测并更新。
采取此种方法的优点是,当没有发生读写冲突时可以达到一个时钟周期更新一个地址表项,理论上能够达到了地址表最大更新速率。
冲突检测模块的状态转移图如下图所示。

IDLE:空闲状态,等待CPU发送过来的配置信息,当检测到FIFO为非空时,跳到REN状态,否则保持原状态。

REN:读使能状态,该状态用来拉高FIFO的读使能,然后跳转到CHECK状态;

CHECK:冲突检测状态,在该状态中紧张有以下操作。

如果FIFO为非空则在该状态中连续拉高FIFO的读使能。
当FIFO为空且没有发生读写冲突,下一状态跳转到DLE状态。
如果要更新的表项地址与查找模块和学习模块供应的读地址相同,代表发生了读写冲突,将上一状态拉高读使能得到的配置信息放置到寄存器中,不进行任何更新操作,然后跳转到COLLISION1状态,如果此时FIFO为空,则跳转到COLLISION2状态。
如果要更新的表项地址与查找模块和学习模块供应的读地址不同,则表示没有发生读写冲突,根据配置信息更新地址表对应的表项信息,并保持原状态。

COLLISION1:冲突1状态,指的是上一CHECK状态检测到冲突,但是FIFO为非空状态,在此状态中拉低FIFO读使能,由上两节关于查找模块和学习模块的先容可知:如果在上一时钟对RAM进行了读操作,则不才一周期绝不会再进行读操作。
因此在此状态下,可以将上一状态中寄存的配置信息更新到地址表相应的位置,然后跳转到CHECK状态。

COLLISION2:冲突2状态,指的是上一CHECK状态检测到冲突,但是FIFO为空,与COLLISION1状态类似,在此状态中拉低FIFO读使能,然后用寄存器中的配置信息更新地址表相应位置内的信息,然后跳转到IDLE状态。

对付状态CHECK和COLLISION1的补充:由于FIFO的输出具有保持的功能,也便是从FIFO读取一组数据,如果不再拉高读使能,则这组数据会一贯在FIFO读数据端口保留。
当在CHECK状态拉高了FIFO读使能,当检测到读写冲突并跳转到COLLISION1状态后,由于在COLLISION1状态并没有连续拉高FIFO的读使能,因此由CHECK状态拉高读使能而读出的一组新的数据会一贯保持在FIFO的读数据端口上,由COLLISION1状态再回到CHECK状态后,可以直接提取FIFO读数据端口的数据进行冲突检测并更新。

从上面的状态转移描述可以看出,当FIFO内存有足够多配置信息的时候,如果冲突检测模块一贯没有检测到读写冲突,则该模块会一贯保持在CHECK状态,并且每一时钟从FIFO读取一帧配置信息,并将配置信息更新到地址表中,实现一个时钟更新一条表项信息的最大速率。

深夜调试FPGA场景

调试FPGA不易,且行且珍惜!

全文完。

标签:

相关文章