这一篇在干嘛?
UG910 精读第二篇,覆盖三大家族:IO 族(DDR 转换、串并转换、动态延迟、三态缓冲)、存储族(分布式 RAM、ERAM20K 块存储、软核 FIFO)和器件管理族(电压温度监测、配置存储纠错、芯片 DNA、多启动)。时钟与运算原语见 原语库 PH1A(1),目录页在 原语库 PH1A。
动态延迟与三态缓冲:IDELAY、IOTRIBUF、IOBUF
IO 双沿转换:IDDR 与 ODDR
DDR 接口(如摄像头 D-PHY、DDR 存储器)在时钟上升沿和下降沿都传数据,而 FPGA 内部逻辑只在单沿工作,中间必须有个转换器——这就是 IDDR(输入)和 ODDR(输出)。
PH1_LOGIC_IDDR 是 IO 上将双沿采样数据变为单沿数据的单元:带数据对齐的双速率 D 触发器、异步复位,把输入的 DDR 数据转为 q0(上升沿数据)、q1(下降沿数据)两位同步到内部时钟网络。

PH1_LOGIC_IDDR #(
.ASYNCRST ("ENABLE"),
.PIPEMODE ("PIPED")
) u_IDDR (
.clk (clk),
.d (d),
.rst (rst),
.q0 (q0),
.q1 (q1)
);参数两个:ASYNCRST(异步复位使能,默认 “ENABLE”)、PIPEMODE(q0/q1 数据对齐模式,“PIPED”/“NONE”,默认 “PIPED”)。
PH1_LOGIC_ODDR 是反过程:内部单沿数据变换为双沿数据输出,支持同步/异步复位,把 d0(上升沿)、d1(下降沿)两路数据双倍率输出到 IO 口。参数只有 ASYNCRST。

常见坑:不例化 ODDR 直接把两位数据"或"到一个 IO 上
IO 物理单元里的输出双沿触发器是唯一能在同一个 IO 上实现 DDR 输出的硬件。绕开 ODDR 用组合逻辑拼,时序上根本对不齐双沿,综合器也无法映射到 IO DDR 资源。
高速串并转换:x2 家族与 HP SERDES
当接口速率更高时,1:2 的 IDDR/ODDR 不够用,需要 1:4 甚至 1:10 的串并转换。
IDDRx2 / IDDRx21(1:4 串转并)
PH1_LOGIC_IDDRx2 是 IO 上的 1:4 串转并单元,功能与 IDDR 相同但支持更高的 IO 速度,需要两个时钟:sclk(1/2 数据率)和 pclk(1/2 sclk)。

PH1_LOGIC_IDDRx21 是它的省时钟版本:直接使用内部 sclk 的 2 分频作为 pclk,节省 1 个 clk 资源,代价是数据输出比 IDDRx2 模式晚一个 sclk 时钟周期。端口上它没有 pclk,只有 sclk。
ODDRx2 / ODDRx21(4:1 并转串)
镜像关系:PH1_LOGIC_ODDRx2 是 IO 内部的 4:1 并转串单元(pclk + sclk);PH1_LOGIC_ODDRx21 同样省掉 pclk 端口、用 sclk 2 分频,输出同样晚一拍。

四个原语的参数都只有 ASYNCRST(“ENABLE”/“DISABLE”,默认 “ENABLE”),复位高有效。
HP_OSERDES / HP_ISERDES(1:10)
HP IO 区域的高速版本,位宽直接到 10:
- PH1_LOGIC_HP_OSERDES:10 位并行 idata[9:0] 转 1 位串行 odata,参数
ODDRMODE可选 “DDRX1”/“DDRX2”/“DDRX3P5”/“DDRX4”/“DDRX5”(3.5 倍率都支持),模式不同对应 pclk 频率不同; - PH1_LOGIC_HP_ISERDES:1 位串行 idata 转 10 位并行 odata[9:0],参数
IDDRMODE多一个 “DDRX1_PIPE” 档位,其余相同。


