一、什么是原语?

原语,英文名称primitive,是FPGA软件集成开发环境所提供的一系列底层逻辑功能单元。由于是底层逻辑功能单元,所以它们往往跟目标FPGA芯片以及芯片厂商紧密相关,因此不同厂商、不同器件的原语往往不能通用。当编译器对我们的HDL代码进行编译时,其中间环节的一些输出往往就是由原语组成的逻辑网表。因此,原语往往是不参与综合过程的,而使用原语描述的逻辑往往也不会被综合工具所优化。例如,Xilinx公司的ISE软件集成开发环境中的unisims库中定义了所有用于综合的原语,而simprims库中则定义了所有用于实现的原语。需要注意的是,在ISE安装目录下的verilog\src\unisims或verilog\src\simprims文件夹下去看这些原语的代码,可以发现其实这些并不是真正的原语,而是在原语的基础上又封装了一层,不过人们常常将它们也泛称为原语。

二、原语的使用

时钟相关原语

如果时钟信号不是由FPGA芯片的专用时钟pin(或pad)引入FPGA的,那么它通常就需要在FPGA内部被显式的连接到时钟树资源上,否则,直接使用这种不经过时钟树的时钟信号,会给FPGA设计的时序带来非常麻烦的问题,进而导致逻辑行为失败。

可是HDL代码仅仅描述功能,无法向编译器表达“希望将某一时钟信号连接到时钟树资源”这样的一层意思,那么此时,就需要使用类似BUFG这样的库里提供的底层模块来进行指示。例如:

// Verilog example
wire innerclk, gclk;BUFG onToGlobalClockTree(.I (innerclk),.O (gclk)
);always@(posedge gclk)
begin……
end

通过显式调用BUFG这样一个库中的底层模块,就可以告诉编译器,我们希望将innerclk信号引入全局时钟树,而其经过全局时钟树后的名字就改为gclk。后续HDL代码便可以放心的基于gclk编写逻辑。需要说明的是,直接从全局时钟pin(或pad)引入的时钟信号,对于xilinx的FPGA芯片来说,实际上是通过IBUFG+BUFG这样的组合直接连接到全局时钟树上的,只不过此时我们不需要显式例化这两个原语。

类似的时钟相关原语还有BUFR、BUFIO等,它们分别对应区域时钟树和IO时钟树资源,暂没看。。。

差分输入、输出原语

FPGA的接口具有单端和差分两种形式,同样,HDL代码只能描述功能,无法表达“某两个pin(或pad)脚互为一个差分对”这样的一层意思。那么此时,就需要使用类似IBUFDS、IBUFGDS、OBUFDS这样的库里提供的底层模块或原语来进行指示。

其中IBUFDS、和OBUFDS都是差分信号缓冲器,用于不同电平接口之间的缓冲和转换。IBUFDS 用于差分输入,OBUFDS用于差分输出。

  • IBUFDS是差分输入缓冲器,支持低压差分信号(如LVCMOS、LVDS等)。在IBUFDS中,一个电平接口用两个独特的电平接口(I和IB)表示。一个可以认为是主信号,另一个可以认为是从信号。
  • OBUFDS 是一个差分输出缓冲器,用于将来自 FPGA 内部逻辑的信号转换成差分信号输出,支持 TMDS、LVDS等电平标准。它的输出用O和OB两个独立接口表示。一个可以认为是主信号,另一个可以认为是从信号。

用法:

//------------------------------------------------------------------------
//--IBUFDS测试模块
//------------------------------------------------------------------------
//------------<模块及端口声明>----------------------------------------
module IBUFDS_test(input    clk     ,               //时钟,50Minput    rst_n   ,               //复位,低电平有效input  data_p  ,               //输入数据,差分+input data_n  ,               //输入数据,差分-output out
);
//------------<例化原语>----------------------------------------
IBUFDS #(.DIFF_TERM     ("FALSE") ,   // Differential Termination.IBUF_LOW_PWR    ("TRUE")  ,   // Low power="TRUE", Highest performance="FALSE" .IOSTANDARD      ("DEFAULT")       // 选择I/O电平标准,这里选择默认
)
IBUFDS_inst (.O             (out)       ,   // 输出.I             (data_p)    ,   // 差分输入+(需要直接连接到顶层端口).IB               (data_n)        // 差分输入-(需要直接连接到顶层端口)
);endmodule
//------------------------------------------------------------------------
//--OBUFDS测试模块
//------------------------------------------------------------------------
//------------<模块及端口声明>----------------------------------------
module OBUFDS_test(input    clk     ,       //时钟,50Minput    rst_n   ,       //复位,低电平有效input  data    ,       //输入数据output    out_p   ,       //输出数据,差分+output    out_n           //输出数据,差分-
);
//------------<例化原语>----------------------------------------
OBUFDS #(.IOSTANDARD        ("DEFAULT")   ,   // 选择I/O电平标准,这里选择默认.SLEW         ("SLOW")      // 选择输出速率,这里选择SLOW
)
OBUFDS_inst (.O             (out_p)     ,   // 差分输出+(需要直接连接到顶层端口).OB               (out_n)     ,   // 差分输出-(需要直接连接到顶层端口).I             (data)          // 输入
);endmodule

