【FPGA】Xilinx原语

Xilinx公司原语的使用方法,学习一点记录一点

目录

1 计算组件

1.1 累加器示例

1.2 预加/乘法/加法示例

1.3 减法器示例

2 时钟组件

2.1 BUFG

2.2 BUFMUX

2.3 BUFIO

2.4 BUFR

2.5 DCM_BASE

3 配置和检测组件

3.1 BSCAN_VIRTEX4

4 吉比特收发器组件

5 I/O端口组件

5.1 BUFIO

5.2 IBUFDS

5.3 IDELAY

5.4 OBUFDS

5.5 IOBUF

5.6 PULLDOWN/PULLUP

6 处理器组件

7 RAM/ROM 组件

7.1 RAM16X1S

7.2  RAMB16

8 寄存器和锁存器

8.1 FDCPE 原语

 9 移位寄存器组件

9.1  SRL16

10 Slice/CLB 组件

10.1  LUT1

10.2 MUXF7

本章小结


原语,其英文名字为Primitive,是Xilinx针对其器件特征开发的一系列常用模块的名字。用户可以将其看成Xilinx公司为用户提供的库函数,类似于C++中的“cout”等关键字。

Xilinx公司提供的原语,涵盖了FPGA开发的常用领域,但只有相应配置的硬件才能执行相应的原语,并不是所有的原语都可以在任何一款芯片上运行。在Verilog中使用原语非常简单,将其作为模块名直接例化即可。

 本节以Virtex平台介绍各类原语,因为该系列的原语类型是最全面的。其它系列芯片原语的使用方法是类似的。 Xilinx公司的原语按照功能分为10类,包括:

  1. 计算组件
  2. I/O端口组件
  3. 寄存器/锁存器
  4. 时钟组件
  5. 处理器组件
  6. 移位寄存器
  7. 配置和检测组件
  8. RAM/ROM组件
  9. Slice/CLB组件
  10. G比特收发器组件

下面分别对其进行详细介绍。 在Vivado 中可以打开所有支持的原语,位置如下:Tools->Language Templates

1 计算组件

计算组件就是DSP48核,也有人将其称为硬件乘法器,功能描述如表1所示。

表1 计算组件清单

DSP48 其结构为一个18*18比特的有符号乘法器,且在后面还级联了一个带有可配置流水线的3输入加法器。DSP48核由一个18比特的乘法后面级联一个48比特的加法器,乘法器和加法器的应用位宽分别可以在18、48比特内任意调整。其在乘加模块中有广泛应用,特别是各类滤波器系统中,不仅可以提高系统稳定性,还能够节省逻辑资源且工作在高速模式下。其在Verilog中的例化模版为:


//   DSP48E1   : In order to incorporate this function into the design,
//   Verilog   : the following instance declaration needs to be placed
//  instance   : in the body of the design code.  The instance name
// declaration : (DSP48E1_inst) and/or the port declarations within the
//    code     : parenthesis may be changed to properly reference and
//             : connect this function to the design.  All inputs
//             : and outputs must be connected.

