这一篇在干嘛?

UG910 精读第二篇,覆盖三大家族:IO 族(DDR 转换、串并转换、动态延迟、三态缓冲)、存储族(分布式 RAM、ERAM20K 块存储、软核 FIFO)和器件管理族(电压温度监测、配置存储纠错、芯片 DNA、多启动)。时钟与运算原语见 原语库 PH1A(1),目录页在 原语库 PH1A

IO 双沿转换:IDDR 与 ODDR

高速串并转换:x2 家族与 HP SERDES

动态延迟与三态缓冲:IDELAY、IOTRIBUF、IOBUF

存储三件套:DRAM、ERAM、RAMFIFO

器件管理:PVT、TS、ECC、DNA、MBOOT

IO 双沿转换:IDDR 与 ODDR

DDR 接口(如摄像头 D-PHY、DDR 存储器)在时钟上升沿和下降沿都传数据,而 FPGA 内部逻辑只在单沿工作,中间必须有个转换器——这就是 IDDR(输入)和 ODDR(输出)。

PH1_LOGIC_IDDR 是 IO 上将双沿采样数据变为单沿数据的单元:带数据对齐的双速率 D 触发器、异步复位,把输入的 DDR 数据转为 q0(上升沿数据)、q1(下降沿数据)两位同步到内部时钟网络。

IDDR 原语框图

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 原语框图

常见坑:不例化 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)。

IDDRx2 原语框图

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 分频,输出同样晚一拍。

ODDRx2 原语框图

四个原语的参数都只有 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” 档位,其余相同。

HP_OSERDES 原语框图

HP_ISERDES 原语框图

常见坑: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_IDELAYHP 类型 IO 输入dly 8 位,0~255更细粒度
PH1_LOGIC_DYNAMIC_HP_ODELAYHP 类型 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 只有 031 档(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 标志与错误注入端口)。

ERAM 原语框图

手册的重要约束:当输出不带寄存器时,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 模式

RAMFIFO 原语框图

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

通关标准:

  1. 拿到一份 DDR 接口需求,能根据速率在 IDDR/IDDRx2/HP_ISERDES 中选出正确原语,并说清 pclk 与 sclk 的频率关系;
  2. 能例化一个 RAMFIFO 并用 SHOWAHEAD、rdusedw 设计反压逻辑;
  3. 能说出 ERAM 输出寄存器与复位模式的联动约束(无输出寄存器时复位只能异步)。