这一篇在干嘛?

这是 UG910《PH1A 系列 FPGA Libraries Guide for HDL Designs》精读的第一篇,讲时钟和运算两大族原语。原语是芯片里真实存在的硬件单元,例化一个原语就是”占用”一个硬件资源——所以要先搞清它是什么、什么时候用、参数怎么填。IO、存储与器件管理原语见 原语库 PH1A(2),目录页在 原语库 PH1A

原语怎么用:例化模板与两种支持方式

全局缓冲 BUFG:时钟和高扇出信号的专属高速路

GCLK:两路全局时钟的无毛刺切换

区域时钟 MLCLK、SCLK、IOCLK

分频原语 LCLK 与 OSCDIV

PLL:倍频、分频、相移一把抓

运算原语速查:除法器、移位器、SLICE、乘法器

原语怎么用:例化模板与两种支持方式

每个原语在手册里都按固定五件套介绍:简介、端口描述、参数描述、使用方式、Verilog 例化示例。例化的写法和普通 module 一样,只是模块名换成原语名,参数用 #(...) 传:

PH1_LOGIC_BUFG u_BUFG (
    .i (clk_in),
    .o (clk_out)
);

手册里每个原语都有一个”使用方式”表,说明两种支持方式:

使用方式含义
原语例化直接在 Verilog 里例化原语模块
IP Generator在 TD 的 IP 界面里图形化配置生成

注意:不是所有原语都支持 IP Generator(如 BUFG、GCLK、LCLK、OSCDIV、SLICE、MULT 都只支持原语例化),这些只能手写例化。参数取值多为字符串枚举(如 "ENABLE"/"DISABLE"),照抄手册别自由发挥。

常见坑:手册例化代码是 OCR 扫描件

MinerU 解析出的例化代码常有空格错乱(如 . c/k(clk)u_ LOGIC_BUFG)。照抄时务必自己整理成合法 Verilog:端口名无空格、. 与端口名紧挨、逗号齐全,否则综合直接报语法错。

全局缓冲 BUFG:时钟和高扇出信号的专属高速路

PH1_LOGIC_BUF 是 FPGA 内部的低延时布线资源;PH1_LOGIC_BUFG 则是高扇出的全局时钟缓冲器,延时和抖动小。手册明确:BUFG 常用于时钟网络和其他高扇出网络(如复位信号、时钟使能),且可以将普通信号走线到 BUFG 上

BUFG 原语框图

两者端口都只有 i/o 各 1 位,无参数。什么时候该用?判断标准是扇出和时序要求:

  • 时钟信号 → 必须(否则时钟树偏斜大,时序难以收敛);
  • 全局复位、全局时钟使能这类扇出几百上千的信号 → 强烈建议;
  • 普通数据信号 → 不用,浪费全局布线资源。

常见坑:所有信号都往 BUFG 上挂

全局时钟网络数量有限,普通低扇出信号走 BUFG 既占资源也不带来任何好处。只有”几乎每个触发器都要用”的信号才配得上 BUFG。

GCLK:两路全局时钟的无毛刺切换

PH1_PHY_GCLK_V2 是全局时钟缓冲选择器:从两路输入时钟 clkin[1:0] 里选一路输出到 clkout,并且可以控制切换过程是否产生毛刺

GCLK 原语框图

端口与控制逻辑:

端口位宽作用
clkin2两路输入时钟
seln2时钟选择,低电平有效
cen2寄存器时钟使能,低电平有效
drct2无毛刺切换使能:2'b00 无毛刺模式(切换会丢失一个下降沿);2'b11 普通模式(切换可能出毛刺)
clkout1输出时钟

输出选择真值表( cen/seln 组合决定输出哪一路):

cen[0]seln[0]cen[1]seln[1]clkout
001Xclkin[0]
00X1clkin[0]
1X00clkin[1]
X100clkin[1]

参数:PRESELECT(初始输出选 CLK0 还是 CLK1,默认 CLK0)、HOLD(无有效输入时输出保持高/低电平,默认 YES)、SEL_TRIGGER(采样边沿 POS/NEG)、GSR(全局复位使能)。

手册给了 4 条硬性注意事项,逐条记下:

  1. 两路输入中任何一路为恒定高电平,GCLK 无法正常工作,必须强迫一路输入为低;
  2. 不建议 seln 和 cen 同时使能,可能导致模块无法正常工作;
  3. drct=2'b00(无毛刺模式)时,输入若是电平信号模块将无法工作——无毛刺模式不支持电平输入;
  4. drct=2'b11 时,若 seln 输入 2'b00,模块无法工作,输出未知。

常见坑:指望"无毛刺"模式一粒毛刺都没有

无毛刺模式只是保证切换点不输出残缺脉冲,代价是输出会丢失一个下降沿。对切换期间的频率连续性有要求的系统要把这个丢失的周期算进协议里。

区域时钟 MLCLK、SCLK、IOCLK

PH1A 的时钟网络是分层的,三种区域时钟原语各管一层:

原语角色输入来源输出去向
PH1_PHY_MLCLK_V2多区域时钟模块本地全局时钟输入管脚、本地 PLL 输出上下相邻两个时钟区域、IOCLK、LCLK
PH1_PHY_SCLK_V2GCLK 的分支时钟全局时钟网络内部逻辑资源和 IP 模块
PH1_PHY_IOCLKIO 列独立时钟网络本区域/相邻区域 MLCLK、本区域 PLL、全局时钟输入管脚本区域所有 IO 块,支持高速串并转换(如 LVDS 接收)

MLCLK 原语框图

SCLK 原语框图

IOCLK 原语框图

三者端口都极简(clkin、ce 可选、clkout)。参数方面:MLCLK_V2 有 BYPASS(输入直通输出)和 GSR;SCLK_V2 在 BYPASS/GSR 之外多一个 DELAY(0~3 级延迟),手册注明单独调节 SCLK 延迟需要与 PH1_LOGIC_BUFG 配合使用。HP IO 区域另有 PH1_PHY_HP_MLCLK 和 PH1_PHY_HP_IOCLK 变体,端口一致;其 MODE 参数(“HPS”/“HPD”)手册注明无实际用途,例化时可忽略

V2 与老版本的关系:MLCLK_V2、GCLK_V2 相比无 V2 版本均增加了 GSR(全局复位使能)参数;SCLK_V2 增加了延迟参数。

常见坑:时钟区域想跨就跨

IOCLK 只能驱动本区域的 IO 块,MLCLK 只能覆盖上下相邻两个时钟区域。布局约束前先想清楚时钟源和消费者在哪个区域,跨区域走时钟要靠 MLCLK 级联,不能想当然直连。

分频原语 LCLK 与 OSCDIV

LCLK:IO 分组上的外部时钟分频器

PH1_PHY_LCLK_V2 是 IO 上的外部时钟分频器,每个 IO 分组有 4 个,分频输出 clkdivout 可供全局时钟网使用,驱动逻辑资源和 IP 模块资源。

LCLK 原语框图

关键参数:

参数取值说明
DIV1~8, 35分频系数,支持 1-8 分频和 3.5 分频
LCLK”BYPASS”/“DIV2T08”/“DIV1”/“GND”clkout 输出模式:BYPASS 不分频直接输出;DIV2T08 输出 clkdivout;DIV1 与原时钟相同且占空比接近 50%;GND 输出低电平
CEMD”SYNC”/“ASYNC”SYNC 时 ce 信号延迟 4 个时钟周期传入内部 DFF
CLKSEL”ORG”/“INV”INV 表示输入时钟取反

手册特别提醒:想让 clkout 和分频输出一致时,DIV=1 要配 LCLK=“DIV1”,DIV=2~8 要配 LCLK=“DIV2TO8”,两个参数是联动的,只改一个必然出错。

OSCDIV:内部振荡器分频出”开机时钟”

PH1A 内部有一个 OSC 振荡器(中心频率 266MHz),PH1_PHY_OSCDIV 把它分频输出,不依赖任何外部时钟就能产生时钟——上电初始化逻辑、看门狗类电路的好帮手。

OSCDIV 原语框图

端口:rstn(低有效复位)、stdby(1 时暂停输出,0 时正常输出)、osc_clk。参数:DIV(1~128,默认 128)、EXT_RSTN

常见坑:把 OSC 时钟当高精度时钟用

内部 OSC 是 RC 振荡器,频率精度远低于晶振,266MHz 只是中心频率。它可以用来”让逻辑先跑起来”,但凡涉及协议波特率、采样率的场景必须用晶振+PLL。

PLL:倍频、分频、相移一把抓

PH1_PHY_PLL 是 FPGA 内部锁相环,功能:输出时钟频率调整、占空比调整、相位调整、动态相位移动,还支持小数分频和展频(SSC)。

PLL 原语框图

端口按功能分组看,不然 30 多个端口根本记不住:

分组端口说明
基本时钟refclk、fbclk、pllpd、pllreset、lock参考时钟、反馈时钟、电源开关(高电平关断)、复位(高有效)、锁定指示(高有效)
输出时钟clkc[7:0]、clkcb[7:0]、clkc_en[7:0]、clkc_rst[1:0]8 路输出及反相输出、使能、复位(clkc_rst[0] 管 03 路,[1] 管 46 路)
动态重配置drp_clk/rstn/sel/rd/wr/addr/wdata/rdy/err/rdata运行时改 PLL 配置的寄存器接口
动态相移psclk、psclksel[2:0]、psstep、psdown、psdone选择某路输出做相移,psstep 上升沿触发
展频ssc_en、ext_freq_mod_*SSC 使能(开启时固定接 1)与外部调制频率

参数更多达上百个,常用核心:REFCLK_DIV(1-128 输入分频)、FBCLK_DIV(1-128 反馈分频)、FRAC_ENABLE+SDM_FRAC(0-4095 小数分频系数)、PLL_FEED_TYPE(INTERNAL/EXTERNAL 反馈模式)、SSC_ENABLE/SSC_MODE(展频)、各路 CLKCn_ENABLE。带宽由 LPF_RES/LPF_CAP/ICP_CUR/GMC_GAIN 四个参数共同决定。