接口相关原语

当需要使用接口资源中的寄存器来实现高速数据采集时,如果直接调用相关的原语,编译器便会利用接口资源中的寄存器来做事情。例如,使用ODDR、IDDR、IDDR2CLK、ISERDES、OSERDES等原语后,编译器便会利用接口资源的寄存器来实现相关接口功能,这样便能达到比较高的性能。例如:

// Verilog example
ISERDES_NODELAY #(.BITSLIP_ENABLE("FALSE"),  // "TRUE"/"FALSE" to enable bitslip controller // Must be "FALSE" if INTERFACE_TYPE set to "MEMORY" .DATA_RATE("DDR"),  // Specify data rate of "DDR" or "SDR" .DATA_WIDTH(4),     // Specify data width - // NETWORKING SDR: 2, 3, 4, 5, 6, 7, 8 : DDR 4, 6, 8, 10// MEMORY SDR N/A : DDR 4.INTERFACE_TYPE("MEMORY"), // Use model - "MEMORY" or "NETWORKING" .NUM_CE(2),             // Number of clock enables used, 1 or 2.SERDES_MODE("MASTER") // Set SERDES mode to "MASTER" or "SLAVE"
) is0 (.Q1(data0Line[0]),      // 1-bit registered SERDES output.Q2(data0Line[1]),      // 1-bit registered SERDES output.Q3(data0Line[2]),      // 1-bit registered SERDES output.Q4(data0Line[3]),      // 1-bit registered SERDES output.Q5(data0Line[4]),      // 1-bit registered SERDES output.Q6(data0Line[5]),      // 1-bit registered SERDES output.SHIFTOUT1(open),   // 1-bit cascade Master/Slave output.SHIFTOUT2(open),   // 1-bit cascade Master/Slave output.BITSLIP(1'b0),         // 1-bit Bitslip enable input.CE1(1'b1),             // 1-bit clock enable input.CE2(1'b1),             // 1-bit clock enable input.CLK(clkFast),          // 1-bit master clock input.CLKB(clkFastInvert),   // 1-bit secondary clock input for DATA_RATE=DDR.CLKDIV(clkSlow),       // 1-bit divided clock input.D(din),                // 1-bit data input, connects to IODELAY or input buffer.OCLK('0'),             // 1-bit fast output clock input.RST(rst),             // 1-bit asynchronous reset input.SHIFTIN1(1'b0),    // 1-bit cascade Master/Slave input.SHIFTIN2(1'b0)     // 1-bit cascade Master/Slave input
);

使用上述原语后,编译器便会利用接口资源中的寄存器实现一个针对输入接口的高性能1:6串并转换器。当然了,为了保证串并处理的成功,仅仅使用ISERDES原语还远远不够,时钟信号也必须按照要求来处理,具体的要求大家可以去查阅Xilinx公司相应器件的用户手册。

三、用原语标识IP核的好处

其实,FPGA软件集成开发环境中提供的IP核基本上都具有原语的表示形式。相比于调用IP核智能生成器对IP核进行配置、生成、例化等一系列过程,直接通过原语调用显得要简便得多,当然了,前提是你要对IP核的各个属性和参数配置比较熟悉。尤其是碰到版本升级或者整体细微修改这样的情况,如果采用在HDL中调用原语的方式,将会使修改的工作量大大降低。

