[X]关闭

21 FPGA知识_解密XILINX FPGA 基本单元CLB

文档创建者:FPGA课程
浏览次数:415
最后更新:2024-08-15
FPGA基础知识
FPGA基础: FPGA编程语言 » Verilog编程入门
本帖最后由 FPGA课程 于 2024-8-15 14:46 编辑

​软件版本:无
操作系统:WIN10 64bit
硬件平台:适用所有系列FPGA
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

1概述
FPGA是一个非常神奇的芯片,是无所不能的芯片,掌握FPGA就是宝剑在手,但是宝剑在手的人,却不一定做可以天下无敌,因为宝剑只是一把好剑,关键的还是得有会用宝剑的人。比如你拿着宝剑去切猪肉,肯定比不上卖猪肉的剁刀。所以我们得先了解FPGA,才能更有利于我们正确使用FPGA,发挥FPGA的作用。
对于不少FPGA工程师来说,虽然会采用相关的FPGA编程语言和工具对FPGA编程开发。但是忽略了对FPGA底层的硬件知识的了解,在FPGA的编程之路上,可能会遇到很多自己搞不清楚的疑问。其实,我们并不需要花费太多时间去了解FPGA的内部的硬件结构,而是重点分析FPGA的CLB资源、BRAM、时钟资源、IO资源。
由于CLB资源对我们学习FPGA的基本编程有很大关系,所以本文重点介绍CLB资源。CLB是FPGA的基本逻辑单元,我们可以把CLB理解为FPGA的细胞单元。每个CLB里面包括了2个Slices,每个Slice又是由4个LUT(查找表),8个寄存器以及一些逻辑门组成。掌握这些基本单元的功能应用,以及功能特性,可以为我们未来对采取代码编程的时候,更好的实现代码和硬件的最佳配合。
2认识FPGA的容量
很多人搞了很久的FPGA都没搞清楚FPGA的容量是什么概念,这是一件非常可笑的事情,你说你是一个FPGA程序员,连FPGA的资源概念都搞不清楚,如何才能正确选型FPGA呢?当我们选型的时候,我们需要评估FPGA的资源。下表是来自于XILINX 官方文档关于资源的描述。如果你看到这个表格还不能明白其中的含义,那么下面的内容你一定不要错过,作为一个专业的FPGA开发者,你是必须要知道的内容。
image.jpg
上表中给出的是K7系列FPGA的资源概述,我们和别人交流FPGA资源的时候,或者选型FPGA的时候需要重点考虑以上资源。接下来,笔者对其中重点的资源进行介绍。
2.1Slices单元
一个CLB包括了2个Slices,但是我们通常描述FPGA资源的时候不会说有多少CLB。Slices是构成CLB的基本单元。所以知道Slices的数量就可以知道FPGA的“大概”逻辑资源容量了。”大概”?,为什么不是精确的数量,作为技术工程师,听到这种不确定的描述,心真的非常不爽。但是上表给出的还真实一个概述,不够精确,所以我们需要进一步分析。
一个Slice等于4个6输入LUT+8个触发器(flip-flop)+算数运算逻辑,每个Slice的4个触发器(虽然有8个flip-flop,但是每个LUT分配一个flip-flop)可以配置成锁存器,这样会有4个触发器(flip-flop)未被使用。
对于CLB来说,里面的Slice居然还不是长一样,有2中类型的Slice。一种是SLICEL,另外一种是SLICEM。SLICEM的功能更强大,SLICEM可以当作分布式RAM或者ROM,或者实现移位寄存器。
2.2Distributed RAM
上表中,Max Distributed RAM就是由SLICEM数量决定的。我们再看下一张表:
image.jpg
对于XILINX 7系列的FPGA来说,SLICEM约占三分一的Slices。上表中我们可以看到精确的数据。比如对于7K325T的FPGA,有16000个SLICEM那么,16000X4X64bit=4096,000b(4000kb)的distributed RAM或者2000kb的Shift Register。
2.3Logic Cells
我们经常说到FPGA容量是多少,FPGA器件的容量通常用逻辑单元来衡量,这在逻辑上等同于经典的4输入LUT和触发器。 7系列FPGA逻辑单元和6输入LUT的数量之比为1.6:1,这是相对于经典的4输入LUT而言得出的。所以,逻辑单元和Slice的数量比是6.4:1。我们在前面第一张表格
image.jpg
仍然以XC7K325T为例子,50950X6.4=326080。通过计算可以看到Slices的数量对应的逻辑单元的数量,这个计算就是等效计算,因为传统的CPLD是逻辑门电路,而现在的FPGA是以查找表的方式实现了逻辑门的等效功能。
3认识FPGA Slice的功能
每个slice包含:
•四个逻辑函数生成器(查找表)
•8个存储单元
•多功能多路复选器
• 快速进位逻辑
FPGA的逻辑、算术和ROM功能就是靠Slice实现,其中slice又分SLICEL和SLICEM,SLICEM的功能更强大,除了具备SLICEL的所有功能,还能实现分布式RAM、ROM和实现移位逻辑。
3.1SLICEL
image.jpg
3.2SLICEM
image.jpg
对比SLICEM和SLICEL,可以看到以上结构图中,他们的差异在查找表上,SLICEM的查找表结构功能更复杂。SLICEM增加了写操作的控制信号,以及移动位进位的功能。
3.3LUT查找表
由于FPGA需要被反复烧写,它实现组合逻辑的基本结构不可能像ASIC那样通过固定的与非门来完成,而只能采用一种易于反复配置的结构。查找表可以很好地满足这一要求,目前主流FPGA都采用了基于SRAM工艺的查找表结构。LUT本质上就是一个RAM。它把数据事先写入RAM后, 每当输入一个信号就等于输入一个地址进行查表,找出地址对应的内容,然后输出。后面我们编程后,可以看到软件综合工具,对于使用了多少查找表的计算。所以FPGA的程序是事先把相关的查找表中填入参数,然后通过查找表实现了逻辑功能。我们经常遇到有人提问FPGA的可重新配置的问题,比如我们程序运行后,需要对部分的代码重新配置代码,理论上我们只要解释代码后,把相关的参数写入指定的FPGA逻辑就可以。这个课题不是我们这里关心的,如果有人要研究可重部分配置,必然需要掌握FPGA的硬件构造。
7系列FPGA中的函数发生器通过六输入查找表(LUT)实现。slice的4个查找表(A,B,C和D)中的每一个都有六个独立输入(A输入A1至A6)和两个独立输出(O5和O6)。
image.jpg
查找表可以实现的函数功能:
•任意定义的六输入布尔函数
•两个任意定义的五输入布尔函数,只要这两个函数共享公共输入
•两个任意定义的布尔函数(3个和2个或更少输入)
六输入功能使用:
•A1-A6输入
•O6输出
两个五输入或更少的输入使用:
•A1–A5输入
•A6驱动高
•O5和O6输出
多路复选器F7AMUX,F7BMUX和F8MUX
•F7AMUX:用于从LUT A和B生成七个输入
•F7BMUX:用于从LUT C和D生成七个输入
•F8MUX:用于组合所有LUT以生成八个输入
什么是6输入,什么是5输入或者更少,以上是什么意思,你明白了吗?
对于6输入功能,查找表可以实现2^6次方,64个存储空间的寻址查表,而且只能输出Q6。显然很多时候我们只有2个输入、3个输入、4个输入、5个输入的情况发生,那么岂不是很浪费LUT了。所以通过设置A6为高,这样低于6输入的查表运算可以通过Q5和Q6同时完成查表输出。但是这里依然有一个问题,就是同时查表的时候A1~A5的输入是相同的,虽然资料里面没有详细说明,但是我们可以通过内部结构推测,相同的输入可以查到不同的表的位置,所以Q5和Q6可以输出2个独立的计算结果。这样有利于提高资源的利用率。
6输入LUT查表原语:
   LUT6 #(
      .INIT(64'h0000000000000000)  // Specify LUT Contents
   ) LUT6_inst (
      .O(O),   // LUT general output
      .I0(I0), // LUT input
      .I1(I1), // LUT input
      .I2(I2), // LUT input
      .I3(I3), // LUT input
      .I4(I4), // LUT input
      .I5(I5)  // LUT input
   );
