这一篇在干嘛?

这篇笔记带你把安路官方的 Soft FIFO IP 用户手册(IPUG012,IP 版本 3.0)从头到尾吃透。先搞懂 FIFO 是个啥、什么时候需要它,再看这个 IP 支持哪些配置、每个信号是干嘛的,最后学会看时序图、在 TD 软件里把它生成出来并正确例化。

FIFO 是什么?什么时候需要它?

FIFO 的全称是 First Input First Output,先入先出队列。你可以把它想象成一根水管:数据从写口(写侧)一端流进去,从读口(读侧)一端流出来,先进去的先出来,顺序不会乱。

在系统设计里,FIFO 主要用来处理大量数据流、匹配传输速率不同的系统,从而提高整体性能。具体来说,最常见的三类场景是:

  1. 速率缓冲:写数据的一方快、读数据的一方慢(或反过来),FIFO 在中间当蓄水池,两边各按自己的节奏存取,只要平均速率守得住、池子不溢出就行。
  2. 跨时钟域:写侧和读侧用的是两个不同的时钟。直接把数据从 A 时钟域搬到 B 时钟域很容易出错,异步 FIFO 的内部逻辑(比如格雷码地址同步)会替你处理这种危险。
  3. 数据位宽变换:写进去是窄数据(比如 2 bit),读出来是宽数据(比如 8 bit),Soft FIFO 支持读写位宽不对称,自动帮你拼/拆数据。

怎么选 RAM 类型?

Soft FIFO 底层存储可以选 ERAM 或 DRAM:ERAM 是器件里的块存储资源,速度快、占用少(8 bit × 1024 深度时只占 1 个 ERAM);DRAM 用 mslice 逻辑搭出来,不吃 ERAM 但费逻辑资源,时序性能也比 ERAM 差。手册给出的实测数据:PH1A180 器件、异步时钟、读写宽度 8、深度 1024、未使能 show ahead 时,ERAM 方案占 LUT 101 / Register 184 / SLICE 139 / ERAM 1,而 DRAM 方案占 LUT 272 / Register 221 / SLICE 332 / ERAM 0。

Soft FIFO IP 有哪些特性?

按手册的描述,Soft FIFO 是一个经过验证、功能完整的软 FIFO,主要特性如下:

  • 支持同步时钟和异步时钟模式,可配置;
  • 支持不对称读写位宽,读写侧位宽比最高 16:1 或 1:16;
  • 数据位宽受器件 RAM 资源限制,最大读写位宽 1024
  • 支持 ERAM 和 DRAM 可选,ERAM 的类型和综合策略也可选;
  • 支持 full_flag、empty_flag 标志位输出,以及可配置的 afull(将满)、aempty(将空) 标志位输出;
  • 支持输出寄存器模式可配置;
  • 支持 show ahead 模式可配置(第一个数据提前出现在输出口);
  • 支持 wrusedw(已写入数据量)和 rdusedw(可读数据量) 输出;
  • 支持读写握手信号

位宽比例的限制

不对称读写位宽只支持 2 的 n 次方比 1,即 16:1、8:1、4:1、2:1、1:1、1:2、1:4、1:8、1:16 这些比例。像 5:1 这种”歪”的比例是不支持的。真有别的比例需求,手册建议改用 UniversalGearbox IP。

时序性能方面,手册在 TD 6.2、PH1A400 器件下给了一组参考值(读 8 bit、深度 1024 这类典型配置):ERAM 方案的写侧时钟最高能跑到 572.7 MHz、读侧 568.8 MHz;DRAM 方案就低一些,比如 528.8 MHz / 489.9 MHz;使能 show ahead 后 ERAM 方案降到 436.7 MHz / 386.7 MHz。这些数字仅供参考,实际要看你自己的工程约束。不对称位宽(读 8 bit、写 16 bit)时也有 500+ MHz 的水平。

参数配置:每个参数都在调什么?

Soft FIFO 的所有配置都能通过 TD 的 GUI 界面完成,界面上主要选项如下:

参数名选择默认值描述
Ram OptionERAM / DRAM / ERAM_144KERAM选择 RAM 类型
CLKMODASYNC / SYNCASYNC同步 FIFO 或异步 FIFO
Data Port OptionWrite Width8FIFO 写位宽
Data Port OptionWrite Depth8FIFO 写深度
Data Port OptionRead Width256FIFO 读位宽
Data Port OptionRead Depth256FIFO 读深度
Show Ahead OptionEnable / DisableDisable提前输出使能控制
Out RegEnable / DisableDisable输出寄存器使能控制
Almost numAlmost full num8afull 的边界值
Almost numAlmost empty num7aempty 的边界值
Reset OptionReset TypeASYNC Reset选择复位方式
Reset OptionDout Reset Value(hxe)0数据输出复位值