// Verilog example
BUFG BUFG_COut0(.I (pllClkOut0), .O (clkOut0));
BUFG BUFG_FB(.I (feedBack), .O (feedBackG));
PLL_ADV #(.BANDWIDTH("OPTIMIZED"),        // "HIGH", "LOW" or "OPTIMIZED" .CLKFBOUT_MULT(7),          // Multiplication factor for all output clocks.CLKFBOUT_PHASE(0.0),       // Phase shift (degrees) of all output clocks.CLKIN1_PERIOD(16.67),          // Clock period (ns) of input clock on CLKIN1.CLKIN2_PERIOD(10.00),          // Clock period (ns) of input clock on CLKIN2.CLKOUT0_DIVIDE(1),         // Division factor for CLKOUT0 (1 to 128).CLKOUT0_DUTY_CYCLE(0.5),   // Duty cycle for CLKOUT0 (0.01 to 0.99).CLKOUT0_PHASE(45.0),       // Phase shift (degrees) for CLKOUT0 (0.0 to 360.0).CLKOUT1_DIVIDE(1),         // Division factor for CLKOUT1 (1 to 128).CLKOUT1_DUTY_CYCLE(0.5),   // Duty cycle for CLKOUT1 (0.01 to 0.99).CLKOUT1_PHASE(0.0),        // Phase shift (degrees) for CLKOUT1 (0.0 to 360.0).CLKOUT2_DIVIDE(1),         // Division factor for CLKOUT2 (1 to 128).CLKOUT2_DUTY_CYCLE(0.5),   // Duty cycle for CLKOUT2 (0.01 to 0.99).CLKOUT2_PHASE(0.0),        // Phase shift (degrees) for CLKOUT2 (0.0 to 360.0).CLKOUT3_DIVIDE(1),         // Division factor for CLKOUT3 (1 to 128).CLKOUT3_DUTY_CYCLE(0.5),   // Duty cycle for CLKOUT3 (0.01 to 0.99).CLKOUT3_PHASE(0.0),        // Phase shift (degrees) for CLKOUT3 (0.0 to 360.0).CLKOUT4_DIVIDE(1),         // Division factor for CLKOUT4 (1 to 128).CLKOUT4_DUTY_CYCLE(0.5),   // Duty cycle for CLKOUT4 (0.01 to 0.99).CLKOUT4_PHASE(0.0),        // Phase shift (degrees) for CLKOUT4 (0.0 to 360.0).CLKOUT5_DIVIDE(1),         // Division factor for CLKOUT5 (1 to 128).CLKOUT5_DUTY_CYCLE(0.5),   // Duty cycle for CLKOUT5 (0.01 to 0.99).CLKOUT5_PHASE(0.0),        // Phase shift (degrees) for CLKOUT5 (0.0 to 360.0).COMPENSATION("SYSTEM_SYNCHRONOUS"), // "SYSTEM_SYNCHRONOUS", // "SOURCE_SYNCHRONOUS", "INTERNAL", // "EXTERNAL", "DCM2PLL", "PLL2DCM" .DIVCLK_DIVIDE(1),              // Division factor for all clocks (1 to 52).EN_REL("FALSE"),               // Enable release (PMCD mode only).PLL_PMCD_MODE("FALSE"),    // PMCD Mode, TRUE/FASLE.REF_JITTER(0.100),             // Input reference jitter (0.000 to 0.999 UI%).RST_DEASSERT_CLK("CLKIN1")     // In PMCD mode, clock to synchronize RST release
) PLL_ADV_inst (.CLKFBDCM(open),            // Output feedback signal used when PLL feeds a DCM.CLKFBOUT(feedBack),      // General output feedback signal.CLKOUT0(pllClkOut0),       // One of six general clock output signals.CLKOUT1(open),         // One of six general clock output signals.CLKOUT2(open),         // One of six general clock output signals.CLKOUT3(open),         // One of six general clock output signals.CLKOUT4(open),         // One of six general clock output signals.CLKOUT5(open),         // One of six general clock output signals.CLKOUTDCM0(open),          // One of six clock outputs to connect to the DCM.CLKOUTDCM1(open),          // One of six clock outputs to connect to the DCM.CLKOUTDCM2(open),          // One of six clock outputs to connect to the DCM.CLKOUTDCM3(open),          // One of six clock outputs to connect to the DCM.CLKOUTDCM4(open),          // One of six clock outputs to connect to the DCM.CLKOUTDCM5(open),          // One of six clock outputs to connect to the DCM.DO(open),                  // Dynamic reconfig data output (16-bits).DRDY(open),                // Dynamic reconfig ready output.LOCKED(locked),          // Active high PLL lock signal.CLKFBIN(feedBackG),        // Clock feedback input.CLKIN1(clkIn),             // Primary clock input.CLKIN2(1'b0),              // Secondary clock input.CLKINSEL(1'b1),            // Selects '1' = CLKIN1, '0' = CLKIN2.DADDR(5'b0),               // Dynamic reconfig address input (5-bits).DCLK(1'b0),              // Dynamic reconfig clock input.DEN(1'b0),                 // Dynamic reconfig enable input.DI(16'b0),                 // Dynamic reconfig data input (16-bits).DWE(1'b0),             // Dynamic reconfig write enable input.REL(1'b0),                 // Clock release input (PMCD mode only).RST(rst)                   // Asynchronous PLL reset
);

如果需要将锁相环的倍频系数改为5的话,直接修改CLKFBOUT_MULT属性的值即可。

UDP 简介

英文全称为User Defined Primitive,是用户自定义原语的意思。

语法:

primitive <primitive_name>(<output_port_name>, <input_port_name_list>);<输出端口类型说明>;<输入端口类型说明>;<输出端寄存器变量说明>;<原语初始状态说明>;
table<table element 1>;<table element 2>;……<table element n>;
endtableendprimitive