//  <-----Cut code below this line---->

   // DSP48E1: 48-bit Multi-Functional Arithmetic Block
   //          Artix-7
   // Xilinx HDL Language Template, version 2018.2

   DSP48E1 #(
      // Feature Control Attributes: Data Path Selection
      .A_INPUT("DIRECT"),               // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
      .B_INPUT("DIRECT"),               // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
      .USE_DPORT("FALSE"),              // Select D port usage (TRUE or FALSE)
      .USE_MULT("MULTIPLY"),            // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
      .USE_SIMD("ONE48"),               // SIMD selection ("ONE48", "TWO24", "FOUR12")
      // Pattern Detector Attributes: Pattern Detection Configuration
      .AUTORESET_PATDET("NO_RESET"),    // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH" 
      .MASK(48'h3fffffffffff),          // 48-bit mask value for pattern detect (1=ignore)
      .PATTERN(48'h000000000000),       // 48-bit pattern match for pattern detect
      .SEL_MASK("MASK"),                // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2" 
      .SEL_PATTERN("PATTERN"),          // Select pattern value ("PATTERN" or "C")
      .USE_PATTERN_DETECT("NO_PATDET"), // Enable pattern detect ("PATDET" or "NO_PATDET")
      // Register Control Attributes: Pipeline Register Configuration
      .ACASCREG(1),                     // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
      .ADREG(1),                        // Number of pipeline stages for pre-adder (0 or 1)
      .ALUMODEREG(1),                   // Number of pipeline stages for ALUMODE (0 or 1)
      .AREG(1),                         // Number of pipeline stages for A (0, 1 or 2)
      .BCASCREG(1),                     // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
      .BREG(1),                         // Number of pipeline stages for B (0, 1 or 2)
      .CARRYINREG(1),                   // Number of pipeline stages for CARRYIN (0 or 1)
      .CARRYINSELREG(1),                // Number of pipeline stages for CARRYINSEL (0 or 1)
      .CREG(1),                         // Number of pipeline stages for C (0 or 1)
      .DREG(1),                         // Number of pipeline stages for D (0 or 1)
      .INMODEREG(1),                    // Number of pipeline stages for INMODE (0 or 1)
      .MREG(1),                         // Number of multiplier pipeline stages (0 or 1)
      .OPMODEREG(1),                    // Number of pipeline stages for OPMODE (0 or 1)
      .PREG(1)                          // Number of pipeline stages for P (0 or 1)
   )
   DSP48E1_inst (
      // Cascade: 30-bit (each) output: Cascade Ports
      .ACOUT(ACOUT),                   // 30-bit output: A port cascade output
      .BCOUT(BCOUT),                   // 18-bit output: B port cascade output
      .CARRYCASCOUT(CARRYCASCOUT),     // 1-bit output: Cascade carry output
      .MULTSIGNOUT(MULTSIGNOUT),       // 1-bit output: Multiplier sign cascade output
      .PCOUT(PCOUT),                   // 48-bit output: Cascade output
      // Control: 1-bit (each) output: Control Inputs/Status Bits
      .OVERFLOW(OVERFLOW),             // 1-bit output: Overflow in add/acc output
      .PATTERNBDETECT(PATTERNBDETECT), // 1-bit output: Pattern bar detect output
      .PATTERNDETECT(PATTERNDETECT),   // 1-bit output: Pattern detect output
      .UNDERFLOW(UNDERFLOW),           // 1-bit output: Underflow in add/acc output
      // Data: 4-bit (each) output: Data Ports
      .CARRYOUT(CARRYOUT),             // 4-bit output: Carry output
      .P(P),                           // 48-bit output: Primary data output
      // Cascade: 30-bit (each) input: Cascade Ports
      .ACIN(ACIN),                     // 30-bit input: A cascade data input
      .BCIN(BCIN),                     // 18-bit input: B cascade input
      .CARRYCASCIN(CARRYCASCIN),       // 1-bit input: Cascade carry input
      .MULTSIGNIN(MULTSIGNIN),         // 1-bit input: Multiplier sign input
      .PCIN(PCIN),                     // 48-bit input: P cascade input
      // Control: 4-bit (each) input: Control Inputs/Status Bits
      .ALUMODE(ALUMODE),               // 4-bit input: ALU control input
      .CARRYINSEL(CARRYINSEL),         // 3-bit input: Carry select input
      .CLK(CLK),                       // 1-bit input: Clock input
      .INMODE(INMODE),                 // 5-bit input: INMODE control input
      .OPMODE(OPMODE),                 // 7-bit input: Operation mode input
      // Data: 30-bit (each) input: Data Ports
      .A(A),                           // 30-bit input: A data input
      .B(B),                           // 18-bit input: B data input
      .C(C),                           // 48-bit input: C data input
      .CARRYIN(CARRYIN),               // 1-bit input: Carry input signal
      .D(D),                           // 25-bit input: D data input
      // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
      .CEA1(CEA1),                     // 1-bit input: Clock enable input for 1st stage AREG
      .CEA2(CEA2),                     // 1-bit input: Clock enable input for 2nd stage AREG
      .CEAD(CEAD),                     // 1-bit input: Clock enable input for ADREG
      .CEALUMODE(CEALUMODE),           // 1-bit input: Clock enable input for ALUMODE
      .CEB1(CEB1),                     // 1-bit input: Clock enable input for 1st stage BREG
      .CEB2(CEB2),                     // 1-bit input: Clock enable input for 2nd stage BREG
      .CEC(CEC),                       // 1-bit input: Clock enable input for CREG
      .CECARRYIN(CECARRYIN),           // 1-bit input: Clock enable input for CARRYINREG
      .CECTRL(CECTRL),                 // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
      .CED(CED),                       // 1-bit input: Clock enable input for DREG
      .CEINMODE(CEINMODE),             // 1-bit input: Clock enable input for INMODEREG
      .CEM(CEM),                       // 1-bit input: Clock enable input for MREG
      .CEP(CEP),                       // 1-bit input: Clock enable input for PREG
      .RSTA(RSTA),                     // 1-bit input: Reset input for AREG
      .RSTALLCARRYIN(RSTALLCARRYIN),   // 1-bit input: Reset input for CARRYINREG
      .RSTALUMODE(RSTALUMODE),         // 1-bit input: Reset input for ALUMODEREG
      .RSTB(RSTB),                     // 1-bit input: Reset input for BREG
      .RSTC(RSTC),                     // 1-bit input: Reset input for CREG
      .RSTCTRL(RSTCTRL),               // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
      .RSTD(RSTD),                     // 1-bit input: Reset input for DREG and ADREG
      .RSTINMODE(RSTINMODE),           // 1-bit input: Reset input for INMODEREG
      .RSTM(RSTM),                     // 1-bit input: Reset input for MREG
      .RSTP(RSTP)                      // 1-bit input: Reset input for PREG
   );

   // End of DSP48E1_inst instantiation
				
			

  • 寄存器,相信大家都很熟悉。在DSP48E1中它主要是用来做流水线操作,来提高DSP48E1整体的运行性能。
  • 框1是一个预加器(加法器),它主要实现的是A(最大位宽30)与D(最大位宽是25)的相加,做预加的话它输出的结果最大位宽为25,该预加器不用的时候可以旁路掉。
  • 框2是一个25x18乘法器,它的两个乘数分别为B(最大位宽18位),以及A与D相加后结果的低25位,输出的结果为48(高5位是符号拓展位,低43位是数据位),该乘法器不用的时候可以旁路掉。
  • 框3是一个的功能比较多。它能做加(减)法器,累加(减)法器,逻辑运算(与或非),它的输出最大位宽为48位数据位+4位进位。
  • 框4是一个模式探测器,它的主要实现带掩膜的数据比较,上下溢出检测,计到一定数对结果进行重置功能。
  • 框5是一个数据选择器,它的两个数据输入端分别为C和P(最大位宽48),因此DSP48E1做普通加法还是做累加就取决于它了。当然真实的DSP48E1里面有很多数据选择器,它们与DSP48E1所实现的功能密切相关。 

图 DSP48E单元的结构示意图

  1. 25×18乘法器;
  2. 30位宽的A端口入。其中低25位输人列乘法尜,而整个30位成为内部48位宽总线的高30位.该48位总线由A和B两个端口的输入拼接而成;
  3. 线联的A和B输入端口。在直接输入和级联输入之间可进行半独立可选的流水线操作;可支持独立时钟的两线A和B输入寄存器组。
  4. 独立的C输人端口,C端口有存器有独立的复位和时钟使能.
  5. CARRYCASCIN和CARYCASCOUT内部级联信号支持用两个DSP48E单元实现累加器/加法器/减法器。
  6. MULTSIGNIN和MULTSIGNOUT内部级联信号用特定的OPMODE设置支持96位MACC扩展。
  7. 在不使用第1级乘法器时SIMD模式支持3输入加法/减法。双24位SIMD加法/减法/累加,使用2个独立的CARRYOUT信号。四12位SIMD加法/减法/累加,使用4个独立的CARRYOUT信号。
  8. 48位逻辑单元。按位逻辑运算,两输入AND、OR、NOT、NAND、NOR、XOR和XNOR。  过ALUMODE可动态选择逻辑单元模式。
  9. 特定数值检测。支持溢出/下溢;支持收敛舍入;计数终止检测及自动复位。
  10. 级联48位P总线支持内部低功耗加法器级联位及允许四12位或双24位SIMD加法器级联。
  11. 可选的17位右移结构可实现更宽乘法器。
  12. 动态可控运算模式,7位OPMODE控制总线提供X、Y和Z多路选择器选择信号。
  13. 进位输入给第2级加法器。支持舍入;支持更宽加/减法;3位CARRYINSEL多路选择器。
  14. 进位输出给第2级加法器。支持更宽加/减法;每个SIMD加法器可用(多至4个);级联的CARRYCASCOUT和MULTSIGNOUT允许MACC扩展至96位。
  15. 可选择的输入、流水和输出/累加寄存器。
  16. 可选择的控制寄存器。
  17. 独立的时钟使能和复位,提供更大的灵活性。
  18. 为节省功耗,当内部乘法器不用时,可用USE_MULT属性关闭内部乘法器逻辑。

每个DSP48E单元包括一个2输入乘法器,其后是多路选择器和3输入加法器/减法器/累加器。DSP48E的乘法器有非对称输入结构,支持18×25的二进制补码乘法。该乘法器以两个部分积的形式产生一个43位的二进制补码结果,该部分积经由X和Y多路复用器符号扩展为48位,然后输入后级的三输入加法器。这样当使用乘法器时,该加法器有效地变为二输入的加法器。

第2级的加法器/减法器在前级乘法器不用时可接受3个48位的二进制补码操作数,产生一个48位的二进制补码结果。设置USE MULT属性为NONE,配合适当的OPMODE设置可不使用乘法器。在SIMD模式下,48位加法器/减法器也支持带CARRYOUT位的双24位或四12位SIMD算术运算。在该模式下通过动态的ALUMODE控制信号,2输入的48位位逻辑运算也可支持。

更高级的DSP功能可以通过级联同一列中的DSP48E单元来实现,两个数据路径(ACOUTand BCOUT)和DSP48E的输出(PCOUT、MULTSIGNOUT和CARRYCASCOUT)提供了这种级联的能力。例如,FIR滤波器设计可以用级联的输入来安排一系列的输入数据采样,采用级联输出来安排一系列的部分输出结果。由于这种级联不使用普通逻辑的走线,所以是一种高性能低功耗的DSP滤波器实现方式。

C输入端口可以形成多组3输入算术功能,如3输入加法、带单个加法的二输入乘法。另一个有价值的功能是支持对称舍入的“逼进零”或“逼进无限”的乘法操作,C输入端口和特定数值检测器一起也支持收敛舍入。

对于多精度算术运算,DSP48E提供17位右移功能。这样DSP48E产生的一个部分积可以右移调整后在相邻的DSP48E中和下一部分积相加,采用该技术DSP48E可于构建更大的乘法器。

对于输入操作数、中间乘积和累加器输出的可编程流水处理增加了DSP处理的数据吞吐能力,48位的内部总线(PCOUT/PCIN)允许在同一列的DSP48E单元级联。当不同列的DSP48E需要连接时,则需要利用普通逻辑资源。

数值检测器位于DSP48E的后端,可支持收敛舍入、溢出/下溢及累加器的终值检测(计数器自动复位),数值检测器也支持在某些位忽略下检测DSP48E输出的特定数值。


通过讲解DSP48E1 Marco这个神奇的IP(图3,直接在IP Catalog中搜索就有),再结合具有代表性的实例,一步步的去挖掘DSP48E1中的内容。

在这里插入图片描述

数据输入线:P A B D C PCIN;模式控制线:OPMODE 、ALUMODE、CARRYINSEL,当然还要注意一下INMODE这个控制信号。

对于DSP48E1 Marco的IP core,需要知道接口A、B、C、D、P的输入输出关系,同时需要了解端口位宽限制。举个例子,乘法因子在精度允许的范围内可选20-30位,你用25位最后只用了1个DSP48E1,但如果你用了30位最后就用到2个DSP48E1,使得多出来的DSP48E1利用率低下,造成浪费。在DSP48E1 Marco的IP core中,当我们在Instruction中输好表达式后(图4),即可到Implements中看相应输入输出位宽的限制(图5)。注意:图5中的CONCAT是将预加器旁路,将A和B拼起来所组成组成一个48位的数,所以使用CONCAT的时候,A、B、D是无效的。

输入表达式(A+D)*B

接下来我们使用DSP48E1 Marco 这个IP来看几个较为经典的表达式样例以及它的路径。这里流水线我们将他设为自动,让IP 生成工具自动给我们插寄存器就好。当然如果你的数据是跨时钟输入的,你可以选择使用DSP内部的寄存器来减少CLB中寄存器的使用。如果对延迟比较敏感的情况,还可以适当减少寄存器的使用,但是一定要确保每条相关路径上的寄存器数保持一致。

1.1 累加器示例

环回累加器P<=C+P

示例说明:C输入后打了3拍与P相加,相加的结果打1拍再输出到P。

1.2 预加/乘法/加法示例

预加,乘法,加法相关:P= (A+D)*B+C

示例说明:A、D打1拍后进行相加,相加后的结果打1拍与B打2拍的结果相乘。相乘后的结果再与C打3拍后的结果相加,相加的结果打1拍再输出到P。

1.3 减法器示例

如果用CLB做加减法,如前面与进位链相关的章节讲到,最低位的进位CIN必须设为1/0。

当用DSP48E1做加减法时,当我们把ALUMODE[1:0]设置为2’00时,Y设为0时我们可以做加法A+B。当我们把ALUMODE[1:0]设置为2’01时,Y设为1时我们可以做减法A-B。此时CIN可以单独拿出来使用,不必强制设为0/1(当然我们也可以用CIN来代替Y的作用)。

此外一个DSP48E1除了能做1个48位与48位加法/减法/逻辑操作(ONE48),还能被用来做2个24位与24位加法(TWO24),4个12位与12位加法(FOUR12,如图10所示)。这些加法的结果都是带进位的,对应的进位关系如图所示。

举个例子:我们可以将A:B拼成48位的CONCAT,与48位的C作为三输入就可以做4个12位与12位的加法/减法/逻辑操作。当然这里的CONCAT、C切成4等份。[47:36],[35:24],[23,12],[11,0]。

  • 当ONE48时,CARRYOUY[3] 为相应的进位结果。
  • 当ONE24时,CARRYOUY[3]、CARRYOUY[1] 为 相应的进位结果。
  • 当ONE12时,CARRYOUY[3] 、CARRYOUY[2] 、CARRYOUY[1] 、CARRYOUY[0]为相应的进位结果。

最后DSP48E1的PATTERN DETECT(模式检测)还是很值的一提的。它的结构如图所示。

图示:PATTERN DECTECT的结构

它的输入主要为PATTERN ,MASK,DATA(经常用的PATTERN和MASK我已经用红框给圈起来了)。DATA为进行DSP48E1运算后未打拍的结果。当我们使用PATTERN DETECT的时候输出要打一拍,这样PATTERNDECT和PATTERNBDECTECT的结果才能和输出P对的上。

  • PATTERN 是用来匹配的样式。当DATA与PATTERN 相同的时候,PATTERNDECT为1,否则为0。当DATA与PATTERN 的反码相同时,PATTENBDETECT为1,否则为0。PATTERN可以由DSP48E1的C打拍后作为输入,也可以选择“参数PATTERN”作为输入(这里的“参数PATTERN” 为PATTERN的其中一个可选输入,注意区分两者关系)。
  • MASK 是掩模,是上下溢出探测最为关键参数。它对应的DATA的每一位。MASK[0] ->DATA[0]...MASK[47] ->DATA[47]。当将MASK的某一位设为1时,它将忽略PATTERN对应位的结果,再将DATA和PATTERN进行比较。MASK可以由DSP48E1的C打拍后作为输入,也可以选择“参数MASK”作为输入,(这里的“参数MASK” 为MASK的其中一个可选输入,注意区分两者关系)。
  • PATTERNBDECTPAST和PATTERNDECTPAST 分别为PATTERNBDECT和PATTERNDECT打一拍的输出结果。

为什么说MASK是上下溢出最为关键的参数呢?我们看一下PATTERN DETECT上下溢出检测的逻辑结构(图13)。很显然overflow是用来检测PATTERNDECT的下降沿的,underflow是用来检测PATTERNBDECT的下降沿的。

图13:PATTERN DETECT上下溢出的逻辑结构

当MASK={44'b0,4'b1111} ,当DATA>5'b01111(15)时就会上溢出,当DATA<5'b10000(-16)就会产生下溢出。

因为overflow的实质就是检测DATA的高44位(符号拓展位)是不是为全0,15+1=16(5'b10000),高44位就不为全0啦,上溢出。

underflow的实质就是检测DATA的高44位(符号拓展位)是不是全1(因为PATTERNBDECT检测的是反码哦,所以检测的是1),-16-1=-17(6'b101111),高44位不为全1,下溢出。

2 时钟组件

时钟组件包括各种全局时钟缓冲器、全局时钟复用器、普通I/O本地的时钟缓冲器以及高级数字时钟管理模块,如表3-7所示。

表3-7 时钟组件的清单

下面对几个常用时钟组件进行简单介绍,其余组件的使用方法是类似的。

2.1 BUFG

BUFG是具有高扇出的全局时钟缓冲器,一般由综合器自动推断并使用,其和同类原语的RTL结构如图3-28所示。全局时钟是具有高扇出驱动能力的缓冲器,可以将信号连到时钟抖动可以忽略不计的全局时钟网络,BUFG组件还可应用于典型的高扇出信号和网络,如复位信号和时钟使能信号。如果要对全局时钟实现PLL或DCM等时钟管理,则需要手动例化该缓冲器。其例化的代码模板如下所示:

// BUFG: 全局时钟缓存(Global Clock Buffer),只能以内部信号驱动 
// Xilinx HDL库向导版本,ISE 9.1 
BUFG BUFG_inst ( 
.O(O), //时钟缓存输出信号 
.I(I) // /时钟缓存输入信号 
); 
// 结束BUFG_ins模块的例化过程 

在综合结果分析中,其和同类原语的RTL结构如图3-32所示。

图3-32 全局时钟原语的RTL级结构示意图

2.2 BUFMUX

BUFMUX是全局时钟复用器,选择两个输入时钟I0或I1中的一个作为全局时钟,其和同类原语BUFMUX1的RTL级结构如图M所示。当选择信号S为低时,选择I0;否则输出I1,其真值表如表M所示。BUFMUX原语和BUFMUX1原语的功能一样,只是选择逻辑不同,对于BUFMUX1,当选择信号S为低时,选择I1;否则输出I0。

BUFMUX原语的例化代码模板如下所示:

// BUFGMUX: 全局时钟的2到1复用器(Global Clock Buffer 2-to-1 MUX) 
// 适用芯片:Virtex-II/II-Pro/4/5, Spartan-3/3E/3A 
// Xilinx HDL库向导版本,ISE 9.1 
BUFGMUX BUFGMUX_inst ( 
.O(O), //时钟复用器的输出信号 
.I0(I0), // 0时钟输入信号 
.I1(I1), //1时钟输入信号 
.S(S) // 时钟选择信号 
); 
// 结束BUFGMUX_inst模块的例化过程 

图全局时钟复用器的RTL级结构示意图

2.3 BUFIO

BUFIO是本地I/O时钟缓冲器,其RTL结构如图M所示,只有一个输入与输出,非常简单。BUFIO使用独立于全局时钟网络的专用时钟网络来驱动纵向I/O管脚,所以非常适合同步数据采集。BUFIO要求时钟和相应的I/O必须在同一时钟区域,而不同时钟网络的驱动需要BUFR原语来实现。需要注意的是,由于BUFIO引出的时钟只到达了I/O列,所以不能来驱动逻辑资源,如CLB和块RAM。 BUFIO的例化代码模板如下:

// BUFIO: 本地I/O时钟缓冲器( Local Clock Buffer) 
// 适用芯片:Virtex-4/5 
// Xilinx HDL库向导版本,ISE 9.1 
BUFIO BUFIO_inst ( 
.O(O), //本地I/O时钟缓冲器的输出信号 
.I(I) //本地I/O时钟缓冲器的输入信号 
); 
// 结束BUFIO模块的例化过程 

在综合结果分析时,其RTL级结构如图所示。

图本地I/O时钟缓冲器的RTL级结构示意图

2.4 BUFR

BUFR是本地I/O时钟、逻辑缓冲器,其RTL结构如图M所示。BUFR和BUFIO都是将驱动时钟引入某一时钟区域的专用时钟网络,而独立于全局时钟网络;不同的是,BUFR不仅可以跨越不同的时钟区域(最多3个),还能够驱动I/O逻辑以及自身或邻近时钟区域的逻辑资源。BUFIO的输出和本地内部互联都能驱动BUFR组件。此外,BUFR能完成输入时钟1~8的整数分频。因此,BUFR是同步设计中实现跨时钟域以及串并转换的最佳方式。 BUFIO的例化代码模板如下:

// BUFR: 本地I/O时钟、逻辑缓冲器(Regional Clock Buffer) 
// 适用芯片:Virtex-4/5 
// Xilinx HDL库向导版本,ISE 9.1 
BUFR #( 
.BUFR_DIVIDE("BYPASS"), 
//分频比,可选择 "BYPASS", "1", "2", "3", "4", "5", "6", "7", "8"。 
.SIM_DEVICE("VIRTEX4") 
// 指定目标芯片, "VIRTEX4" 或者 "VIRTEX5" 
) BUFR_inst ( 
.O(O), //时钟缓存输出信号 
.CE(CE), //时钟使能信号,输入信号 
.CLR(CLR), //时钟缓存清空信号 
.I(I) // 时钟缓存输入信号 
); 
// 结束BUFR模块的例化过程 

需要注意的是:BUFIO和BUFR只能在Virtex-4系列以及更高系列芯片中使用。在综合结果分析时,其RTL结构如图所示。

图 本地I/O时钟、逻辑缓冲器的RTL级结构示意图

2.5 DCM_BASE

DCM_BASE是基本数字时钟管理模块的缩写,是相位和频率可配置的数字锁相环电路,常用于FPGA系统中复杂的时钟管理。如果需要频率和相位动态重配置,则可以选用DCM_ADV原语;如果需要相位动态偏移,可使用DCM_PS原语。DCM系列原语的RTL结构如图所示。

模块接口信号的说明如表所列。

DCM_BASE组件可以通过Xilinx的IP Wizard向导产生,也可以直接通过下面的例化代码直接使用。其Verilog的例化代码模板为:

// DCM_BASE: 基本数字时钟管理电路(Base Digital Clock Manager Circuit) 
// 适用芯片:Virtex-4/5 
// Xilinx HDL库向导版本,ISE 9.1 
DCM_BASE #( 
.CLKDV_DIVIDE(2.0), 
// CLKDV分频比可以设置为: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5 
// 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 
.CLKFX_DIVIDE(1), // Can be any integer from 1 to 32 
// CLKFX信号的分频比,可为1到32之间的任意整数 
.CLKFX_MULTIPLY(4), 
// CLKFX信号的倍频比,可为2到32之间的任意整数 
.CLKIN_DIVIDE_BY_2("FALSE"), 
// 输入信号2分频的使能信号,可设置为TRUE/FALSE 
.CLKIN_PERIOD(10.0), 
// 指定输入时钟的周期,单位为ns,数值范围为1.25~1000.00。 
.CLKOUT_PHASE_SHIFT("NONE"), 
// 指定移相模式,可设置为NONE或FIXED 
.CLK_FEEDBACK("1X"), 
// 指定反馈时钟的频率,可设置为NONE、1X或2X。相应的频率关系都是针对CLK0而言的。 
.DCM_PERFORMANCE_MODE("MAX_SPEED"), 
// DCM模块性能模式,可设置为 MAX_SPEED 或 MAX_RANGE 
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), 
// 抖动调整,可设置为源同步、系统同步或0~15之间的任意整数 
.DFS_FREQUENCY_MODE("LOW"), 
// 数字频率合成模式,可设置为LOW或HIGH 两种频率模式 
.DLL_FREQUENCY_MODE("LOW"), 
// DLL的频率模式,可设置为LOW、HIGH或HIGH_SER 
.DUTY_CYCLE_CORRECTION("TRUE"), 
// 设置是否采用双周期校正,可设为TRUE或FALSE 
.FACTORY_JF(16'hf0f0), 
// 16比特的JF因子参数 
.PHASE_SHIFT(0), 
// 固定相移的数值,可设置为 -255 ~ 1023之间的任意整数 
.STARTUP_WAIT("FALSE") 
// 等DCM锁相后再延迟配置DONE管脚,可设置为TRUE/FALSE 
) DCM_BASE_inst ( 
.CLK0(CLK0), // 0度移相的DCM时钟输出 
.CLK180(CLK180), // 180度移相的DCM时钟输出 
.CLK270(CLK270), // 270度移相的DCM时钟输出 
.CLK2X(CLK2X), // DCM模块的2倍频输出 
.CLK2X180(CLK2X180), // 经过180度相移的DCM模块2倍频输出 
.CLK90(CLK90), // 90度移相的DCM时钟输出 
.CLKDV(CLKDV), // DCM模块的分频输出,分频比为CLKDV_DIVIDE 
.CLKFX(CLKFX), // DCM合成时钟输出,分频比为(M/D) 
.CLKFX180(CLKFX180), // 180度移相的DCM合成时钟输出 
.LOCKED(LOCKED), // DCM锁相状态输出信号 
.CLKFB(CLKFB), // DCM模块的反馈时钟信号 
.CLKIN(CLKIN), // DCM模块的时钟输入信号 
.RST(RST) // DCM 模块的异步复位信号 
); 
// 结束DCM_BASE模块的例化过程 

在综合结果分析时,DCM系列原语的RTL结构如图所示。

图DCM模块的RTL级结构示意图

3 配置和检测组件

配置和检测组件提供了FPGA内部逻辑和JTAG扫描电路之间的数据交换以及控制功能,只要由6个原语组成,如表所示。

表配置和检测原语列表

下面对BSCAN_VIRTEX4组件进行简单介绍,其余组件的使用方法是类似的。

3.1 BSCAN_VIRTEX4

当JTAG USER1/2/3/4指令被加载后,BSCAN_VIRTEX4允许设计人员来检测TCK、TMS以及TDI等专用JTAG管脚的数据,并且可以将用户数据写入到TDO管脚上,这样可以在PC上通过JTAG链读取芯片内部的用户数据。

BSCAN_VIRTEX4的管脚信号说明如下:

  • CAPTURE:位宽为1的输出信号,用于指示是否加载了用户指令,当JTAG接口处于CAPTURE-DR状态时,输出为高。
  • DRCK:位宽为1的输出信号,用于监测JTAG电路的TCK信号。当JTAG链路处于用户指令模式或者JTAG接口为SHIFT-DR状态时,才有信号输出。
  • RESET:位宽为1的输出信号,在加载用户指令时有效。当JTAG接口控制器处于TEST-LOGIC-RESET状态时置高。
  • SEL:位宽为1的输出信号,高有效。用于指示USER1数据是否加载到JTAG指令寄存器中。在UPDATE-IR状态时有效,直到加载新的指令之前,一直保持有效电平。
  • SHIFT:位宽为1的输出信号,加载用户指令时有效。当JTAG接口控制器处于SHIFT-DR状态时置高。
  • TDI:位宽为1的输出信号,用于检测JTAG链的TDI信号。
  • UPDATE:位宽为1的输出信号,加载USER1指令和USER2指令时有效。当JTAG接口控制器处于UPDATE-DR状态时置高。
  • TDO:位宽为1的输入信号,可以将外部JTAG链的TDO信号直接连到该管脚上。

在Virtex-4芯片中,有4个BSCAN_VIRTEX4硬件原语可用。因此,其属性JTAG_CHAIN的有效值为1~4,默认值为1。 BSCAN_VIRTEX4原语的例化代码模板如下所示:

// BSCAN_VIRETX4: 完成内部逻辑和JTAG接口连接的边界扫描原语(Boundary Scan primitive for connecting internal logic to JTAG interface.) 
// 适用芯片:Virtex-4/5 
// Xilinx HDL库向导版本,ISE 9.1 
BSCAN_VIRETX4 #( 
.JTAG_CHAIN(1) 
// 指定JTAG链用户指令,必须为1, 2, 3, 或4中的任何一个正整数 
) BSCAN_VIRETX4_inst ( 
.CAPTURE(CAPTURE), // 捕获到的从TAP控制器的输出 
.DRCK(DRCK), // 用户函数服务的数据寄存器输出 
.RESET(RESET), // TAP控制器输出的复位信号 
.SEL(SEL), // 用户激活输出 
.SHIFT(SHIFT), // TAP控制器的移位输出 
.TDI(TDI), // TAP控制器的TDI输出信号 
.UPDATE(UPDATE), // TAP控制器的UPDATE输出信号 
.TDO(TDO) // 用户函数的数据输入信号 
); 
// 结束BSCAN_VIRETX4:模块的例化过程 