常见坑:pclk 和 sclk 频率关系配错
x2 家族要求 pclk = sclk/2、sclk = 数据率/2;HP SERDES 的 pclk 频率随 ODDRMODE/IDDRMODE 档位变化。这两个时钟必须由同一 PLL 按固定关系生成,随便拿两个不相干的时钟接入,串并转换出来的数据位序直接错乱。
动态延迟与三态缓冲:IDELAY、IOTRIBUF、IOBUF
高速源同步接口(如摄像头、ADC)里,数据和时钟的偏斜要靠输入延迟微调来修。PH1A 提供三档:
| 原语 | 适用 IO | 延迟设置 | 说明 |
|---|---|---|---|
| PH1_LOGIC_DYNAMIC_IDELAY | 普通 IO 输入 | in_dly 5 位,0~31 | 带 indly_en 动态使能 |
| PH1_LOGIC_DYNAMIC_HP_IDELAY | HP 类型 IO 输入 | dly 8 位,0~255 | 更细粒度 |
| PH1_LOGIC_DYNAMIC_HP_ODELAY | HP 类型 IO 输出 | dly 8 位,0~255 | 输出端延迟 |
三者都无参数、只支持原语例化(不支持 IP Generator)。手册注明:具体可使用动态调节的 IO 引脚详见《UG911 PH1A 系列 FPGA IO 用户手册》——不是每个引脚都有 IDELAY 资源,引脚分配前先查。
三态与缓冲:PH1_LOGIC_IOTRIBUF 是三态 IO 控制模块(i/t/o/io 四端口,t 控制输出使能,io 为双向引脚),驱动总线类接口用;PH1_LOGIC_IOBUF 是最简单的输入输出缓冲(i/o 两端口)。两者同样只支持原语例化。
常见坑:给 dly 填了超范围值
普通 IDELAY 只有 0
31 档(5 位),HP 版本才是 0255(8 位)。超范围赋值在综合阶段可能被静默截断,延迟档位和设计预期不符时,眼图测试会莫名失败。
存储三件套:DRAM、ERAM、RAMFIFO
DRAM:分布式 RAM
PH1_LOGIC_DRAM 是 FPGA 内部的分布式 RAM(用 LUT 资源实现),可配置为单口 RAM 使用。特点:读写端口独立配置位宽和深度(DATA_WIDTH_W/ADDR_WIDTH_W 与 DATA_WIDTH_R/ADDR_WIDTH_R 分开),深度 = 2**地址位宽。
PH1_LOGIC_DRAM #(
.DATA_WIDTH_W (9),
.ADDR_WIDTH_W (10),
.DATA_DEPTH_W (2 ** 10),
.DATA_WIDTH_R (9),
.ADDR_WIDTH_R (10),
.DATA_DEPTH_R (2 ** 10)
) u_DRAM (
.di (di),
.waddr (waddr),
.we (we),
.wclk (wclk),
.raddr (raddr),
.rdo (rdo)
);实用参数:READREG(读寄存器使能,开启后走 rdoq 输出,多一拍延迟)、RESETMODE(“SYNC”/“ASYNC”)、INIT_FILE(预加载文件)、FILL_ALL(未初始化空间填充,二进制串如 “0101”,不超过最宽端口位宽)。
ERAM:20K 块存储
PH1_LOGIC_ERAM 是 FPGA 内部的 ERAM20K 块存储资源,功能最全:四种工作模式 MODE——“DP”(真双口)、“SP”(单口)、“PDPW”(简单双口,一写一读)、“FIFO”;A/B 两口各自独立的数据/地址位宽、输出寄存器(REGMODE “NOREG”/“OUTREG”)、写模式(“NORMAL”/“READBEFOREWRITE”/“WRITETHROUGH”)、复位模式;还带字节使能(BYTE_ENABLE/BYTE_A/BYTE_B)和 ECC(ECC_ENCODE/ECC_DECODE,配合 ecc_sbiterr/ecc_dbiterr 标志与错误注入端口)。

