FPGA和ASIC的RAM工作模式——WRITE_FIRST / READ_FIRST / NO_CHANGE详解

1、前言

Vivado在生成memory的时候,有个Operating Mode选项。

本篇将专门分析这些工作模式的含义。

2、具体含义

官方解释如下:

“WRITE_FIRST” 模式,写操作时,输出端口会将当前写的数据输出。(ASIC中又称“write through”,或AWT,Async)
“READ_FIRST” 模式,写操作时,输出端口会将当前写地址的原数据输出。
“NO_CHANGE”模式,写操作时,输出端口会保持原值不变。只有在读操作的过程中输出端口才会变化。

 

不好理解没关系,下面列出图示和时序波形:

  • “WRITE_FIRST” 模式(ASIC中又称“write through”)
  • 写入的数据一边写到RAM内核,一边输出到端口。

 

  • “READ_FIRST” 模式
  • 写入的数据写到RAM内核,写地址指向的RAM数据输出到端口。

 

  • “NO_CHANGE” 模式
  • 写入的数据写到RAM内核。输出端口的数据(实际上有个寄存器)保持不变。

 

下面列出对应的代码,有人习惯从RTL代码上理解。此代码是可以被Vivado工具直接识别的。

  • “WRITE_FIRST”代码,可综合
//write port
always @(posedge clk) begin
    if(en && we)
        RAM[addr] <= di;
end

//read port
always @(posedge clk) begin
    if(en)
        if(we)
            dout <= di;
        else
            dout <= RAM[addr];
end

 

  • “READ_FIRST”代码,可综合
//write port
always @(posedge clk) begin
    if(en && we)
        RAM[addr] <= di;
end

//read port
always @(posedge clk) begin
    if(en)
        dout <= RAM[addr];
end

 

  • “NO_CHANGE”代码,可综合
//write port
always @(posedge clk) begin
    if(en && we)
        RAM[addr] <= di;
end

//read port
always @(posedge clk) begin
    if(en && !we)
        dout <= RAM[addr];
end

其实,RTL还是更好理解一些的。

注意,http://www.elecfans.com/d/887964.html这篇文章的RTL部分“READ_FIRST” 代码和“NO_CHANGE”代码写的有问题。

3、应用和背景

在IC设计领域,FPGA主要用来做AISC的原型验证,即在FPGA上要实现一个与ASIC完全一致的设计,以此加速仿真,方便快速找到AISC设计的问题。

分享两个故事:

一个故事发生在前东家,有次生成FPGA的ram时,错把Operation Mode选成了“READ_FIRST” ,而恰好暴露出来一个之前没验证到的bug。为什么会这样呢?

Bug是这样的,这位designer把当前cycle写入ram的值,下一cycle直接在读接口上采样并使用了,这实际是利用了“WRITE_FIRST”(ASIC中叫“write through”)的特性。

在设计中,这样的操作是不允许的,虽然这样可以省掉一个read cycle,但这种设计的通用性很差,一旦更换ram,就会出问题。当时的项目就是迁移到新工艺节点,ram由原来的“write through”(对应FPGA的“WRITE_FIRST”)更新到了“no write through”(对应FPGA的“NO_CHANGE”),这样此designer的设计出问题了。

为什么ASIC仿真没有发现这个问题呢?

IC公司在ASIC仿真时为了加速,一般都是用自己写的ram sim model来做仿真模型的。工艺节点升级了,ram行为也由write through变成了no write through模式,而ram sim model却没有更新。因此,ASIC仿真并没有暴露出来这个问题。

幸亏这个bug在RTL freeze前暴露出来了,若是没有检查出来而流片了,那后果不堪设想。

另一个故事发生在现公司,遇到的问题也是类似原因。

Bug是这样的,一位designer设计时没有考虑好读写端口的配合,导致某种场景下会出现读的数据没来及取走,就已经向这个地址覆盖了新的数据的情况,且这种情况只会冲刷一个cycle

若ram是write through模式,则会丢失一个数据;若是no write through模式,则恰好利用了读端口的保持特性规避了丢数据的问题。

本质上讲,这样的设计也是错误的,肯定要改设计,只不过项目已经进展到RTL freeze阶段,只能靠这种方式来规避了。

4、总结

上述提到的两处bug,都是因为设计者(包括写ram model的验证者)不了解ram的特性导致的。

  • 建议要用脚本语言来生成FPGA、ASIC的ram,用GUI生成则很容易出错,且不好检查。
  • 建议要用FPGA、ASIC的ram工具生成的ram model来做仿真,不要手写ram model。
  • 设计者要用标准的读写时序进行设计,必须避免“利用端口特性的不规则设计”,
  • 28
    点赞
  • 129
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值