这一篇在干嘛?
第 1 篇解决了”时钟怎么走、DDR 数据怎么收发”,这一篇补齐 UG710 的另外三大功能族:存储(硬核 FIFO、软核 RAMFIFO、ERAM20K 块存储、分布式 DRAM、移位寄存器 SHIFTER)、运算(硬核乘法器 MULT 与 DSP 加法/逻辑/寄存器家族、软核除法器 SEQ_DIV),以及系统辅助(SLICE 底层积木、配置存储纠错 ECC、芯片唯一码 DNA、电压温度传感器 PVT、全局控制 GCTRL/TRSTN)。时钟与 IO 部分见第 1 篇。
DSP 家族:DSPADD、DSPLOGIC、DSPREG、DSPMREG、DSPTADD
本篇导读:存储与运算资源怎么选
PH1A100 片上的存储和运算硬件不止一种,选型错了不是”性能差点”,而是根本综合不出来或资源爆掉。先给一张地图:
| 需求 | 该用谁 | 一句话理由 |
|---|---|---|
| 跨时钟域缓冲、位宽 1~320 | PH1_LOGIC_FIFO(硬核) | 双时钟域原生支持,带 ECC |
| 跨时钟域 + 想知道”还剩多少数据” | PH1_LOGIC_RAMFIFO(软核) | 额外支持实时深度指示与 Showahead |
| 大容量存储(20K bit 为单位级联) | PH1_LOGIC_ERAM | 单/伪双口/真双口/FIFO 四种模式 |
| 小容量、要很多份的存储 | PH1_LOGIC_DRAM | 用 LUT/CLB 资源实现的分布式 RAM |
| 延迟线、行缓冲 | PH1_LOGIC_SHIFTER | 固定深度移位链 |
| 乘法 | PH1_LOGIC_MULT | 18x18→36 硬核乘法器 |
| 乘加/复杂运算流水的积木 | DSPADD/DSPLOGIC/DSPREG/DSPMREG/DSPTADD | DSP 块内部各功能单元 |
| 除法(商+余数) | PH1_LOGIC_SEQ_DIV | TD 软核除法器,多拍完成 |
这些原语大部分同时支持原语例化和 IP Generator(FIFO/ERAM/DRAM/RAMFIFO/SHIFTER/SEQ_DIV/DSP 系列都是),只有 MULT、SLICE 等少数只支持手写例化。
硬核 FIFO:PH1_LOGIC_FIFO
PH1_LOGIC_FIFO 是片上硬 FIFO 单元,写口和读口各自独立(时钟、复位、使能、片选全套分离),天然适合跨时钟域。