在综合结果分析时,BSCAN_VIRTEX4的RTL结构图如图所示。

图 BSCAN_VIRTEX4原语的RTL图

4 吉比特收发器组件

吉比特收发器组件用于调用RocketIO千兆位级收发器,支持从622 Mbps 到 6.5 Gbps的多速率应用,符合最广泛的芯片、背板和光学器件的标准及协议,具有高级Tx/Rx均衡技术,收发器最多可达24个,提供了完整的串行 I/O 解决方案。具体包括4个组件,如表所示。

表 吉比特收发器组件

由于吉比特收发器操作复杂,使用原语很容易出错,不易配置,因此需要在ISE中通过结构向导完成。有关吉比特收发器的原理和使用方法,将在以后详细介绍。

5 I/O端口组件

I/O组件提供了本地时钟缓存、标准单端I/O缓存、差分I/O信号缓存、DDR专用I/O信号缓存、可变抽头延迟链、上拉、下拉以及单端信号和差分信号之间的相互转换,具体包括了21个原语,如表3-11所示。

表3-11 I/O端口组件

下面对几个常用I/O组件进行简单介绍,其余组件的使用方法是类似的。

5.1 BUFIO

BUFIO是FPGA芯片内部简单的时钟输入、输出缓存器,其RTL结构如图3-38所示。BUFIO使用独立于全局时钟网络的专用时钟网络来驱动I/O列,因此非常适合用于源同步的数据采集。但要注意的是:BUFIO只能在单一的时钟区域内使用,不能跨时钟域操作。此外,BUFIO也不能用于驱动逻辑资源(CLB、块RAM等),因此其只能到达I/O列。

