作者:Prathamesh Suryavanshi,AMD工程师;文章来源:AMD开发者社区
简介:块 RAM 中的地址冲突场景
块 RAM 是基于 FPGA 的系统设计中的关键组件,通常用于其高速数据存储功能。然而,地址冲突可能会带来重大挑战,影响系统的可靠性和性能。在本博客中,我们将探讨简单双端口 RAM 模块中地址冲突的概念,并深入研究各种写模式及其对地址冲突的影响。通过实际示例,我们将演示发生这些冲突的场景,并提供仿真截图来说明这些问题的实际表现。虽然本博客主要介绍简单双端口 RAM,但如果设计师想要了解有关真双端口 RAM 的更多信息,可参阅 UG1485/AM007。
地址冲突:
块 RAM 中的地址冲突是指针对同一个物理存储器地址同时执行多项读操作或写操作的场景。这可能导致冲突和不可预测的行为,未能妥善管理或控制这些操作的情况下尤其如此。地址冲突是使用块 RAM 来设计和实现数字系统(如,现场可编程门阵列 (FPGA))的过程中的重要考虑因素。
写模式:
针对每个端口,均有三种可配置的写模式可供单独选择,其中任一模式即可决定写操作后输出锁存器的行为。默认模式为 `WRITE_FIRST`,输出会立即显示正在写入的新数据。或者可选 `READ_FIRST` 模式,该模式在内部对存储器阵列写入新数据的同时,会将先前存储的数据保留在输出上。最后是 `NO_CHANGE`,该模式确保写操作完全不影响输出,输出仅在执行读操作后才会改变。
三种写模式:
写操作后输出锁存器上数据的行为由以下三种设置决定:WRITE_FIRST、READ_FIRST 和 NO_CHANGE。针对每个块 RAM 端口,均可独立设置该属性,使您能够对存储器的行为进行精细控制。
1. WRITE_FIRST 模式:
行为:在 WRITE_FIRST 模式下,写操作优先用于输出。块 RAM 会将新写入的数据输出到输出总线上。可以将其理解为一种“直写”或“数据转发”机制 - 当前写入的数据直接通过存储器逻辑传递到输出锁存器。
使用场景:WRITE_FIRST 是默认且通常最直观的模式。它非常适合简单的寄存器文件或缓冲器,在这些场景中您希望随时获取最新信息并立即可用。如果写入一个值,那么在此模式下,您可在下一个周期立即使用它,而没有任何时延

2. READ_FIRST 模式:
行为:在 READ_FIRST 模式下,优先执行读操作。块 RAM 会输出先前存储的数据 - 即,发生写操作之前该存储位置中的数据。写操作仍成功并在内部更新存储单元,但输出反映的是该时钟周期“之前”的状态。
使用场景:READ_FIRST 是需要以流水打拍方式执行的“读-改-写”操作的主力模式。以如下累加器为例:memory[i] = memory[i] + 1。您需要读取 memory[i] 的旧值,将其发送到加法器,然后将结果写回。READ_FIRST 允许写入由前一项操作计算所得的新值的操作与读取旧值的操作发生在同一个周期内。它对于构建高效的流水线、FIFO 和数据路径处理元素至关重要。

3. NO_CHANGE 模式:
行为:此模式最为独特。在写/读操作冲突期间,块 RAM 输出不会改变。它只是保持上一项成功的读操作的输出值不变。对存储单元的内部写操作仍然正确执行,但输出端口在该周期内实际上被“冻结”。
使用场景:NO_CHANGE 的主要优势是降低功耗。通过防止输出总线翻转,可以降低块 RAM 及其连接的下游逻辑的动态功耗。在写周期中,如果从块 RAM 读取数据的逻辑不需要有效数据,那么该模式是极佳的选择。如果控制逻辑可以在发生写操作的周期中简单忽略块 RAM 输出,则使用 NO_CHANGE 可以实现更节能的设计。

下表展示了各种写模式下的地址冲突场景:


以下是 SDPRAM 中地址冲突的一些实际示例:
1. 共用时钟 WF 模式:

2. 共用时钟 RF 模式:

3. 共用时钟 NC 模式:

4. 独立时钟 WF 模式:

5. 独立时钟 RF 模式:

6. 独立时钟 NC 模式:

同样,设计师也可以对 TDPRAM 进行仿真。
如何避免地址冲突:
块 RAM 系统中的 No-change 模式在双端口 RAM 设置中尤为常见,它提供了一种方法,用于在同一存储器地址上同时进行读写操作时管理潜在数据冲突。在这种设置中,可能会在同一地址上并发执行读写操作,如果处理不当,可能导致数据损坏。No-change 模式通过如下方式来解决此问题:它确保在这些并发操作期间,读操作会检索该位置上最后一个稳定的数据值,而不是反映同时执行写操作所引入的当前状态或瞬态状态。此模式对于维护数据完整性和一致性至关重要,可在冲突期间提供可预测的响应。No-change 模式的实现可能因具体的存储器技术和 FPGA 或类似架构中 RAM 的设计而异,通常是通过设计工具或特定硬件设置来配置的。通过使用 no-change 模式,设计师可以降低与额外仲裁或优先级逻辑相关的复杂性,在不牺牲数据可靠性的前提下简化系统设计。此外,它提供了一种简单有效的方法来确保数据读操作稳定可靠,在存储块经历同时执行读写访问的繁重数据处理任务期间,最大限度减少错误发生的可能性。