对应到 IP 内部的 PARAMETER 定义(写 Verilog 例化时会遇到):

信号默认值描述
COMMON_CLK_EN00:异步时钟;1:同步时钟
MEMORY_TYPE00:ERAM(area);1:ERAM(fast timing);2:ERAM(9K, area);3:ERAM(32K, area);4:ERAM(9K, timing);5:DRAM;6:ERAM 144K(仅 PH2A 器件有效)
RST_TYPE00:无复位;1:异步复位;2:同步复位
DATA_WIDTH_W / ADDR_WIDTH_W8 / 10写位宽 / 写深度
DATA_WIDTH_R / ADDR_WIDTH_R8 / 10读位宽 / 读深度
DOUT_INITVAL8’d0复位值
OUTREG_EN”NOREG""NOREG”:未使能输出寄存器;“OUT_REG”:使能输出寄存器
SHOW_AHEAD_EN00:未使能;1:使能 SHOW AHEAD 模式
AL_FULL_NUM / AL_EMPTY_NUM10 / 10将满水线 / 将空水线
RDUSEDW_WIDTH / WRUSEDW_WIDTH10 / 10读侧可读数据计数位宽 / 写侧已写入数据计数位宽
ASYNC_RST_SYNC_RELS01:使能异步复位同步释放模式(复位在异步模式下使能)
SYNC_STAGE2异步模式下跨时钟域打排寄存器级数,可选 2~8

其中 Implement Option(ERAM 的具体实现方式)因器件而异:EF2、EG4 器件有 EMB9K(Area Opt) / EMB9K(Timing Opt) / EMB32K / AUTO 可选,EF3、SF1 只有 9K 的 Area/Timing 两种,PH1A/DR1/PH1P/PH2A/SF2 则是 EMB20K 的 Area/Timing 两种。9K 或 20K 的 Timing Opt 比 Area Opt 时序性能更好;auto 模式下 TD 会优先用 9K 来完成 Soft FIFO。

另外注意:9K 和 32K 的 ERAM 仅支持小器件;ERAM 144K 只在 PH2A 器件上有效。

信号端口:写口、读口和一堆标志位

Soft FIFO 的端口可以按”写侧 / 读侧 / 状态指示”三堆来看:

复位和时钟(输入)

端口方向描述
wrst / rrstinput复位信号,高电平有效,内部采用异步复位
srstinput复位信号,高电平有效,内部采用同步复位
rstinput复位信号,高电平有效,内部采用异步复位同步释放
clkinput同步时钟下的时钟输入,上升沿触发
clkw / clkrinput异步时钟下的写侧 / 读侧输入时钟,上升沿触发

写口与读口

端口方向描述
weinput写使能,高电平有效
di[W1-1:0]input数据输入信号
reinput读使能,高电平有效
dout[W2-1:0]output数据输出端口
validoutput数据有效指示,高电平有效

状态指示(输出)

端口方向描述
full_flagoutput满指示信号,高电平有效
empty_fulloutput空指示信号,高电平有效
afulloutputalmost full 指示,高电平有效
aemptyoutputalmost empty 指示,高电平有效
wrusedw[D1-1:0]output同步至写时钟域的已写入数据量
rdusedw[D2-1:0]output同步至读时钟域的可读数据量
overflowoutput指示数据写溢出
underflowoutput指示数据读溢出
wr_successoutput指示数据写入成功

满了还写、空了还读会怎样?

  • 满写:full_flag 拉高后再写,数据不会进去,overflow 拉高、wr_success 拉低,这一笔直接被丢掉。
  • 空读:empty_flag 拉高后再读,underflow 拉高、valid 拉低,dout 上的数据是无效的。
  • usedw 是”保守值”:wrusedw 和 rdusedw 报出的值永远少于 FIFO 中实际可读的数据量,就是为了保守起见保证 FIFO 永远不会溢出。另外写侧报的已写入数据量按写位宽 W1 计算,读侧报的可读数据量按读位宽 W2 计算,两侧位宽不同时数字含义不一样。

正确的读写姿势

写侧:先看 full_flag / afull,不满再拉 we 送数据。读侧:先看 empty_flag / aempty,不空再拉 re 取数;数据是否真的有效要看 valid——empty_flag 为 0 时,re 拉高后下一周期 valid 拉高,表示 dout 有效。

复位操作:别把复位搞砸了

Soft FIFO 支持多种复位模式,不同时钟模式下可用的选择是:

  • 同步时钟:同步复位、异步复位同步释放、无复位;
  • 异步时钟:异步复位、异步复位同步释放、无复位。