端口要点(完整表见 UG710 第 10.2 节):
| 端口 | 方向 | 功能 |
|---|---|---|
| wrst / rrst | input | 写/读复位,高有效 |
| clkw / clkr | input | 写/读时钟 |
| di / dout | inout | 写入 / 读出数据(DATA_WIDTH 位) |
| we / re | input | 写/读使能 |
| csw / csr | input, 3 | 片选,高有效,必须接 3’b111 |
| ore / owe | input | 读出/写寄存器使能 |
| empty_flag / full_flag | output | 空/满标志 |
| fifo_wrpointer / fifo_rdpointer | output | 写/读指针 |
| ecc_sbiterr / ecc_dbiterr | output | ECC 单/双 bit 错误标志 |
关键参数:
| 参数 | 范围 | 默认 | 说明 |
|---|---|---|---|
| DATA_WIDTH | 1~320 | 9 | 数据宽度 |
| ADDR_WIDTH | 9~14 | 10 | 地址位宽(决定深度) |
| REGMODE_W / REGMODE_R | ”NOREG”/“OUTREG" | "NOREG” | 写/读寄存器 |
| AE / AF | 0~2^14 | 96 | 快空/快满标志深度 |
| CLKMODE | ”SYNC”/“ASYNC" | "SYNC” | 时钟模式 |
| FIRSTWRITE_RD | ENABLE/DISABLE | DISABLE | Read Ahead 使能 |
| ECC_ENCODE / ECC_DECODE | ENABLE/DISABLE | DISABLE | ECC 编解码 |
| ASYNC_RESET_RELEASE | ”SYNC”/“ASYNC" | "SYNC” | 异步复位是否同步释放 |
| GSR | ENABLE/DISABLE | DISABLE | 全局复位使能 |
PH1_LOGIC_FIFO #(
.DATA_WIDTH_W(9),
.ADDR_WIDTH(10),
.REGMODE_W("NOREG"),
.REGMODE_R("NOREG"),
.GSR("DISABLE"),
.FIRSTWRITE_RD("DISABLE"),
.AE(96),
.AF(96),
.ECC_DECODE("DISABLE"),
.ECC_ENCODE("DISABLE"),
.ASYNC_RESET_RELEASE("SYNC")
) u_LOGIC_FIFO (
.rrst(rrst), .di(di), .clkw(clkw), .we(we), .csw(csw),
.dout(dout), .clkr(clkr), .re(re), .csr(csr),
.ore(ore), .owe(owe),
.ecc_sbiterr(ecc_sbiterr), .ecc_dbiterr(ecc_dbiterr),
.empty_flag(empty_flag), .full_flag(full_flag),
.fifo_wrpointer(fifo_wrpointer), .fifo_rdpointer(fifo_rdpointer)
);常见坑:
①
csw/csr两个片选不是普通使能,手册写明必须接 3’b111,悬空或接别的值 FIFO 不工作。② 深度是 2^ADDR_WIDTH 而不是 ADDR_WIDTH 本身,ADDR_WIDTH=10 就是 1024 深。③ 跨时钟域用的时候 CLKMODE 必须配 “ASYNC”,默认值是 “SYNC”,用默认值跨时钟域指针比较会出错。
软核 FIFO:PH1_LOGIC_RAMFIFO
PH1_LOGIC_RAMFIFO 是 TD 集成的软核 FIFO 控制器(基于 ERAM20K 实现,IMPLEMENT 参数固定 “20K”)。与硬核 FIFO 相比,它额外支持两个好用的特性:实时深度指示(rdusedw/wrusedw 直接告诉你可读/已写数据个数)和 Showahead 模式(SHOWAHEAD=1 时数据先摆在 dout 上,读使能来了即”确认拿走”,省一拍读延迟)。
| 端口 | 方向 | 功能 |
|---|---|---|
| rst | input | 异步复位,高有效 |
| di / dout | inout | 数据输入 / 输出(DATA_WIDTH 位) |
| clk | input | 时钟(注意:单时钟,读写共用) |
| we / re | input | 写/读使能 |
| empty_flag / full_flag | output | 空/满指示 |
| rdusedw / wrusedw | output | 可读数据个数 / 已写数据个数 |
参数只有 4 个:DATA_WIDTH(默认 8)、ADDR_WIDTH(默认 8)、SHOWAHEAD(0/1,默认 0)、IMPLEMENT(固定 “20K”)。
PH1_LOGIC_RAMFIFO #(
.DATA_WIDTH(8),
.ADDR_WIDTH(8),
.SHOWAHEAD(1)
) u_logic_ramfifo (
.rst(rst), .di(di), .we(we), .dout(dout),
.clk(clk), .re(re),
.empty_flag(empty_flag), .full_flag(full_flag),
.rdusedw(rdusedw), .wrusedw(wrusedw)
);和硬核 FIFO 的选择依据:要跨时钟域选硬核 PH1_LOGIC_FIFO(双时钟口);单时钟域但需要流量监控(按 rdusedw 做反压/整形)或 Showahead 快速读,选软核 RAMFIFO。
块存储:PH1_LOGIC_ERAM(ERAM20K)
PH1_LOGIC_ERAM 对应片上 ERAM20K 资源,是容量最大的存储原语。通过 MODE 参数支持四种工作模式:“DP”(真双口)、“SP”(单口)、“PDPW”(简单双口,一口写一口读)、“FIFO”。A/B 两个口各有独立的时钟、使能、字节使能、复位和输出寄存器配置。