table的内容其实就是该原语的真值表。每个UDP只能有一个输出最多有10个输入,但尽量控制在5个以内,否则table将会巨大无比;端口只能是标量,不能是向量,即均为1bit宽的;不支持高阻(z)逻辑;不能被综合等等。

Xilinx原语的使用相关推荐

  1. Xilinx 原语简介--(Xilinx FPGA开发实用教程)

    目录 前言 1.Xilinx 原语简介 1.1 时钟组件原语(Clock Components) 1.1.1 BUFG 1.1.2 BUFGMUX 1.2 I/O端口组件(IO Components) ...

  2. Xilinx原语使用方法

    目录 简介 1. 时钟组件 IBUFG IBUFGDS BUFG 简介 原语(Primitive),是Xilinx针对其器件特征开发的一系列常用模块的名字,用户可以将其看成Xilinx公司为用户提供的 ...

  3. Xilinx原语的用法

    Xilinx公司原语的使用方法 原语,其英文名字为Primitive,是Xilinx针对其器件特征开发的一系列常用模块的名字,用户可以将其看成Xilinx公司为用户提供的库函数,类似于C++中的&qu ...

  4. 【XINLIX 原语】XILINX 原语的使用之 IBUFDS 差分转单端、OBUFDS 单端转差分

    目录 IBUFGDS IBUFDS 介绍 IBUFDS 示意图 例化方式 OBUFDS OBUFDS 介绍 OBUFDS 示意图 例化方式 在 XILINX 中有许多原语,常见的差分转单端 IBUFD ...

  5. Xilinx原语ODDR的使用

    ODDR is Xilinx HDL Language Template. ODDR:Output Double Data Rate(DDR) . 在介绍ODDR之前,我们先简单了解一下OLOGIC. ...

  6. XILINX FPGA 7系之 Distribute RAM

    XILINX FPGA 7系之 CLB/LUT 可以知道 CLB 是基本的组成单元,SLICE 也是 CLB 的基本组成单元,为了更好的使用 XILINX FPGA ,有必要在深挖一下 Distrib ...

  7. Xilinx FPGA平台GTX简易使用教程(五)GTX收发测试及示例工程介绍

    GTX IP配置完了,你不得搞个回环测试一番? 汇总篇: Xilinx FPGA平台GTX简易使用教程(汇总篇) 目录 前言 一.示例工程Example Design 1.1 gtx_support模 ...

  8. vcs编译vivado原语:

    使用vcs+verdi问题较少: 使用vlogan+vcs+verdi三步编译: vlogan: vlogan -V -sverilgo -ignore unique_checks +libext+. ...

  9. FPGA设计实用分享02之XILINX的可参数化FIFO

    一.背景 FIFO是FPGA项目中使用最多的IP核,一个项目使用几个,甚至是几十个FIFO都是很正常的.通常情况下,每个FIFO的参数,特别是位宽和深度,是不同的. 明德扬(MDY)在2021年承担了 ...

最新文章

  1. 知识点小记之转义字符
  2. laravel 5.1 Model 属性详解
  3. 【SICP练习】3 练习1.7
  4. spring 注释_Spring核心注释
  5. .net数据绑定控件中的数据导出到Excel
  6. 网络通信 public ip 和 private ip
  7. Unity C#笔记 委托事件
  8. word电子签名工具_电子签名是您不会想到的必备工具的5个理由
  9. 2010计算机系助学金,计算机系贫困生助学金申请书
  10. Unity3D中MonoDevelop无法使用
  11. 四维空间的二维线框投影可视化(附matlab代码)
  12. IKVM.NET的妙手偶得
  13. 温控中使用PID控制算法
  14. 菜鸟也能飞:SQL数据库实战专业教程(二)
  15. Linux系统之进入单用户模式的方法及相关作用
  16. python 英语分词是什么意思_英语里面现在分词是什么意思
  17. Ubuntu22.04安装、配置、美化、软件安装、配置开发环境
  18. android studio 正式版本
  19. jupyter notebook占用内存空间过大打不开的解决办法(包括但不限于爬虫造成的)
  20. Zabbix学习小结-----介绍

热门文章

  1. 原生jq下载文件的方式
  2. promise和回调函数 js
  3. phpword 利用phpword将信息导出成word文档进行下载
  4. 什么都不会的宝妈,怎么做自媒体赚钱?
  5. gatling 之性能测试
  6. 手机充电线接头处容易断裂怎么办?
  7. 下拉 html 实现原理,百度搜索下拉框实现技术原理分析
  8. CCF- CSP 201912-2回收站选址 巧用STL实现O(n)时间复杂度 满分题解
  9. 全国天气预报信息数据 API
  10. GoLang之iface 和 eface 的区别是什么?