图3-38 BUFIO的RTL结构图

5.2 IBUFDS

IBUFDS原语用于将差分输入信号转化成标准单端信号,且可加入可选延迟。在IBUFDS原语中,输入信号为I、IB,一个为主,一个为从,二者相位相反。 IBUFDS的逻辑真值表如表3-12所列,其中“-*”表示输出维持上一次的输出值,保持不变。

表3-12 IBUFDS原语的输入、输出真值表

BUFDS原语的例化代码模板如下所示:

// IBUFDS: 差分输入缓冲器(Differential Input Buffer) 
// 适用芯片:Virtex-II/II-Pro/4, Spartan-3/3E 
// Xilinx HDL库向导版本,ISE 9.1 
IBUFDS #( 
.DIFF_TERM("FALSE"), 
// 差分终端,只有Virtex-4系列芯片才有,可设置为True/Flase 
.IOSTANDARD("DEFAULT") 
// 指定输入端口的电平标准,如果不确定,可设为DEFAULT 
) IBUFDS_inst ( 
.O(O), // 时钟缓冲输出 
.I(I), // 差分时钟的正端输入,需要和顶层模块的端口直接连接 
.IB(IB) // 差分时钟的负端输入,需要和顶层模块的端口直接连接 
); 
// 结束IBUFDS模块的例化过程 