比如代
assign DQ = A[5:0]== 6’d1 ? 1’b1 : 1’b0
可以实现6输入查找表,实现逻辑功能。
通过对查找表的认识,我们知道了FPGA如何实现算术逻辑功能,以及我们也可以推测FPGA如果要实现软件实时自动编程应该会采用SLICEM资源。虽然现在笔者还没能力验证这一点。所以如果作为读者的你有有机会在这个领域研究,希望也能和笔者一起分享FPGA软件可以部分重编程的方案。
3.4寄存器、触发器、锁存器

image.jpg
每个slice有8个存储元素,如上图所示。
image.jpg

其中四个为DFF/LATCH,可以配置为边沿触发D型触发器或电平敏感锁存器输入上图。 D输入可以通过AFFMUX,BFFMUX,CFFMUX或DFFMUX的LUT输出直接驱动,也可以通过AX,BX,CX或DX输入绕过函数发生器的BYPASS slice输入直接驱动。 当配置为锁存器时,当CLK为低电平时,锁存器是透明的。
image.jpg
另外四个为仅为DFF,它们只能配置为边沿触发的D型触发器。 D输入可以由LUT的O5输出驱动,也可以由AX,BX,CX或DX输入的BYPASS slice输入驱动。 当原始的四个存储单元配置为闩锁时,这四个附加的存储单元将无法使用。
触发器代码如下,当敏感型号CLK上升沿到来把B值赋给A
  1. always@(posedge CLK)
  2. A <= B;