端口骨架(每口一组):dia/addra/cea/ocea/clka/wea/rsta/bea/doa(A 口),dib/addrb/.../dob(B 口),另有 ecc_sbiterr/ecc_dbiterr。参数重点:
| 参数 | 说明 |
|---|---|
| DATA_WIDTH_A/B、ADDR_WIDTH_A/B | 各口数据/地址位宽,深度 = 2^ADDR_WIDTH |
| MODE | ”DP”/“SP”/“PDPW”/“FIFO”,默认 “DP” |
| REGMODE_A/B | ”NOREG”/“OUTREG” 输出寄存器 |
| WRITEMODE_A/B | ”NORMAL”/“READBEFOREWRITE”/“WRITETHROUGH” 写模式 |
| RESETMODE_A/B | ”SYNC”/“ASYNC”,默认 ASYNC |
| BYTE_ENABLE | 0/8/10,字节使能粒度 |
| ECC_ENCODE / ECC_DECODE | ECC 编解码使能 |
| CLK_MODE | ”ASYNC”/“SYNC”,默认 ASYNC |
| INIT_FILE / FILL_ALL | 初始值文件 / 未初始化空间填充 |
一个简单双口(PDPW)的例化骨架:
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"),
.ECC_ENCODE("DISABLE"), .ECC_DECODE("DISABLE"),
.CLKMODE("ASYNC"),
.RESETMODE_A("ASYNC"), .RESETMODE_B("ASYNC"),
.ASYNC_RESET_RELEASE_A("SYNC"), .ASYNC_RESET_RELEASE_B("SYNC"),
.INIT_FILE("NONE"), .FILL_ALL("NONE")
) inst (
.dia(dia), .addra(addra), .cea(cea), .clka(clka), .wea(wea),
.dib({16{1'b0}}), .addrb(addrb), .ceb(ceb), .clkb(clkb), .web(1'b0),
.ocea(1'b0), .oceb(1'b0),
.bea(1'b0), .beb(1'b0), .rsta(1'b0), .rstb(1'b0),
.ecc_sbiterr(open), .ecc_dbiterr(open),
.doa(), .dob(dob)
);常见坑:
手册注释第 14.3 节写得很明确:输出不带寄存器时,RESETMODE 只能选 “ASYNC”,不能选同步;带输出寄存器(OUTREG)时才可以二选一。另外输出加寄存器后数据会延迟一个时钟周期,算读延迟时别漏了这一拍。
分布式 RAM:PH1_LOGIC_DRAM
PH1_LOGIC_DRAM 是分布式 RAM,用逻辑资源实现,可配置为单口或简单双口 RAM。和 ERAM 相比容量小、但数量多、分布广,适合小而多的存储需求(寄存器堆、小查找表、状态缓冲)。

端口:写侧 di/waddr/wclk/we,读侧 raddr/rclk/rce/rrst,输出两套:rdo(不带寄存器)和 rdoq(带寄存器)。参数:
| 参数 | 默认 | 说明 |
|---|---|---|
| DATA_WIDTH_W / ADDR_WIDTH_W | 8 / 6 | 写侧位宽/地址位宽 |
| DATA_WIDTH_R / ADDR_WIDTH_R | 8 / 6 | 读侧位宽/地址位宽 |
| DATA_DEPTH_W/R | 2^ADDR_WIDTH | 深度自动跟随地址位宽 |
| READREG | ”DISABLE” | 读寄存器使能 |
| RESETMODE | ”SYNC” | 复位模式 |
| INIT_FILE / FILL_ALL | ”NONE” | 初始值文件 / 未初始化填充 |
PH1_LOGIC_DRAM #(
.DATA_WIDTH_W(9), .ADDR_WIDTH_W(10),
.DATA_WIDTH_R(9), .ADDR_WIDTH_R(10)
) u_LOGIC_DRAM (
.di(di), .waddr(waddr), .we(we), .wclk(wclk),
.raddr(raddr), .rdo(rdo)
);注意 RESETMODE 默认是 “SYNC”,和 ERAM(默认 ASYNC)方向相反,两个都手写例化时容易记混。
移位寄存器:PH1_LOGIC_SHIFTER
PH1_LOGIC_SHIFTER 是片内移位寄存器模块,典型用途是数据延迟线、图像行缓冲。datain 默认上升沿锁存,en 控制是否移位,深度由参数和端口共同决定——这是它最容易踩坑的地方。

参数与深度规则:
| 参数 | 默认 | 说明 |
|---|---|---|
| DATA_WIDTH | 16 | 数据位宽 |
| DEPTH_WIDTH | 2 | 地址位宽 |
| SHIFT_TYPE | ”FIXED" | "FIXED”/“VARIABLE” 转换类型 |
| DATA_DEPTH | 32 | 数据深度 |
| INIT_FILE | ”NONE” | 预加载初始值文件 |
规则拆开讲:SHIFT_TYPE="FIXED" 时 depth 端口是无用信号,深度就是 DATA_DEPTH;SHIFT_TYPE="VARIABLE" 时深度为 2^DEPTH_WIDTH,depth 端口是真实的运行时深度控制信号。但注意手册注释:PH1A100 器件不支持 “VARIABLE” 模式,只支持 “FIXED”,所以在这颗芯片上 depth 端口实际不用管。深度还有一条属性表公式:16 位宽时 shift_depth = depth[4:0] + 2(0x00→2,0x1F→33,最大 33);8 位宽时 shift_depth = depth[5:0] + 2(最大 65)。
PH1_LOGIC_SHIFTER #(
.DATA_WIDTH(16),
.DEPTH_WIDTH(2),
.SHIFT_TYPE("FIXED")
) u1_LOGIC_SHIFTER (
.clk(clk), .en(en),
.datain(datain),
.depth(depth),
.dataout(dataout)
);乘法器:PH1_LOGIC_MULT
PH1_LOGIC_MULT 是硬核乘法器,默认 18x18 → 36 位,A/B/输出三级都有可选寄存器(PIPE),适合做滤波器、FFT 这类流水化乘法。