在综合结果分析时,IBUFDS的RTL结构如图3-39所示。

图3-39 IBUFDS原语的RTL结构图

5.3 IDELAY

Virtex-4系列芯片中,每个用户I/O管脚的输入通路都有一个IDELAY模块,可用于数据信号或时钟信号,以使二者同步,准确采集输入数据。IDELAY具有可控的64抽头延迟线,每个抽头的延迟都是经过精密校准的78ps,且与进程、电压和温度特性无关,其内部结构如图3-40所示。

图3-40 IDELAY模块的RTL级结构图

IDELAY原语的信号说明如下:

  • I:单比特输入信号,来自于IOB的串行输入数据;
  • C:单比特输入信号,时钟输入信号;
  • INC:单比特输入信号,用于增加或减少延迟抽头数;
  • CE:单比特输入信号,使能延迟抽头数增加或减少的功能;
  • RST:单比特输入信号,复位延迟链的延迟抽头数,如果没有编程输入,则为0;
  • O:单比特输出信号。

IDELAY原语的例化代码模板如下所示:

// IDELAY: 输入延迟单元(Input Delay Element) 
// 适用芯片:Virtex-II/II-Pro/4, Spartan-3/3E 
// Xilinx HDL库向导版本,ISE 9.1 
IDELAY #( 
.IOBDELAY_TYPE("DEFAULT"), 
// 输入延迟类型,可设置为 "DEFAULT", "FIXED" 或者 "VARIABLE" 
.IOBDELAY_VALUE(0) 
// 输入延迟周期数,可设置为0~63之间的任意整数 
) IDELAY_inst ( 
.O(O), //1比特输出信号 
.C(C), // 1比特时钟输入信号 
.CE(CE), // 1比特时钟使能信号 
.I(I), // 1比特数据输入信号 
.INC(INC), // 1比特增量输入信号 
.RST(RST) //1比特复位输入信号 
); 
// 结束IDELAY模块的例化过程 