复制代码

锁存器代码如下,当C为1时候把B赋值给A,锁存器应该尽力避免,因为会影响到电路时序收敛,对毛刺敏感,容易导致意想不到的错误。
  1. always@(*)
  2. if(C==1’b1)
  3. A <= B;
复制代码

避免锁存器的代码
  1. always@(*)
  2. if(C==1’b1)
  3. A <= B;
  4. else
  5. A <= 1’b0;
复制代码

3.5分布式RAM(Distributed RAM)
在前面的章节中我们已经知道SLICEM资源可以实现分布式RAM。这里再次介绍分布式RAM的功能单元。笔者这里先给出可以实现的RAM类型:
•单口RAM
•双端口
•简单的双端口
•四端口
下表给出了通过1 SLICEM中的4个LUT可以实现的RAM类型
image.jpg
一下列举部分RAM的形式加深大家的理解,但是注意,以下列举的并不是所有的RAM形式:
1) 32 X 2 Quad Port Distributed RAM (RAM32M)
在前面的内容部分,我们介绍过把6输入LUT 当作2个5输入LUT使用,在这里,就可以同一个LUT实现数据位宽的增加。对于32X2的4口RAM,如下图所以,代表了输入和输出的数据位宽都是2bit,深度是32。4口代表了4个LUT都处于工作状态,它们的DI0和DI1,共用,第一个LUT的A1-A5和WA1-WA5相连接,并且4个LUT的WA1-WA5全部接到了一起。所以我们可以同时把数据写入到每个LUT的地址空间,然后可以分别读出每个LUT的数据。写操作是同步写入,读操作是异步读出。4口RAM实际上用的不多,我们重点看后面的单口RAM和双口RAM。
image.jpg
原语调用
  1.    RAM32M #(
  2.       .INIT_A(64'h0000000000000000), // Initial contents of A Port
  3.       .INIT_B(64'h0000000000000000), // Initial contents of B Port
  4.       .INIT_C(64'h0000000000000000), // Initial contents of C Port
  5.       .INIT_D(64'h0000000000000000)  // Initial contents of D Port
  6.    ) RAM32M_inst (
  7.       .DOA(DOA),     // Read port A 2-bit output
  8.       .DOB(DOB),     // Read port B 2-bit output
  9.       .DOC(DOC),     // Read port C 2-bit output
  10.       .DOD(DOD),     // Read/write port D 2-bit output
  11.       .ADDRA(ADDRA), // Read port A 5-bit address input
  12.       .ADDRB(ADDRB), // Read port B 5-bit address input
  13.       .ADDRC(ADDRC), // Read port C 5-bit address input
  14.       .ADDRD(ADDRD), // Read/write port D 5-bit address input
  15.       .DIA(DIA),     // RAM 2-bit data write input addressed by ADDRD,
  16.                      //   read addressed by ADDRA
  17.       .DIB(DIB),     // RAM 2-bit data write input addressed by ADDRD,
  18.                      //   read addressed by ADDRB
  19.       .DIC(DIC),     // RAM 2-bit data write input addressed by ADDRD,
  20.                      //   read addressed by ADDRC
  21.       .DID(DID),     // RAM 2-bit data write input addressed by ADDRD,
  22.                      //   read addressed by ADDRD
  23.       .WCLK(WCLK),   // Write clock input
  24.       .WE(WE)        // Write enable input
  25.    );
复制代码

2) 64 X 1 Single Port Distributed RAM (RAM64X1S)
对于64X1的单口RAM只要使用一个LUT就够了,地址A0-A5和WA0-WA5接到一起,当WE为1的时候为写操作,当WE为0的时候为读操作。
image.jpg
原语调用:
  1.    RAM64X1S #(
  2.       .INIT(64'h0000000000000000) // Initial contents of RAM
  3.    ) RAM64X1S_inst (
  4.       .O(O),        // 1-bit data output
  5.       .A0(A0),      // Address[0] input bit
  6.       .A1(A1),      // Address[1] input bit
  7.       .A2(A2),      // Address[2] input bit
  8.       .A3(A3),      // Address[3] input bit
  9.       .A4(A4),      // Address[4] input bit
  10.       .A5(A5),      // Address[5] input bit
  11.       .D(D),        // 1-bit data input
  12.       .WCLK(WCLK),  // Write clock input
  13.       .WE(WE)       // Write enable input
  14.    );
复制代码
3) 64 X 1 Dual Port Distributed RAM (RAM64X1D)
对于双口RAM,如下图所示,使用了2个LUT,第一个LUT的读写地址是连接到一起的,而第二个LUT的写地址和对一个LUT的写地址连接到一起,但是读地址是独立,所以双口RAM可以同时进行读和写操作。
image.jpg
原语调用:
  1. RAM64X1D #(
  2.       .INIT(64'h0000000000000000) // Initial contents of RAM
  3.    ) RAM64X1D_inst (
  4.       .DPO(DPO),     // Read-only 1-bit data output
  5.       .SPO(SPO),     // Rw/ 1-bit data output
  6.       .A0(A0),       // Rw/ address[0] input bit
  7.       .A1(A1),       // Rw/ address[1] input bit
  8.       .A2(A2),       // Rw/ address[2] input bit
  9.       .A3(A3),       // Rw/ address[3] input bit
  10.       .A4(A4),       // Rw/ address[4] input bit
  11.       .A5(A5),       // Rw/ address[5] input bit
  12.       .D(D),         // Write 1-bit data input
  13.       .DPRA0(DPRA0), // Read-only address[0] input bit
  14.       .DPRA1(DPRA1), // Read-only address[1] input bit
  15.       .DPRA2(DPRA2), // Read-only address[2] input bit
  16.       .DPRA3(DPRA3), // Read-only address[3] input bit
  17.       .DPRA4(DPRA4), // Read-only address[4] input bit
  18.       .DPRA5(DPRA5), // Read-only address[5] input bit
  19.       .WCLK(WCLK),   // Write clock input
  20.       .WE(WE)        // Write enable input
  21.    );
复制代码

4) 128 X 1 Single Port Distributed RAM (RAM128X1S)
理解了前面的内容,理解128X1的RAM就不难了,下图中可以看出来,通过2个LUT的组合使用可以串联实现更大深度的分布式RAM。下图中出现了F7BMUX的加入,F7BMUX可以用于LUT输出的选通。
image.jpg