| 端口 | 方向 | 功能 |
|---|---|---|
| a / b | input | 乘数(INPUT_WIDTH_A/B 位) |
| p | output | 乘积(OUTPUT_WIDTH 位) |
| cea / ceb / cepd | input | A/B/输出片选,高有效 |
| rstan / rstbn / rstpdn | input | A/B/输出复位,低有效 |
| clk | input | 同步时钟 |
参数要点:
| 参数 | 默认 | 说明 |
|---|---|---|
| INPUT_WIDTH_A/B / OUTPUT_WIDTH | 18/18/36 | 位宽 |
| INPUTFORMAT | ”SIGNED" | "SIGNED”/“UNSIGNED” |
| INPUTREGA/INPUTREGB/OUTPUTREG | ”ENABLE” | 三级寄存器使能 |
| SRMODE | ”ASYNC” | 复位置位模式 SYNC/ASYNC |
| IMPLEMENT | ”AUTO" | "AUTO”/“DSP”/“GATE”,实现方式 |
PH1_LOGIC_MULT #(
.INPUT_WIDTH_A(18), .INPUT_WIDTH_B(18), .OUTPUT_WIDTH(36),
.INPUTFORMAT("SIGNED"),
.INPUTREGA("ENABLE"), .INPUTREGB("ENABLE"), .OUTPUTREG("ENABLE"),
.SRMODE("ASYNC"),
.IMPLEMENT("AUTO")
) MULT_inst (
.p(p), .a(a), .b(b),
.cea(cea), .ceb(ceb), .cepd(cepd),
.clk(clk),
.rstan(rstan), .rstbn(rstbn), .rstpdn(rstpdn)
);时序规则一句话:任何一级寄存器使能都会让输出延迟一个时钟周期,全开时 a/b 进来后 3 拍才出现在 p 上。它只支持原语例化(IP Generator 为”否”),所以流水级数要自己心里有数。
DSP 家族:DSPADD、DSPLOGIC、DSPREG、DSPMREG、DSPTADD
MULT 之外的五个 DSP 原语是 DSP 块内部各功能单元的独立入口,用来搭更复杂的运算流水线:
- PH1_PHY_DSPADD:27 位加/减法模块。
opctrl[0]使能,opctrl[1]选 sum=a+b 或 a-b。 - PH1_PHY_DSPLOGIC:54 位逻辑运算模块,
opctrl[3:0]选择 xor/xnor/and/and-not/or/nor/nand 等十种运算,另有 54 位输入的宽位异或输出wxor[1:0]。 - PH1_PHY_DSPREG:DSP 寄存器模块,WIDTH 可配 1~54,参数 RSTMUX/CEMUX/CLKMUX 与 RSTMODE(SYNC/ASYNC,默认 ASYNC)。
- PH1_PHY_DSPMREG:带动态级数选择的寄存器模块。
opctrl=0时 dynamic_q 是 d 的 2 级寄存输出;opctrl=1时级数由DYNAMIC_DATA参数决定(“D” 为 0 级直通,“Q” 为 1 级)。可在运行中切换流水深度。 - PH1_PHY_DSPTADD:动态选择切换的三输入加法器。x0/y0/z0 与 x1_special/y1_special/z1_special 可运行时动态切换,
opctrl[3:0]决定 sum 表达式(x+y+z+ci 及各路取负组合),opctrl[8:4]控制各输入的切换与 overflow/underflow 输出;参数 X1_EXTEND(符号扩展)、Y1_ROUND(换成内置常数 RND_CONST)、Z1_SHIFT(右移 17 位)、CI_INVERT(进位取反)用于特殊运算(如四舍五入、移位对齐)。
// DSPADD 示例
PH1_PHY_DSPADD DSPADD_inst (
.a(a), .b(b), .opctrl(opctrl), .sum(sum)
);
// DSPMREG 示例
PH1_PHY_DSPMREG DSPMREG_inst (
.clk(clk), .rst(rst), .ce(ce),
.d(d), .opctrl(opctrl), .dynamic_q(dynamic_q)
);DSP 家族成员都同时支持原语例化和 IP Generator。竞赛项目里如果只做普通乘加,用 MULT 甚至让综合器推断 * 就够了;DSPTADD/DSPMREG 这类动态切换单元用在需要运行时改数据通路的高阶场景。
软核除法器:PH1_LOGIC_SEQ_DIV
PH1_LOGIC_SEQ_DIV 是 TD 集成的软核除法器,多周期完成一次除法,输出商和余数。握手时序是关键:
| 端口 | 方向 | 功能 |
|---|---|---|
| clk / rst | input | 时钟 / 复位(rst=1 时 quotient、remain 置 0,done 置 1) |
| start | input | 置 1 缓存输入数据;由 1 变 0 时开始计算 |
| numer / denom | input | 被除数(NUMER_WIDTH)/ 除数(DENOM_WIDTH) |
| quotient / remain | output | 商 / 余数,done=1 时才有效 |
| done | output | 计算完成标志 |
参数只有两个:NUMER_WIDTH、DENOM_WIDTH,默认都是 16。
PH1_LOGIC_SEQ_DIV #(
.NUMER_WIDTH(16),
.DENOM_WIDTH(16)
) u_LOGIC_SEQ_DIV (
.clk(clk), .rst(rst), .start(start),
.numer(numer), .denom(denom),
.quotient(quotient), .remain(remain), .done(done)
);常见坑:
手册特别提示:start=0 之后改变 numer/denom 不影响本次计算,但”为了防止波形显示时产生误解”,应该在 done=1 之后才提供下一组输入——即标准的”请求-等待-取数-再请求”握手,别在计算中途换数。
底层积木:PH1_LOGIC_SLICE
PH1_LOGIC_SLICE 是 FPGA 最底层逻辑单元 SLICE 的原语入口。一个 SLICE 内含两个非独立的双 LUT5、两个独立的 DFF,还有进位链(fci/fco)。平时写 Verilog 从不需要碰它,但看懂它能明白综合器在底层怎么摆放逻辑,也能在特殊场合手工榨性能。