在综合结果分析时,IDELAY原语的RTL结构如图3-41所示。

图3-41 IDELAY原语的RTL结构图

5.4 OBUFDS

OBUFDS将标准单端信号转换成差分信号,输出端口需要直接对应到顶层模块的输出信号,和IBUFDS为一对互逆操作。OBUFDS原语的真值表如表3-13所列。

表3-13 OBUFDS原语的真值表

OBUFDS原语的例化代码模板如下所示:

// OBUFDS: 差分输出缓冲器(Differential Output Buffer) 
// 适用芯片:Virtex-II/II-Pro/4, Spartan-3/3E 
// Xilinx HDL库向导版本,ISE 9.1 
OBUFDS #( 
.IOSTANDARD("DEFAULT") 
// 指名输出端口的电平标准 
) OBUFDS_inst ( 
.O(O), // 差分正端输出,直接连接到顶层模块端口 
.OB(OB), // 差分负端输出,直接连接到顶层模块端口 
.I(I) // 缓冲器输入 
); 
// 结束OBUFDS模块的例化过程 

在综合结果分析时,OBUFDS原语的RTL结构如图3-42所示。

图3-42 OBUFDS的RTL结构图

5.5 IOBUF

IOBUF原语是单端双向缓冲器,其I/O接口必须和指定的电平标准相对应,支持 LVTTL、LVCMOS15、LVCMOS18、LVCMOS25以及LVCMOS33等信号标准,同时还可通过DRIVE、 FAST 以及SLOW等约束来满足的不同驱动和抖动速率的需求。默认的驱动能力为12mA,低抖动。IOBUF由IBUF和OBUFT两个基本组件构成,当I/O端口为高阻时,其输出端口O为不定态。IOBUF原语的功能也可以通过其组成组件的互联来实现。 IOBUF原语的输入输出真值表如表3-14所列。

表3-14 IOBUF原语的真值表

IOBUF原语的例化代码模板如下所示:

// IOBUF: 单端双向缓冲器(Single-ended Bi-directional Buffer) 
// 适用芯片:所有芯片 
// Xilinx HDL库向导版本,ISE 9.1 
IOBUF #( 
.DRIVE(12), 
// 指定输出驱动的强度 
.IOSTANDARD("DEFAULT"), 
// 指定I/O电平的标准,不同的芯片支持的接口电平可能会有所不同 
.SLEW("SLOW") 
// 制定输出抖动速率 
) IOBUF_inst ( 
.O(O), // 缓冲器的单元输出 
.IO(IO), // 缓冲器的双向输出 
.I(I), // 缓冲器的输人 
.T(T) // 3态使能输入信号 
); 
// 结束IOBUF模块的例化过程 

在综合结果分析时,IOBUF原语的RTL结构如图3-43所示。

图3-43 OBUFDS的RTL结构图

5.6 PULLDOWN/PULLUP

数字电路有三种状态:高电平、低电平、高阻状态。有些应用场合不希望出现高阻状态,可以通过上拉电阻或下拉电阻的方式使其处于稳定状态,如图3-44所示。FPGA的I/O端口,可以通过外接电阻上下拉,也可以在芯片内部,通过配置完成上下拉。上拉电阻是用来解决总线驱动能力不足时提供电流的,而下拉电阻是用来吸收电流。通过FPGA内部配置完成上下拉,能有效节约电路板面积,是设计的首选方案。

图3-44 上、下拉电路示意图

上、下拉的原语分别为PULLUP和PULLDOWN。 1)PULLUP原语的例化代码

// PULLUP: 上拉原语(I/O Buffer Weak Pull-up) 
// 适用芯片:所有芯片 
// Xilinx HDL库向导版本,ISE 9.1 
PULLUP PULLUP_inst ( 
.O(O), 
//上拉输出,需要直接连接到设计的顶层模块端口上); 
// 结束PULLUP模块的例化过程 

2)PULLDOWN原语的例化代码 

// PULLDOWN:下拉原语( I/O Buffer Weak Pull-down) 
// 适用芯片:所有芯片 
// Xilinx HDL库向导版本,ISE 9.1 
PULLDOWN PULLDOWN_inst ( 
.O(O), 
// 下拉输出,需要直接连接到设计的顶层模块端口上 
); 
// 结束PULLDOWN模块的例化过程

6 处理器组件

处理器组件主要包括高速以太网MAC控制器和PowerPC硬核,如表3-15所示。

表3-15处理器组件列表

 处理器组件是 Xilinx 的嵌入式解决方案,涉及软、硬件调试以及系统设计, 将在第 8 章详细介绍。

7 RAM/ROM 组件

RAM/ROM 组件可用于例化 FIFO、分布式 RAM、分布式 RAM、块 ROM 以 及块 ROM,具体包括 12 个组件,如表 3-16 所示。

表 3-16 RAM/ROM 原语列表

 下面主要介绍 FIFO、分布式双口 RAM 以及块双口 RAM 原语的使用,单口RAM 和 ROM 原语的用法类似,限于篇幅,就不再介绍。
 

7.1 RAM16X1S

RAM16X1S 是深度为 16 比特,位宽为 1 的同步 RAM。当写使能信号 WE为低时,写端口的数据操作无效, RAM 内部的数据不会改变;当 WE 为高时,可以在任意地址中写入比特。为了保证数据的稳定性,地址和数据应该在 WCLK 的上升沿前保持稳定。输出信号 O 为 RAM 中由读地址信号所确定的地址中所存数据的值。此外,还可通过属性指定 RAM 的初始值。
RAM16X1S 原语的例化代码模版如下所示: 

// RAM16X1S: 16比特 1深度同步 RAM(16 x 1 posedge write distributed (LUT)
RAM)
// 适用芯片:所有芯片
// Xilinx HDL 库向导版本, ISE 9.1
RAM16X1S #(
.INIT(16'h0000)
//对 RAM 的内容进行初始化,这里初始化为全 1
) RAM16X1S_inst (
.O(O), // RAM output
.A0(A0), // RAM address[0] input
.A1(A1), // RAM address[1] input
.A2(A2), // RAM address[2] input
.A3(A3), // RAM address[3] input
.D(D), // RAM data input
.WCLK(WCLK), // Write clock input
.WE(WE) // Write enable input
);
// 结束 RAM16X1S 模块的例化过程

需要注意的是, RAM16X1S 原语是 Xilinx 独有的一类结构,在小数据量存储方面非常节省资源。在综合结果分析时, RAM16X1S 原语的 RTL 结构如图 3-45 所示。

图 3-45 原语 RAM16X1S 的 RTL 结构图

7.2  RAMB16

RAMB16 是 FPGA 芯片中内嵌的双口块 RAM,数据位宽可配置成 1、 2、 4、9、 18 以及 36 比特,每个块 RAM 的大小为 18 1024 比特,所以位宽越大,深度越小。块 RAM 在 FPGA 中按照矩阵的方式排列,其数量完全取决于芯片容量的大小。在使用中,可以添加坐标来约束块 RAM 的位置。例如:LOC = RAMB16_X#Y#;同样,也可以对块 RAM 完成初始化。块 RAM 是以硬核的方式内嵌到 FPGA芯片中,不占用芯片的逻辑资源,是 FPGA 芯片内部非常宝贵的一种资源。在工作时,要尽量使用芯片的块 RAM 资源,不仅能保证较高的工作频率,还具有很低的动态功耗。
RAMB16 的 Verilog 例化代码如下所示。