原语调用:
  1.    RAM128X1S #(
  2.       .INIT(128'h00000000000000000000000000000000) // Initial contents of RAM
  3.    ) RAM128X1S_inst (
  4.       .O(O),        // 1-bit data output
  5.       .A0(A0),      // Address[0] input bit
  6.       .A1(A1),      // Address[1] input bit
  7.       .A2(A2),      // Address[2] input bit
  8.       .A3(A3),      // Address[3] input bit
  9.       .A4(A4),      // Address[4] input bit
  10.       .A5(A5),      // Address[5] input bit
  11.       .A6(A6),      // Address[6] input bit
  12.       .D(D),        // 1-bit data input
  13.       .WCLK(WCLK),  // Write clock input
  14.       .WE(WE)       // Write enable input
  15.    );
复制代码
5) 128 X 1 Dual Port Distributed RAM (RAM128X1D)
128x1的双口RAM需要4个LUT实现,正好是一个SLICEM,并且分别使用了F7BMUX和F7AMUX.
image.jpg
原语调用:
  1.    RAM128X1D #(
  2.       .INIT(128'h00000000000000000000000000000000)
  3.    ) RAM128X1D_inst (
  4.       .DPO(DPO),   // Read port 1-bit output
  5.       .SPO(SPO),   // Read/write port 1-bit output
  6.       .A(A),       // Read/write port 7-bit address input
  7.       .D(D),       // RAM data input
  8.       .DPRA(DPRA), // Read port 7-bit address input
  9.       .WCLK(WCLK), // Write clock input
  10.       .WE(WE)      // Write enable input
  11.    );