使用限制(手册原文要点):切断输入时钟时,PLL 的 VCO 无法完全关闭,会存在最低震荡频率,通道输出频率由每通道分频系数和具体芯片决定

常见坑:手写 PLL 例化参数

PLL 参数体系庞大,手册也支持 IP Generator 方式。除非必须用原语例化(如参数动态重配置场景),日常倍频分频需求建议走 TD 的 PLL IP 图形界面,频率计算和带宽参数由工具帮你算,不容易错。

运算原语速查:除法器、移位器、SLICE、乘法器

SEQ_DIV 软核除法器

PH1_LOGIC_SEQ_DIV 是软件集成的软核除法器,多周期握手协议:

PH1_LOGIC_SEQ_DIV #(
    .NUMER_WIDTH (16),
    .DENOM_WIDTH (16)
) u_SEQ_DIV (
    .clk      (clk),
    .rst      (rst),
    .start    (start),
    .numer    (numer),
    .denom    (denom),
    .quotient (quotient),
    .remain   (remain),
    .done     (done)
);

时序协议:rst=1 时 quotient/remain 清零、done 置 1;start=1 时输入缓存进内部寄存器,start 由 1 变 0 时才开始计算done=1 时 quotient/remain 才是最终结果。参数 NUMER_WIDTH/DENOM_WIDTH 均默认 16。手册提醒:start 为 0 期间改 numer/denom 不影响计算,但为了波形可读,请在 done=1 之后再给下一组输入

SHIFTER 移位寄存器

PH1_LOGIC_SHIFTER 支持固定/可变两种深度模式,但PH1A 器件只支持 “FIXED” 模式(“VARIABLE” 不可用):

PH1_LOGIC_SHIFTER #(
    .DATA_WIDTH  (16),
    .DEPTH_WIDTH (2),
    .SHIFT_TYPE  ("FIXED")
) u_SHIFTER (
    .clk     (clk),
    .en      (en),
    .datain  (datain),
    .depth   ({2{1'b0}}),
    .dataout (dataout)
);

FIXED 模式下 depth 端口无用,深度由 DATA_DEPTH 参数决定(默认 32)。深度换算有公式:16 位宽时最大深度 33,shift_depth = depth[4:0] + 2;8 位宽时最大深度 65,shift_depth = depth[5:0] + 2。还支持 INIT_FILE 预加载初始值。

SLICE:最底层的逻辑单元

PH1_LOGIC_SLICE 是 FPGA 内部 SLICE 模块的端口,内部含两个非独立的双 LUT5 和两个独立的 DFF,另有进位链(fci/fco)。参数 20 多个,核心是 LUTMODE(“LUT6”/“DLUT5”)、各 LUT 初始值 INIT_LUT5A/B、各种 MUX 选择。它支持原语例化、不支持 IP Generator

正常写 Verilog 时综合器会自动帮你映射 SLICE,不需要手动例化。需要手动例化的场景:要精确控制进位链、复用 LUT/寄存器输出等底层优化。手册给出了配置为 LUT6 输出的示例(寄存器输出 oqb + 组合输出 ofb 同时引出)。

MULT 乘法器与 DSP 家族速览

PH1_LOGIC_MULT 是 FPGA 内部乘法器(支持 IP Generator 的只有它,DSP 系列原语例外)。核心参数:

参数默认说明
INPUT_WIDTH_A/B18/18两个乘数位宽
OUTPUT_WIDTH36乘积位宽
INPUTFORMAT”SIGNED”有符号/无符号
INPUTREGA/B、OUTPUTREG”ENABLE”输入/输出寄存器,加寄存器输出延迟一拍
SRMODE”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")
) u_MULT (
    .p(p), .a(a), .b(b),
    .cea(cea), .ceb(ceb), .cepd(cepd), .clk(clk),
    .rstan(rstan), .rstbn(rstbn), .rstpdn(rstpdn)
);

注意三个复位都是低有效(rstan/rstbn/rstpdn)。此外 DSP 硬核还有更细粒度的原语族:PH1_PHY_DSPADD(27 位加减法)、PH1_PHY_DSPMULT(27×18 乘法)、PH1_PHY_DSPLOGIC(54 位逻辑运算)、PH1_PHY_DSPREG/DSPMREG(DSP 寄存器)、PH1_PHY_DSPTADD(54 位三输入加减法器,opctrl[3:0] 选择 x/y/z 的符号组合)——与 MULT 不同,DSP 家族同时支持原语例化和 IP Generator,属于流水线级拼装积木,竞赛里用 MULT 或让综合器推断即可。

通关标准:

  1. 能说出 BUFG 与 BUF 的区别,并解释为什么时钟和全局复位必须上 BUFG;
  2. 能照抄模板例化 SEQ_DIV,并描述 start/done 握手时序;
  3. 能解释 GCLK 无毛刺切换的代价(丢失一个下降沿)以及 LCLK 的 DIV 与 LCLK 参数联动规则。