手册的重要约束:当输出不带寄存器时,RESETMODE_A/B 只能选异步(“ASYNC”),不能选同步;输出带寄存器时才可选同步或异步。另外输出加寄存器(Output Register)后数据会延迟一个时钟周期输出——时序收敛和 latency 预算要一起看。
PH1_LOGIC_ERAM #(
.DATA_WIDTH_A(16), .DATA_WIDTH_B(16),
.ADDR_WIDTH_A(11), .ADDR_WIDTH_B(11),
.DATA_DEPTH_A(2048), .DATA_DEPTH_B(2048),
.MODE("PDPW"),
.REGMODE_A("NOREG"), .REGMODE_B("NOREG"),
.WRITEMODE_A("NORMAL"), .WRITEMODE_B("NORMAL"),
.IMPLEMENT("20K"),
.ECC_ENCODE("DISABLE"), .ECC_DECODE("DISABLE"),
.RESETMODE_A("ASYNC"), .RESETMODE_B("ASYNC")
) u_ERAM (
.dia(dia), .addra(addra), .cea(cea), .clka(clka),
.wea(1'b1), .rsta(1'b0), .bea(1'b0),
.dib({16{1'b0}}), .addrb(addrb), .ceb(ceb), .clkb(clkb),
.web(1'b0), .rstb(1'b0), .beb(1'b0),
.ocea(1'b0), .oceb(1'b0),
.doa(), .dob(dob),
.ecc_sbiterr(), .ecc_dbiterr(),
.ecc_sbiterrinj(1'b0), .ecc_dbiterrinj(1'b0)
);RAMFIFO:软核 FIFO
PH1_LOGIC_RAMFIFO 是软件集成的软核 FIFO 控制器,与硬核 FIFO 相比额外支持实时深度指示与 Showahead 模式。

PH1_LOGIC_RAMFIFO #(
.DATA_WIDTH(8),
.ADDR_WIDTH(8),
.SHOWAHEAD (1)
) u_RAMFIFO (
.rst (rst), // 异步复位,高有效
.clk (clk),
.di (di),
.we (we),
.re (re),
.dout (dout),
.empty_flag (empty_flag),
.full_flag (full_flag),
.rdusedw (rdusedw), // 可读数据个数
.wrusedw (wrusedw) // 已写数据个数
);SHOWAHEAD(1) 时数据先于读请求出现在 dout 上(先出后请),适合流式解析;rdusedw/wrusedw 实时报告 FIFO 内数据量,用来做反压控制。IMPLEMENT 固定 “20K”,即底层用 ERAM20K 实现。
常见坑:容量按 ADDR_WIDTH 直接算
FIFO 深度是 2**ADDR_WIDTH,但也别忽略 DATA_WIDTH——跨时钟域数据缓存的大小要按”最坏情况下游停顿时间 × 上游数据率”来算,而不是拍脑袋定 8 位地址。rdusedw 是做水位告警的关键端口,别忘了接出来。
器件管理:PVT、TS、ECC、DNA、MBOOT
PVT / TS:芯片电压温度监测
PH1_LOGIC_PVT 是 PH1A 内置的高集成度 PVT Sensor,可高精度测量芯片电压、温度,还有监控供电电压和工艺的模式。注意:只有 PH1A400 和 PH1A60 器件支持 PVT 模块;PH1_LOGIC_TS 是只测温度的 T Sensor,只有 PH1A90 和 PH1A180 支持。比赛用的 EG4S20 属于 PH1A 系列,使用前先确认手上的具体型号。
两个 sensor 的使用规则几乎一样,坑也相同:
- clk 推荐工作频率低(PVT 1.2MHz、TS 1MHz),用分频时钟驱动;
ena不能直接接常 1,必须提供上升沿触发信号,且保持有效直到 data_valid 到来,否则会复位 sensor;- PVT 的
vsample在 ena 为高期间不得变化(0 测温度、1 测电压),否则变化后的输出数据错误; - 输出 data_out 10 位,data_valid 与 clk 同步高有效。
ECC_V2:配置存储纠错
PH1_LOGIC_ECC_V2 让用户控制 ECC 逻辑的发起和停止,并获取错误和地址信息,校验对象是 Configuration Memory(配置帧)。关键端口与行为:
ecc_enable_n_i拉低并保持 → ECC 开始运行(低有效,同步于 ecc_clk_o);ecc_clk_o由内部晶振分频得到,PH1A 频率范围 2~11MHz,可用参数ECC_FREQ配置(“2MHz”/“3MHz”/“5MHz”/“11MHz”);ecc_stop_o默认高(停止态),从接收停止操作到安全停止需要等待时间,主动停止后必须等 ecc_stop_o 变高才能重新发起;ecc_done_o校验到最后一个配置帧并进入 global crc check 阶段时拉高;ecc_info_o[37:0]打包了错误信息:[37:15] 配置帧地址、[14:8]+[7:3] syndrome(对应 81 个 DWORD 和 32 bit)、[2] 单 bit 错误、[1] 双 bit 错误、[0] gcrc 错误。
参数三个关键项:ECC_PROTECT(ENABLE 时检测到单 bit 错误做二次校验)、SEC_OPTION(“HOLD” 停机等待 / “CORRECT_AND_CONTINUE” 修复后继续 / “CORRECT_AND_HOLD” 修复后停机)、ECCERR_REPORT_EN(ENABLE 时出错把 INITN 引脚拉低,外部可观测)。
还有一组按器件型号写死的保留端口接法:PH1A400 的 ecc_endaddrdebug_n_i 接高、ecc_endaddr_i 全低;PH1A90 接低 + 23’h1a_0c9e;PH1A180 接低 + 23’h22_199e。
DNA_V2:读取芯片唯一 ID
PH1_LOGIC_DNA_V2 提供读取 64 位芯片唯一 DNA 的接口,移位协议四个端口:dna_clk_i、dna_shift_n_i(低有效移位使能)、dna_din_i(用户数据移入)、dna_do_o(数据移出)。参数 EXT_DNA_CLK_I 默认 “SIG”。手册注明它与老版本 PH1_LOGIC_DNA 端口和参数完全一致,可直接替换。做加密授权、设备指纹时用它——每颗芯片的 DNA 出厂唯一。
MBOOT_V2:多套位流启动
PH1_LOGIC_MBOOT_V2 是多启动模块:在 SPI FLASH 里放两套或多套位流,上电先加载 Primary 位流,Primary 里的逻辑可以控制 FPGA 跳转到指定地址重新加载——现场升级、A/B 分区容灾的硬件基础。
三个端口:multiboot_en_n_i(低有效使能)、multiboot_code_i(等于 8’hA5 时多重启动才生效,防误触发)、multiboot_addr_i(32 位重启地址)。参数:MULTBOOT_ADDRSRC_SEL(“STATIC” 静态地址 / “DYNAMICAL” 动态地址)、MULTBOOT_STATIC_ADDR(默认 32’h0100_0000)。注意 V2 与老版本的区别:V2 静态启动地址默认 32’h0100_0000,老版本 PH1_LOGIC_MBOOT 是 32’h0080_0000。
通关标准:
- 拿到一份 DDR 接口需求,能根据速率在 IDDR/IDDRx2/HP_ISERDES 中选出正确原语,并说清 pclk 与 sclk 的频率关系;
- 能例化一个 RAMFIFO 并用 SHOWAHEAD、rdusedw 设计反压逻辑;
- 能说出 ERAM 输出寄存器与复位模式的联动约束(无输出寄存器时复位只能异步)。
IDDRx21 比 IDDRx2 省了什么、代价是什么?
省了一个 pclk 时钟资源:IDDRx21 直接用内部 sclk 的 2 分频当 pclk。代价是数据输出比 IDDRx2 模式晚一个 sclk 时钟周期。时钟资源紧张、对延迟不敏感的场合选 x21。
ERAM 输出想配同步复位,行不行?
只有在输出带寄存器(REGMODE 为 “OUTREG”)时才能配同步复位;输出不带寄存器时 RESETMODE_A/B 只能选 “ASYNC”,同步配置非法。
PVT 的 ena 为什么不能直接接 1?
ena 是异步使能,需要上升沿触发才能保证 sensor 正常工作;直接接常 1 没有上升沿,且使能期间必须保持到 data_valid 有效,否则 sensor 会被复位。正确做法是用一个置位触发器在采样开始时产生脉冲沿。
multiboot_code_i 为什么要写成 8'hA5 才生效?
这是一个防误触发魔数(magic key):只有 Primary 位流里的逻辑明确给出 8’hA5 才会执行重加载,防止逻辑跑飞或总线毛刺意外触发位流切换导致系统重启。
RAMFIFO 的 SHOWAHEAD 模式和普通模式读数据有什么区别?
普通模式下 re 拉高后 dout 下一拍才出数据;SHOWAHEAD 模式下数据先出现在 dout 上,re 相当于”弹出确认”。解析器可以先 peek 头部数据再决定是否弹出,写协议解析状态机时更方便。