复制代码
6)256 X 1 Single Port Distributed RAM (RAM256X1S)
256x1的单口RAM需要4个LUT实现,也正好是一个SLICEM,并且分别使用了F7BMUX和F7AMUX以及一个F8MUX.

image.jpg
原语调用:
  1.    RAM256X1S #(
  2.       .INIT(256'h0000000000000000000000000000000000000000000000000000000000000000)
  3.    ) RAM256X1S_inst (
  4.       .O(O),       // Read/write port 1-bit output
  5.       .A(A),       // Read/write port 8-bit address input
  6.       .WE(WE),     // Write enable input
  7.       .WCLK(WCLK), // Write clock input
  8.       .D(D)        // RAM data input
  9.    );
复制代码
3.6分布式ROM(Distributed ROM)
SLICEL中的每个LUT都可以实现64 x 1位ROM。提供三种配置:ROM64X1,ROM128X1和ROM256X1。 ROM内容会在每种设备配置中加载。 下表显示了每种ROM配置大小所占用的LUT数量。
image.jpg
  1.    ROM32X1 #(
  2.       .INIT(32'h00000000) // Contents of ROM
  3.    ) ROM32X1_inst (
  4.       .O(O),   // ROM output
  5.       .A0(A0), // ROM address[0]
  6.       .A1(A1), // ROM address[1]
  7.       .A2(A2), // ROM address[2]
  8.       .A3(A3), // ROM address[3]
  9.       .A4(A4)  // ROM address[4]
  10.    );
  11.    ROM64X1 #(
  12.       .INIT(64'h0000000000000000) // Contents of ROM
  13.    ) ROM64X1_inst (
  14.       .O(O),   // ROM output
  15.       .A0(A0), // ROM address[0]
  16.       .A1(A1), // ROM address[1]
  17.       .A2(A2), // ROM address[2]
  18.       .A3(A3), // ROM address[3]
  19.       .A4(A4), // ROM address[4]
  20.       .A5(A5)  // ROM address[5]
  21.    );
  22.    ROM128X1 #(
  23.       .INIT(128'h00000000000000000000000000000000) // Contents of ROM
  24.    ) ROM128X1_inst (
  25.       .O(O),   // ROM output
  26.       .A0(A0), // ROM address[0]
  27.       .A1(A1), // ROM address[1]
  28.       .A2(A2), // ROM address[2]
  29.       .A3(A3), // ROM address[3]
  30.       .A4(A4), // ROM address[4]
  31.       .A5(A5), // ROM address[5]
  32.       .A6(A6)  // ROM address[6]
  33.    );
  34.    ROM256X1 #(
  35.       .INIT(256'h0000000000000000000000000000000000000000000000000000000000000000) // Contents of ROM
  36.    ) ROM256X1_inst (
  37.       .O(O),   // ROM output
  38.       .A0(A0), // ROM address[0]
  39.       .A1(A1), // ROM address[1]
  40.       .A2(A2), // ROM address[2]
  41.       .A3(A3), // ROM address[3]
  42.       .A4(A4), // ROM address[4]
  43.       .A5(A5), // ROM address[5]
  44.       .A6(A6), // ROM address[6]
  45.       .A7(A7)  // ROM address[7]
  46.    );
复制代码