几条关键行为规则:

  1. 无复位模式在工作过程中无法对 FIFO 进行复位,选了就再也”喊不醒”它,要谨慎。
  2. 异步复位同步释放模式:复位信号无效后,要过四个时钟周期才真正释放。
  3. 异步复位模式下读写时钟域各自单独复位,读写操作必须等读写侧复位都释放后才能进行
  4. 同步复位模式下,复位信号必须持续至少一个时钟周期(异步复位模式下按读写侧最小时钟算)。
  5. 复位只对内部地址、信号标志、dout 输出生效,不会清空内部存储单元

复位释放前别动手

最容易踩的坑是复位还没释放完就开始读写。尤其异步模式下读写两侧释放时间可能不同步,务必等两侧都完成复位,否则标志位和地址指针状态不可信。

读写时序图:一张张看懂

满了会怎样:写溢出时序

异步和同步模式下的写溢出时序如下图(图 3-1 为异步 FIFO、图 3-2 为同步 FIFO):

异步 FIFO 写满后的溢出时序:wr_success 拉低、overflow 拉高,数据 33 被拒收

同步 FIFO 写满后的溢出时序,行为与异步类似但 wrusedw 值不同

看图要点:full_flag 拉高后一个周期,wr_success 拉低、overflow 拉高,图中数据 33 没能写进 FIFO。另外异步 FIFO 和同步 FIFO 的实际数据深度不同,所以同样写满后 wrusedw 的值不一样。

读操作与下溢

FIFO 读操作时序:re 拉高后下一周期 valid 拉高,空读则 underflow 拉高

读侧逻辑:empty_flag 为 0 时拉高 re,下一周期 valid 拉高,dout 上的数据有效;等 empty 拉高后 rdusedw 变 0,再读一个周期 underflow 拉高指示下溢,valid 拉低表示数据无效。

afull 和 aempty:提前预警线

afull 指示的是 FIFO 内部剩余有效数据量与 AL_FULL_NUM 的关系:剩余量大于 AL_FULL_NUM 时拉高,反之拉低。异步时钟、AL_FULL_NUM 配置为 10 时的波形:

异步时钟下 afull 信号时序:wrusedw 到 10 拉高,低于 10 拉低

aempty 则要求在界面上设置 Almost empty num。下图配置为 4:写入 4 个读侧数据后 re 信号有效,rdusedw 大于 4 时 aempty 拉低、小于 4 时拉高。

aempty 端口时序:以 Almost empty num=4 为界翻转

afull / aempty 的边界可能和直觉相反

当 Almost full num 大于 Almost empty num 时,afull 和 aempty 与通常理解的 almost full / almost empty 一致;但当 Almost full num 等于或小于 Almost empty num 时,aempty 信号翻转的时间点会先于 afull,和直觉不一样,配置水线时要注意。

输出寄存器模式与 Show Ahead 模式

使能输出寄存器(Out Reg)后,dout 比 normal 模式延迟一个时钟输出,代价是时序性能更好:

输出寄存器模式时序:dout 比 normal 模式晚一拍输出

Show Ahead 模式则相反,dout 比 normal 模式提前一个时钟出现:

Show Ahead 模式时序:第一个数据 D1 自动出现在输出端口

结合上图:写入数据 “D1”、“D2”、“D3” 后,empty_flag 拉低、valid 拉高,第一个数据 “D1” 已经自动出现在输出端口,re 拉高后可直接取走端口数据,比 normal 模式省一拍。使能 Show Ahead 时,输出寄存器不会影响数据提前输出——这一点与旧版本的 Show Ahead 功能不同。

读写位宽不对称:数据怎么拼、怎么拆?

读:写 = 4:1(窄进宽出)

当读位宽 8 bit、写位宽 2 bit(比例 4:1)时,写入 4 个 2 bit 数据后才拼出一个 8 bit 读出。写入顺序 2’b00 → 2’b01 → 2’b10 → 2’b11,先写入的 2’b00 放在低位,最后写入的 2’b11 放在高位

数据关系示意图:读位宽比写位宽等于 4:1 时的拼接顺序

对应的读写数量规则要记牢:

  • 写入数据不足 8 bit 时,读不出数据(empty 信号 = 1);
  • 若写入个数 wr_num 不是 4 的整数倍,读空后 FIFO 内部还剩 wr_num%4 个 2 bit 数据”滞留”。

它对应的时序图如下:

数据关系时序图:读位宽比写位宽等于 4:1 时的读写波形

读:写 = 1:4(宽进窄出)