// RAMB16: 块 RAM(Virtex-4 16k+2k Parity Paramatizable BlockRAM
// 适用芯片: Virtex-4 芯片
// Xilinx HDL 库向导版本, ISE 9.1
RAMB16 #(
.DOA_REG(0),// A 端口可选的输出寄存器,可设置为 0 或 1,分别表示输出不寄存/寄存
.DOB_REG(0),// B 端口可选的输出寄存器,可设置为 0 或 1,分别表示输出不寄存/寄存
.INIT_A(36'h000000000),// 初始化 A 端口的输出初始值
.INIT_B(36'h000000000),// 初始化 A 端口的输出初始值
.INVERT_CLK_DOA_REG("FALSE"),// 反转 A 端口寄存器的时钟,可设置为"TRUE"或 "FALSE",分别表示不反转/反转
.INVERT_CLK_DOB_REG("FALSE"),// 反转 B 端口寄存器的时钟,可设置为"TRUE"或 "FALSE",分别表示不反转/反转
.RAM_EXTENSION_A("NONE"),// RAM 的 A 端口扩展选项,可设置为"UPPER"、 "LOWER"或 "NONE",分别表示作为高字节、低字节级联,或者不扩展
.RAM_EXTENSION_B("NONE"),// RAM 的 B 端口扩展选项.READ_WIDTH_A(0),同 A 端口
.READ_WIDTH_A(0),// A 端口的数据读取宽度,有效值为 1, 2, 4, 9, 18, 或 36
.READ_WIDTH_B(0),// B 端口的数据读取宽度,有效值为 1, 2, 4, 9, 18, 或 36
.SIM_COLLISION_CHECK("ALL"),// 碰撞检测使能信号,可设置为"ALL"、 "WARNING_ONLY"、"GENERATE_X_ONLY" 或者"NONE"
.SRVAL_A(36'h000000000),// 复位后 A 端口的输出值
.SRVAL_B(36'h000000000),//复位后 A 端口的输出值
.WRITE_MODE_A("WRITE_FIRST"),// A 端口的写模式,可设置为"WRITE_FIRST", "READ_FIRST", 或"NO_CHANGE"
.WRITE_MODE_B("WRITE_FIRST"),// B 端口的写模式,可设置为"WRITE_FIRST", "READ_FIRST", 或"NO_CHANGE"
.WRITE_WIDTH_A(2),// A 端口的数据写入宽度,有效值为 1, 2, 4, 9, 18, 或 36
.WRITE_WIDTH_B(0),// B 端口的数据写入宽度,有效值为 1, 2, 4, 9, 18, 或 36
// 下列 INIT_xx 声明用于指定 RAM 的初始化内容
.INIT_00(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_01(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_02(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_03(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_04(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_05(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_06(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_07(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_08(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_09(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_0A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_0B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_0C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_0D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_0E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_0F(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_10(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_11(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_12(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_13(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_14(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_15(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_16(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_17(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_18(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_19(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1F(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_20(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_21(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_22(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_23(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_24(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_25(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_26(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_27(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_28(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_29(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2F(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_30(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_31(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_32(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_33(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_34(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_35(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_36(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_37(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_38(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_39(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3F(256'h0000000000000000000000000000000000000000000000000000000000000000),
// 下面的 INITP_xx 用于初始化校验比特
.INITP_00(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_01(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_02(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_03(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_04(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_05(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_06(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_07(256'h0000000000000000000000000000000000000000000000000000000000000000)
) RAMB16_inst (
.CASCADEOUTA(CASCADEOUTA), // A 端口的 1 比特级联输出
.CASCADEOUTB(CASCADEOUTB), // B 端口的 1 比特级联输出
.DOA(DOA), // A 端口的 32 比特数据输出
.DOB(DOB), // B 端口的 32 比特数据输出
.DOPA(DOPA), // A 端口 4 比特校验数据输出
.DOPB(DOPB), // B 端口 4 比特校验数据输出
.ADDRA(ADDRA), // A 端口 15 比特地址输入
.ADDRB(ADDRB), // B 端口 15 比特地址输入
.CASCADEINA(CASCADEINA), // A 端口 1 比特级联地址输入
.CASCADEINB(CASCADEINB), // B 端口 1 比特级联地址输入
.CLKA(CLKA), //A 端口的工作时钟输入
.CLKB(CLKB), // B 端口的工作时钟输入
.DIA(DIA), // A 端口的 32 比特写数据
.DIB(DIB), // A 端口的 32 比特写数据
.DIPA(DIPA), //A端口 4 比特校验输入数据
.DIPB(DIPB), //B 端口 4 比特校验输入数据
.ENA(ENA), //A 端口的 1 比特使能信号
.ENB(ENB), //B 端口的 1 比特使能信号
.REGCEA(REGCEA), //A 端口 1 比特寄存器使能信号
.REGCEB(REGCEB), //B 端口 1 比特寄存器使能信号
.SSRA(SSRA), // A 端口 1 比特复位输入信号
.SSRB(SSRB), // B 端口 1 比特复位输入信号
.WEA(WEA), // A 端口 4 比特写使能输入信号
.WEB(WEB) // B 端口 4 比特写使能输入信号
);
// 结束 RAMB16 模块的例化过程

在综合结果分析时, RAMB16 的 RTL 结构如图 3-46 所示。
 

 图 3-46 RAMB16 的 RTL 结构示意图

8 寄存器和锁存器


寄存器和锁存器是时序电路中常用的基本元件,其原语在表 3-17 中给出。

 表 3-17 寄存器和锁存器原语列表

下面只介绍 FDCPE 原语的使用,其余两个原语的使用方法类似。

8.1 FDCPE 原语

FDCPE 指带单数据输入信号 D、单输出 O、时钟使能信号 CE、异步复位 PRE和异步清空信号 CLR 的 D 触发器。当 PRE 信号为高时,输出端 O 为高;当CLR 为高时,输出端 O 为低;当 PRE 和 CLR 都为低、 CE 信号为高时,输入信号 D 在时钟上升沿被加载到触发器中,并被送到输出端;当 PRE 和 CLR都为低、 CE 信号为低时,输出端保持不变。 FDCPE 的真值表如表 3-18 所列。
                                           

表 3-18 FDCPE 原语的真值表

 FDCPE 原语的 Verilog 实例化代码如下所示: 

// FDCPE: D 触发器(Single Data Rate D Flip-Flop )
// 适用芯片:所有 FPGA 芯片
// Xilinx HDL 库向导版本, ISE 9.1
FDCPE #(
.INIT(1'b0)
//初始化寄存器的值,可设置为 1'b0 或 1'b1
) FDCPE_inst (
.Q(Q), // 数据输出端口
.C(C), // 时钟输入端口
.CE(CE), // 时钟使能输入信号
.CLR(CLR), // 异步清空输入信号
.D(D), // 数据输入信号
.PRE(PRE) // 异步复位输入信号
);
// 结束 FDCPE 模块的例化过程

在综合结果分析时, FDCPE 原语的 RTL 结构如图 3-47 所示。

 图 3-47 FDCPE 的 RTL 结构 

 9 移位寄存器组件


移位寄存器组件为 Xilinx 芯片所独有,由于属性的不同,具体有 8 个,如表3-19 所列。
                                                        表 3-19 移位寄存器组件列表 

各个移位寄存器原语都是在 SRL16 的基础上发展起来的,因此,本节主要介绍基本的 SRL16 原语。

9.1  SRL16

SRL16 是基于查找表(LUT)的移位寄存器,在实际应用中既能节省资源,还能保证时序。其输入信号 A3、 A2、 A1 以及 A0 选择移位寄存器的读取地址,当写使能信号高有效时,输入信号将被加载到移位寄存器中。单个移位寄存器的深度可以是固定的,也可以动态调整,最大不能超过 16。需要更大深度的移位寄存器时,则需要将多个 SRL16 拼接起来。单个 SRL16 的地
址信号线与输出的真值表如表 3-20 所示。

                                                         表 3-20 SRL16 的功能说明表

SRL16 本质上是一种基于查找表(LUT)的移位寄存器,因此其位宽(B)和深度(D)需要满足查找表的结构特点,所占用 Slice 资源 M 的计算公式为:

其中, R[]函数的意义是取整。从上式可以看出,深度为 1 的移位寄存器和深度为 16 的移位寄存器所占用的 Slice 资源是一样的。和触发器相比, SRL16最大的特点就是占用 Slice 资源特别少。

只要固定 A3~A0 的信号电平,即可获得一个固定长度的移位寄存器,其长度范围从 1~16,可由公式(M)计算得到。当 A3~A0 全为 0 时,其寄存深度为 1;当 A3~A0 全为 1 时,其寄存深度为 16。
Length = (8 x A3) +(4 x A2) + (2 x A1) + A0 +1 (M)
SRL16 原语的 Verilog 实例化代码如下所示: 

// SRL16: 16 位查找表移位寄存器(16-bit shift register LUT operating on posedge of clock)
// 适用芯片:所有 FPGA 芯片
// Xilinx HDL 库向导版本, ISE 9.1
SRL16 #(
.INIT(16'h0000)// 初始化移位寄存器的值,可以为 16 比特任意整数
) SRL16_inst (
.Q(Q),     // SRL16 的数据输出信号
.A0(A0),   // 选择[0]输入
.A1(A1),   // 选择[1]输入
.A2(A2),   // 选择[2]输入
.A3(A3),   // 选择[3]输入
.CLK(CLK), // 时钟输入信号
.D(D)      // SRL16 的数据输入信号
);
// 结束 SRL16 模块的例化过程

在综合结果分析时, SRL16 原语的 RTL 级结构如图 3-48 所示。

图 3-48 SRL16 的 RTL 级结构示意图

10 Slice/CLB 组件


Slice/CLB 组件涵盖了 Xilinx FPGA 中所有的逻辑单元,包括各种查找表、复用器以及逻辑操作等 21 个原语,如表 3-21 所列。

表 3-21 Slice/CLB 组件列表 

本节主要介绍基本的单输出 1 比特查找表原语和通用输出 2 到 1 复用器原语的使用方法。

10.1  LUT1

FPGA内部的组合逻辑都可以通过LUT结构实现,常用的LUT结构有LUT1、LUT2、 LUT3 以及 LUT4,其区别在于查找表输入比特宽度的不同。 LUT1是其中最简单的一种,常用于实现缓冲器和反相器,是带通用输出的 1 比特查找表。
LUT1 原语的 Verilog 实例化代码如下所示:

// LUT1: 1 比特输入的通用查找表(1-input Look-Up Table with general output)
// 适用芯片:所有 FPGA 芯片
// Xilinx HDL 库向导版本, ISE 9.1
LUT1 #(
.INIT(2'b00)// 指定 LUT 的初始化内容
) LUT1_inst (
.O(O), // LUT 的通用输出
.I0(I0) // LUT 输入信号
);
// 结束 LUT1 模块的例化过程

在综合结构分析时, LUT1 原语的 RTL 级结构如图 3-49 所示。 

图 3-49 LUT1 的 RTL 级结构示意图

10.2 MUXF7

MUXF7 是带通用输出的 2 到 1 查找表复用器,其控制信号 S 可以是任何内部信号,当其为低电平时,选择 I0;当其为高电平时选择 I1。 MUXF7 需要占用一个完整的 CLB 资源,和其相关的查找表可组成 7 功能的查找表和 16到 1 的选择器,可将 MUXF6 的输出连接到 MUXF7 的输入端。 MUXF7 的真值表如表 3-22 所示。

表 3-22 MUXF7 的真值表

 MUXF7 原语的实例化代码如下所示:

// MUXF7: 2 到 1LUT 复用器(CLB MUX to tie two MUXF6's together with general output)
// 适用芯片: Virtex-II/II-Pro 以及 Spartan-3/3E
// Xilinx HDL 库向导版本, ISE 9.1
MUXF7 MUXF7_inst (
.O(O), // MUX 的通用输出信号
.I0(I0),
.I1(I1), // 复用器的输入信号,连接到 MUXF6 LO
.S(S) // 复用器的输入选择信号
);
// End of MUXF7_inst instantiation

 在综合结构分析时, MUXF7 原语的 RTL 级结构如图 3-50 所示。

图 3-50 MUXF7 的 RTL 及结构示意图 

本节给出了典型的 Xilinx 原语的使用,但更多的原语需要读者在实践中大量应用才能熟练掌握。只有全面掌握了原语,才能对 Xilinx FPGA 的资源有一个理性认识,从而将工程设计提升到艺术雕刻的高度,这是每一个 FPGA 开发人员的目标。详细的原语资料可在 ISE 安装目录下的“doc\usenglish\books\docs”文件夹中找到,其中 Virtex4 系列芯片的原语资料文件“v4ldl.pdf”
位于“v4ldl”文件中, Virtex5 系列芯片的原语资料文件“v5ldl.pdf”位于“v5ldl”文件中, Spartan 3A 系列芯片的原语资料文件“s3adl.pdf”位于“s3adl”文件中,Spartan 3E 系列芯片的原语资料文件“s3edl.pdf”位于“s3edl”文件中。

本章小结

本章主要介绍基于 Xilinx 芯片的 Verilog 开发技术。首先介绍了典型的硬件设计思维;然后讨论了优秀的通用代码风格和 Xilinx 专用的代码风格,无论哪种风格都是稳定性、速度以及硬件资源三者优化,只不过前者从 FPGA 器件共有的特性出发,后者则面向 Xilinx 公司的 FPGA 芯片特点;最后,介绍了 Xilinx 公司 FPGA 器件的硬件原语,以及典型原语的使用方法。特别需要强调的一点是:对原语的全面掌握是 Xilinx FPGA 开发人员的基本要求。
 

Xilinx FPGA原语是指Xilinx公司针对其器件特征开发的一系列常用模块,用户可以将其看成Xilinx为用户提供的库函数,类似于C中的关键字。原语代表FPGA中实际拥有的硬件逻辑单元,如LUT,D触发器,RAM等。在实现过程中,需要将设计单元转译为目标器件中的基本元件,否则无法实现。原语可以直接例化使用,是最直接的代码输入方式。Xilinx公司提供的原语按功能分为计算组件、I/O端口组件、寄存器和锁存器、时钟组件、处理器组件、移位寄存器、配置和检测组件、RAM/ROM组件、Slice/CLB组件以及G比特收发器组件。 其中,计算组件包括DSP48核,也被称为硬件乘法器。它是Xilinx FPGA原语的一种,功能为进行计算。 另外,FPGA设计中的时钟信号如果不是由FPGA芯片的专用时钟pin引入,通常需要在FPGA内部连接到时钟树资源上。这样做是为了避免时序问题影响逻辑行为。 还有一种原语是BUFMUX,它是全局时钟复用器,用于选择两个输入时钟中的一个作为全局时钟。BUFMUX的功能可以通过选择信号来实现。它在综合结果分析中和同类原语BUFMUX1有相似的RTL级结构。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Xilinx公司原语的使用方法](https://blog.csdn.net/phenixyf/article/details/42874011)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Xilinx原语的使用](https://blog.csdn.net/qq_45776815/article/details/129262416)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

惜缘若水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值