3.7移位寄存器(Shift Register)
是不是有点累了,是不是有点云里雾里了?但是这些知识很少在书本里面出现,只要不是大家都容易获取到学习到的内容,你掌握了,你就是大神了,所以坚持住。打好FPGA的底层硬件基础,为我们成为FPGA技术大神添砖加瓦。
前来重点讲解了基于SLICELM实现的RAM,这里的移位寄存器功能也是非常重要的。
SLICEM中的LUT可以配置为32位移位寄存器,而无需使用slice中可用的触发器。 以这种方式使用,每个LUT可以将串行数据延迟1到32个时钟周期。 移入D(DI1 LUT引脚)和移出Q31(MC31 LUT引脚)线路将LUT级联,以形成更大的移位寄存器。 因此,SLICEM中的四个LUT被级联以产生高达128个时钟周期的延迟。
32位移位寄存器调用原语:
image.jpg


举例说明了在7系列FPGA Slice(一个配置为SRL的LUT)中实现的移位寄存器的时序特性
image.jpg
Slice SRL Timing Characteristics
如下图所示,1个SLICEM内的4个LUT级联后可以实现128bit的移位寄存器
image.jpg

3.8多路复选器(Multiplexers)
7系列FPGA中的LTU和相关的多路复选器可以实现以下功能:
•使用一个LUT的4:1多路复选器
•使用两个LUT的8:1多路复选器
•使用四个LUT的16:1多路复选器
4:1复选器
1个LUT可以配置为4:1多路复选器。 4:1多路复选器可以通过触发器在同一片中实现。 一个slice中最多可以实现四个4:1多路复选器,如下所示:
image.jpg
以LUTA为例不经过D触发器的对应代码:
  1. always@(*)
  2.     case (SELA[1:0])
  3.      2'b00: A = DATA_A[0];
  4.      2'b01: A = DATA_A[1];
  5.      2'b10: A = DATA_A[2];
  6.      2'b11: A = DATA_A[3];
  7.      default:A = 1'bx;
  8.      endcase
复制代码
继续以LUTA为例经过D触发器的对应代码:
  1. always@(posedge CLK)
  2.     case (SELA[1:0])
  3.      2'b00: A <= DATA_A[0];
  4.      2'b01: A <= DATA_A[1];
  5.      2'b10: A <= DATA_A[2];
  6.      2'b11: A <= DATA_A[3];
  7.      default:A < = 1'bx;
  8.      endcase
复制代码
8:1复选器
每个slice具有一个F7AMUX和一个F7BMUX。
F7AMUX和F7BMUX原语:
  1.   MUXF7 MUXF7_inst (
  2.       .O(O),    // Output of MUX to general routing
  3.       .I0(I0),  // Input (tie to LUT6 O6 pin)
  4.       .I1(I1),  // Input (tie to LUT6 O6 pin)
  5.       .S(S)     // Input select to MUX
  6.    );
复制代码
这两个多路复选器组合了两个LUT的输出,以形成多达13个输入(或8:1多路复选器)的组合功能。 一个slice中最多可以实现两个8:1 MUX,如下图所示。
image.jpg
以LUTA和LUTB组从的8:1复选器为例不经过D触发器的对应代码:
  1. always@(*)
  2.     if(AX)begin
  3.         case (SELA[1:0])
  4.         2'b00: A = DATA_A[0];
  5.         2'b01: A = DATA_A[1];
  6.         2'b10: A = DATA_A[2];
  7.         2'b11: A = DATA_A[3];
  8.         default:A = 1'bx;
  9. endcase
  10.     end
  11. else begin
  12.         case (SELB[1:0])
  13.         2'b00: B = DATA_B[0];
  14.         2'b01: B = DATA_B[1];
  15.         2'b10: B = DATA_B[2];
  16.         2'b11: B = DATA_B[3];
  17.         default:B = 1'bx;
  18. endcase
  19. end
  20. assign AMUX = AX ? A : B;
复制代码
以上是没有经过优化的代码,代码可以优化为:
  1. always@(*)
  2.     case ({AX,SELB[1:0]})
  3.      3'b000: AMUX = DATA_A[0];
  4.      3'b001: AMUX = DATA_A[1];
  5.      3'b010: AMUX = DATA_A[2];
  6.      3'b011: AMUX = DATA_A[3];
  7.      3'b100: AMUX = DATA_B[0];
  8.      3'b101: AMUX = DATA_B[1];
  9.      3'b110: AMUX = DATA_B[2];
  10.      3'b111: AMUX = DATA_B[3];
  11.      default: AMUX = 1'bx;
  12. endcase