端口分组:组合输入 ia~ie/imf;复用输入 ima/imb;寄存器控制 clk/cea/ceb/ssr/asr;输出 oqa/oqb(时序)、ofa/ofb(组合);进位 fci/fco。参数非常多(LUTMODE、INIT_LUT5A/B、各路 MUX 选择……),核心逻辑是:
LUTMODE:“LUT6”(两片 LUT5 拼成一片 LUT6)或 “DLUT5”(两片独立 LUT5)。INIT_LUT5A/INIT_LUT5B:32 位真值表直接定义 LUT 功能——这就是”LUT 是一张 32x1 查找表”的具象化。- 各
*_MUX/*_SD参数决定内部信号怎么走(寄存器输入来自 LUT 还是复用口、输出选组合还是时序等)。
手册给的示例是”SLICE 配置为 LUT6 输出:寄存器输出和不带寄存器输出”:
PH1_LOGIC_SLICE #(
.REGB_SD("LUT6"),
.LUTMODE("LUT6"),
.CLKMUX("SIG"),
.INIT_LUT5A(INIT_LUT5A),
.INIT_LUT5B(INIT_LUT5B),
.CEBMUX("SIG"),
.SSRMUX("SIG"),
.ASRMUX("SIG"),
.OFB_SD("LUTX"),
.OQBMUX("QB")
) lut6_inst (
.imf(imf), .ie(ie), .id(id), .ic(ic), .ib(ib), .ia(ia),
.ceb(1'b1), .clk(clk), .ssr(1'b0), .asr(1'b0),
.oqb(oqb), // reg output
.ofb(ofb) // lut6 output
);只支持原语例化。初学者了解即可,别在常规逻辑里手写 SLICE。
可靠性与身份:ECC、DNA、PVT
这三个原语不参与你的数据通路,但竞赛/产品化场景经常用得上:
PH1_LOGIC_ECC——配置存储器纠错单元。FPGA 的配置存储(Configuration Memory)在太空/高辐射/老化场景可能发生单粒子翻转,ECC 单元可对配置帧做校验、修复并上报错误信息。工作流程:拉低 ecc_enable_n_i 并保持 → 等 ecc_stop_o 变低开始运行 → 校验完最后一个配置帧进入 global crc check 阶段时 ecc_done_o 拉高(至少持续 2 个 ecc_clk_o 周期)→ 38 位 ecc_info_o 携带出错配置帧地址、syndrome、单/双 bit 错误与 gcrc 错误标志。参数:ECC_PROTECT(保护模式:单 bit 错误二次校验)、SEC_OPTION(“HOLD”/“CORRECT_AND_CONTINUE”/“CORRECT_AND_HOLD” 三种纠错策略)、ECCERR_REPORT_EN(出错时拉低 INITN 管脚对外报告)、ECC_FREQ(2/3/5/11MHz)。ecc_clk_o 由内部晶振分频产生,用户只需提供使能时序。

PH1_LOGIC_DNA——读取 64 位芯片唯一 DNA。移位寄存器式接口:dna_shift_n_i 低电平使能移位,dna_din_i 移入、dna_do_o 逐位移出。参数 EXT_DNA_CLK_I 控制时钟来源。典型用途:产品序列号、加密绑板。
PH1_LOGIC_PVT——芯片内置两个 PVT Sensor,可高精度测量电压和温度(VSAMPLE=0 测温度、1 测电压),data_out 10 位,data_valid 指示有效。参数 SENSOR_LOC 选传感器位置(“0” 芯片右上角、“1” 芯片中间),EXT_ENA 选外部使能方式。

常见坑:
PVT 的
ena是异步使能,手册注释写明不能直接接常量 1,必须提供上升沿触发信号,并保持有效直到 data_valid,否则会复位 sensor;时钟推荐 1.2MHz。三个原语都只支持原语例化。
杂项控制信号:GCTRL 与 TRSTN
最后两个是芯片级控制信号的原语入口,端口极少:
- PH1_LOGIC_GCTRL:加载标准信号输出模块,只有两个输出端口
done_o(DONE 信号)和wakeup_o(wakeup 信号),把芯片配置完成/唤醒状态引给用户逻辑用。 - PH1_LOGIC_TRSTN:用户 TRSTN 控制信号,输入
usrtrstn_i和选择信号usrtrstn_sel_n_i,参与内部复位树控制。
PH1_LOGIC_GCTRL LOGIC_GCTRL_inst (
.done_o(done_o),
.wakeup_o(wakeup_o)
);两者都只支持原语例化、无参数。它们在 UG710 里篇幅最短,但在做”配置完成后才开始工作”(等 done_o)这类上电时序设计时会用到。
通关标准:
- 能说出硬核 FIFO 与软核 RAMFIFO 的两条选择依据(跨时钟域 vs 深度指示/Showahead)。
- 能解释 ERAM 的 RESETMODE 与输出寄存器的联动规则(无输出寄存器只能异步复位)。
- 能独立例化 SEQ_DIV 并描述 start/done 的正确握手时序。
自测 1:例化 PH1_LOGIC_FIFO 时 csw/csr 忘了接,会发生什么?
FIFO 不工作。手册明确 csw/csr 是高有效片选且必须接 3’b111,它们不是普通写/读使能。这是 FIFO 例化里最容易漏的”隐藏必接端口”,症状是编译能过但读写永远无响应。
自测 2:为什么跨时钟域场景必须把 FIFO 的 CLKMODE 配成 "ASYNC"?
默认 “SYNC” 假设读写时钟同源,内部指针比较按同步逻辑处理;跨时钟域时读写指针分属两个时钟域,按 SYNC 处理会导致空/满标志误判(亚稳态/假满假空),数据丢失或卡死。CLKMODE=“ASYNC” 才会启用跨域指针同步机制。
自测 3:PH1A100 上想把 SHIFTER 做成运行时可变深度,行不行?
不行。SHIFT_TYPE=“VARIABLE” 才支持 depth 端口做运行时深度控制,但手册注明 PH1A100 只支持 “FIXED” 模式,深度在参数 DATA_DEPTH 里静态确定,depth 端口是无用信号。要动态深度只能换 VARIABLE 支持的器件,或用 DRAM 自建环形缓冲。
自测 4:MULT 三级寄存器全开时,输入 a/b 到输出 p 延迟几拍?
3 拍。INPUTREGA、INPUTREGB、OUTPUTREG 每一级寄存器各延迟一个时钟周期,手册注明”输入或者输出加寄存器,输出会延迟一个时钟周期输出”。做流水线对齐时要把这 3 拍算进控制通路。
自测 5:PVT 的 ena 直接接 1'b1 为什么测不出数据?
ena 是异步使能,需要上升沿触发,直接接常量 1 没有上升沿,sensor 不会启动采样;而且手册要求 ena 保持有效直到 data_valid 出现,中途撤销会复位 sensor。正确做法是用一个从 0→1 的控制信号(如上电后状态机拉高)驱动 ena,时钟用推荐的 1.2MHz。