反过来,读位宽 2 bit、写位宽 8 bit(比例 1:4)时,写入一个 8’b11100111,读出顺序是 2’b11 → 2’b01 → 2’b10 → 2’b11:

数据关系示意图:读位宽比写位宽等于 1:4 时的拆分顺序

对应时序图:

数据关系时序图:读位宽比写位宽等于 1:4 时的读写波形

位宽变换时的深度也别忘了换算

位宽不对称时,写侧深度和读侧深度不是一回事:读 8 bit、写 16 bit 的配置里,读深度 1024 对应写深度 512。配参数时按两侧位宽分别算清楚,免得实际容量比预期小一半。

实际深度:界面配置 ≠ 实际容量

Soft FIFO 的实际深度和界面选择的配置不一定一致,对应关系如下:

界面选择配置实际深度
同步时钟,未使能 show aheadwrite/read depth
同步时钟,使能 show aheadwrite/read depth + 1
异步时钟,未使能 show ahead(写侧)write depth − 1
异步时钟,未使能 show ahead(读侧)read depth − (read depth / write depth)
异步时钟,使能 show aheadwrite/read depth + 1

也就是说异步 FIFO 会”吃掉”一点深度用于内部地址同步管理(这与前文写溢出时序中”异步与同步 FIFO 实际数据深度不同”的说明是呼应的),设计余量时按实际深度来算。

在 TD 里生成并例化 Soft FIFO

打开配置界面

在 TD(手册以 6.2 版本为例)里依次点击 Tools → IP Generator → Primitive IP → Memory → Soft_FIFO,双击进入配置界面。Component Name 在进入配置界面后依旧可以修改。

配置界面有 BasicLocal Ports 两个 Tab。

Basic Tab 包含 Ram Option、Implement Option、Clock Mode、Interface Type 四个选项:

TD 中 Soft FIFO IP 的 Basic 配置界面

  • Ram Option:三个可选项(ERAM / DRAM / ERAM_144K);
  • Implement Option:六个选项,具体可选项由器件拥有的资源决定(比如 EF2 器件有 9K 和 32K 资源,就有 4 个可选项);
  • CLKMODE:同步时钟(SYNC)或异步时钟(ASYNC)二选一;
  • Addr Domain Across Control:异步时钟模式下,读写地址格雷码跨时钟同步的拍数。

Local Ports Tab 包含五组配置:

TD 中 Soft FIFO IP 的 Local Ports 配置界面

  • Data Port Option:设置位宽和深度,超出器件资源限制会报错;
  • Show Ahead Option:使能后第一个数据提前输出;Show Ahead 模式支持 ERAM、DRAM、同步时钟、异步时钟;
  • Out Reg:数据输出加一级寄存器,可提升时序性能;同样支持 ERAM、DRAM、同步/异步时钟;
  • Almost num(Almost full num 和 Almost empty num):配置 afull 和 aempty 信号的 assert / deassert 门限,可配置范围与读写深度相关;
  • Reset Option:选择复位模式及 RAM 的输出复位值。

配置完成后的输出文件

参数配好、无报错后点击 OK,会生成以下文件:

文件备注
.vIP 工具生成的 wrapper.v 文件
.xmlIP Gen 界面配置参数记录文件
.vSoft FIFO IP 核
.tclIP 时序约束文件

时序约束:基本不用你操心

异步 Soft FIFO 模式下,IPGEN 会在 IP 同级目录下生成 .tcl 时序约束文件。当前版本的 Soft FIFO IP 会自动获取用户顶层的时序约束,例化之后无需手动修改;自带约束文件由 IPC 文件调用,不必单独加入工程,且约束路径不可更改。

绝对不要自己加跨时钟域豁免

在用户 SDC 文件里,不可直接对 Soft FIFO IP 的读写时钟使用 set_clock_groups 或 set_fault_path 命令,更不能用 set_cross_domain_timing self/domain 之类命令让工具不分析这两个异步时钟域——否则 IP 内部格雷码跨时钟域的 set_max_delay 约束会失效,FIFO 逻辑存在时序风险。如果工程里除了 Soft FIFO 还有别的逻辑跨这两个时钟域,正确做法是在用户 SDC 里加 set_max_delay -from [get_clocks A] -to [get_clocks B] -datapath_only 100 来放松时序(A/B 是驱动 FIFO 的读写时钟名称)。

收尾清单

  • Soft FIFO 支持全系列安路 FPGA 器件(除 ELF、AL3 外);
  • IP 会限制单个 FIFO 的位宽和深度,多次例化时注意器件资源会不会超(大工程配小器件尤其小心);
  • 配深度时按上表换算实际深度,别按界面数值估算容量。