复制代码
继续以以LUTA和LUTB组从的8:1复选器为例经过D触发器的对应代码:
  1. always@(posedge CLK)
  2.     case ({AX,SELB[1:0]})
  3.     3'b000: AMUX <= DATA_A[0];
  4.     3'b001: AMUX <= DATA_A[1];
  5.     3'b010: AMUX <= DATA_A[2];
  6.     3'b011: AMUX <= DATA_A[3];
  7.     3'b100: AMUX <= DATA_B[0];
  8.     3'b101: AMUX <= DATA_B[1];
  9.     3'b110: AMUX <= DATA_B[2];
  10.     3'b111: AMUX <= DATA_B[3];
  11.     default: AMUX <= 1'bx;
  12. endcase
复制代码
16:1复选器
每个slice都有一个F8MUX。
F8MUX原语:
  1. MUXF8 MUXF8_inst (
  2.       .O(O),    // Output of MUX to general routing
  3.       .I0(I0),  // Input (tie to MUXF7 L/LO out)
  4.       .I1(I1),  // Input (tie to MUXF7 L/LO out)
  5.       .S(S)     // Input select to MUX
  6.    );
复制代码
F8MUX组合了F7AMUX和F7BMUX的输出,以形成多达27个输入(或16:1多路复选器)的组合功能。 一个slice中只能实现一个16:1多路复选器,如图下图所示。
image.jpg

16:1复选器不经过D触发器的对应代码:
  1. always@(*)
  2.     case ({BX,AX,SELB[1:0]})
  3.      4'b0000: AMUX = DATA_A[0];
  4.      4'b0001: AMUX = DATA_A[1];
  5.      4'b0010: AMUX = DATA_A[2];
  6.      4'b0011: AMUX = DATA_A[3];
  7.      4'b0100: AMUX = DATA_B[0];
  8.      4'b0101: AMUX = DATA_B[1];
  9.      4'b0110: AMUX = DATA_B[2];
  10.      4'b0111: AMUX = DATA_B[3];
  11.      4'b1000: AMUX = DATA_C[0];
  12.      4'b1001: AMUX = DATA_C[1];
  13.      4'b1010: AMUX = DATA_C[2];
  14.      4'b1011: AMUX = DATA_C[3];
  15.      4'b1100: AMUX = DATA_D[0];
  16.      4'b1101: AMUX = DATA_D[1];
  17.      4'b1110: AMUX = DATA_D[2];
  18.      4'b1111: AMUX = DATA_D[3];
  19.      default: AMUX = 1'bx;
  20. endcase
复制代码
16:1复选器经过D触发器的对应代码:
  1. always@(posedge CLK)
  2.     case ({BX,AX,SELB[1:0]})
  3.      4'b0000: AMUX <= DATA_A[0];
  4.      4'b0001: AMUX <= DATA_A[1];
  5.      4'b0010: AMUX <= DATA_A[2];
  6.      4'b0011: AMUX <= DATA_A[3];
  7.      4'b0100: AMUX <= DATA_B[0];
  8.      4'b0101: AMUX <= DATA_B[1];
  9.      4'b0110: AMUX <= DATA_B[2];
  10.      4'b0111: AMUX <= DATA_B[3];
  11.      4'b1000: AMUX <= DATA_C[0];
  12.      4'b1001: AMUX <= DATA_C[1];
  13.      4'b1010: AMUX <= DATA_C[2];
  14.      4'b1011: AMUX <= DATA_C[3];
  15.      4'b1100: AMUX <= DATA_D[0];
  16.      4'b1101: AMUX <= DATA_D[1];
  17.      4'b1110: AMUX <= DATA_D[2];
  18.      4'b1111: AMUX <= DATA_D[3];
  19.      default: AMUX <= 1'bx;
  20. endcase
复制代码
3.9进位逻辑(Carry Logic)
Slice中除了LUT,寄存器,触发器,锁存器外,还提供了专用的快速超前进位逻辑, 可以在slice中执行快速算术加法和减法。
CLB中的专用进位逻辑提高了算术功能(如加法器,计数器和比较器)的性能。包含简单计数器或加法器/减法器的设计会自动推断进位逻辑。如果是更复杂的乘法器可以使用单独的DSP48E1 Slice实现。
7系列FPGA CLB具有两个独立的进位链,如图下所示,1个CLB中的2个Slice各有1个CIN。
image.jpg

进位链可级联以形成更宽的加/减逻辑,如图下图所示。
image.jpg

进位链向上延伸,每个slice的高度为4bits。对于每个bit,都有一个进位多路复选器(MUXCY)和专用的XOR门,用于用选定的进位位加/减操作数。专用的进位路径和进位多路复选器(MUXCY)也可以用于级联LUT,以实现广泛的逻辑功能。如下图所示:
image.jpg

  1. CARRY4 CARRY4_inst (
  2.       .CO(CO),         // 4-bit carry out
  3.       .O(O),           // 4-bit carry chain XOR data out
  4.       .CI(CI),         // 1-bit carry cascade input
  5.       .CYINIT(CYINIT), // 1-bit carry initialization
  6.       .DI(DI),         // 4-bit carry-MUX data in
  7.       .S(S)            // 4-bit carry-MUX select input
  8.    );
复制代码
进位链与功能生成器一起使用进位超前逻辑。有10个独立输入和8个独立输出:
•输入
•S输入S0至S3
-进位超前逻辑的“传播”信号
-来自LUT的O6输出
•DI输入-DI1至DI4
-进位超前逻辑的“生成”信号
-来自LUT的O5输出
-创建乘数
-或SLICE的BYPASS输入(AX,BX,CX或DX)
• CYINIT
-进位链的第一位的CIN
-0表示加
-1表示减
-动态第一进位位的AX输入
•CIN
-级联Slice以形成更长的进位链
•输出
•O输出-O0至O3
-包含加法/减法之和
•CO输出-CO0到CO3
-计算每一位的进位
-CO3连接到Slice的COUT输出以通过级联多个Slice形成更长的进位链-创建加法器/累加器
4其他资源
对于入门掌握FPGA,了解FPGA的CLB是必须的,当然除了CLB还有IO资源、时钟资源、高速GTP/GTX资源等,我们在后续的学习中,在相关的课程中继续解密FPGA的其他资源结构。
5总结
本文对于如何选型FPGA,以及如何使用FPGA的LUT资源起到理论支持作用,在后面编程的时候,也有利于加深理解硬件编程语言和硬件电路的对应关系。


d724cba44af5489ebb77e4a1f7ee27ad.jpg
b103411b669d4b62aecd4ef9402b1054.jpg
68c06961aebc43c5ba5e176927d14cee.jpg
fedca495fceb4a148be53f8b693cc75c.jpg
6d38679a253d4624a2eeffda2fc8369a.jpg
8bfc370ee48a402c961dac02527db629.jpg
b8212718499244eaa4612279611af2fd.jpg
9c9766c85c5941308cbd61c8c5650fa8.jpg
0f7c5c546fee4b44929585f226ffad74.jpg
1c63f6e09b064188840760873661f05c.jpg
0b9ebc258065436a9ec79d75567b9302.jpg
b976d0c1abfb478498a52f105d79d929.jpg
3a86d34626bf4abfac5bfdd4d8d9242d.jpg
5a6e887b251b4b48a897d3e4e133b6c3.jpg
160f5493ee7f4760a231aa529fc630dc.jpg
44d250236ceb4a6ca6e156ce91a71eea.jpg
c1aa9c4645ac48419afa4a66ac8f1fa5.jpg
e9e62d9c764640abbc641f700b95c415.jpg
cd90144aec9d41e696ebd966b1c48906.jpg
18a7a0057b4a45cf8e28518fbecd3e84.jpg
bcb75ed6420145518836fcd12f1b3fa0.jpg
a8a102345e4c4db393bb4c02166c9830.jpg
f0ed4887f02d4d22a4b628e623a8d2e5.jpg
bf602cf997834b56ac2b24632125c221.jpg
9acf2ce8922941cbb02106e44d05efb4.jpg
f268ee6f164d4b6993615b742ffc9816.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则