问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 72 人浏览分享

开启左侧

第二十一课 FPGA 知识_解密 XILINX FPGA 基本单元 CLB

[复制链接]
72 0
AMD-FPGA课程
AMD课程: 04-FPGA编程基础 » FPGA硬件资源解析
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.1 Slices 单元
       一个 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,另外一种是 SLICEMSLICEM 的功能更强大,SLICEM 可以当作分布式 RAM 或者 ROM,或者实现移位寄存器。

2.2 Distributed 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.3 Logic Cells
       我们经常说到 FPGA 容量是多少,FPGA 器件的容量通常用逻辑单元来衡量,这在逻辑上等同于经典的 4 输入LUT 和触发器。 7 系列 FPGA 逻辑单元和 6 输入 LUT 的数量之比为 1.61,这是相对于经典的 4 输入 LUT 而言得出的。所以,逻辑单元和 Slice 的数量比是 6.41。我们在前面第一张表格:
image.jpg
       仍然以 XC7K325T 为例子,50950X6.4=326080。通过计算可以看到 Slices 的数量对应的逻辑单元的数量,这个计算就是等效计算,因为传统的 CPLD 是逻辑门电路,而现在的 FPGA 是以查找表的方式实现了逻辑门的等效功能。

3 认识 FPGA Slice 的功能
       每个 slice 包含:
  • •四个逻辑函数生成器(查找表)
  • •8 个存储单元
  • •多功能多路复选器
  • • 快速进位逻辑
       FPGA 的逻辑、算术和 ROM 功能就是靠 Slice 实现,其中 slice 又分 SLICEL 和 SLICEM,SLICEM 的功能更强大,除了具备 SLICEL 的所有功能,还能实现分布式 RAMROM 和实现移位逻辑。

3.1 SLICEL
image.jpg

3.2 SLICEM
image.jpg
       对比 SLICEM 和 SLICEL,可以看到以上结构图中,他们的差异在查找表上,SLICEM 的查找表结构功能更复杂。SLICEM 增加了写操作的控制信号,以及移动位进位的功能。

3.3 LUT 查找表
       由于 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 输入可以通过AFFMUXBFFMUXCFFMUX DFFMUX LUT 输出直接驱动,也可以通过 AXBXCX DX 输入绕过函数发生器的 BYPASS slice 输入直接驱动。 当配置为锁存器时,当 CLK 为低电平时,锁存器是透明的。
image.jpg
       另外四个为仅为 DFF,它们只能配置为边沿触发的 D 型触发器。 D 输入可以由 LUT 的 O5 输出驱动,也可以由AXBXCX DX 输入的 BYPASS slice 输入驱动。 当原始的四个存储单元配置为闩锁时,这四个附加的存储单元将无法使用。
       触发器代码如下,当敏感型号 CLK 上升沿到来把 B 值赋给 A:
always@(posedge CLK)
A <= B;
       锁存器代码如下,当 C 为 1 时候把 B 赋值给 A,锁存器应该尽力避免,因为会影响到电路时序收敛,对毛刺敏感,容易导致意想不到的错误。
always@(*)
if(C==1’b1)
A <= B;
       避免锁存器的代码
always@(*)
if(C==1’b1)
A <= B;
else
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,深度是 324 口代表了 4 LUT 都处于工作状态,它们的 DI0 DI1,共用,第一个 LUT A1-A5 WA1-WA5 相连接,并且 4 LUT WA1-WA5 全部接到了一起。所以我们可以同时把数据写入到每个 LUT 的地址空间,然后可以分别读出每LUT 的数据。写操作是同步写入,读操作是异步读出。4 RAM 实际上用的不多,我们重点看后面的单口 RAM和双口 RAM
image.jpg
原语调用:
RAM32M #(
.INIT_A(64'h0000000000000000), // Initial contents of A Port
.INIT_B(64'h0000000000000000), // Initial contents of B Port
.INIT_C(64'h0000000000000000), // Initial contents of C Port
.INIT_D(64'h0000000000000000) // Initial contents of D Port
) RAM32M_inst (
.DOA(DOA),
// Read port A 2-bit output
.DOB(DOB),
// Read port B 2-bit output
.DOC(DOC),
// Read port C 2-bit output
.DOD(DOD),
// Read/write port D 2-bit output
.ADDRA(ADDRA), // Read port A 5-bit address input
.ADDRB(ADDRB), // Read port B 5-bit address input
.ADDRC(ADDRC), // Read port C 5-bit address input
.ADDRD(ADDRD), // Read/write port D 5-bit address input
.DIA(DIA),
// RAM 2-bit data write input addressed by ADDRD,
//
read addressed by ADDRA
.DIB(DIB),
// RAM 2-bit data write input addressed by ADDRD,

//
read addressed by ADDRB
.DIC(DIC),
// RAM 2-bit data write input addressed by ADDRD,
//
read addressed by ADDRC
.DID(DID),
// RAM 2-bit data write input addressed by ADDRD,
//
read addressed by ADDRD
.WCLK(WCLK),
// Write clock input
.WE(WE)
// Write enable input
);


2) 64 X 1 Single Port Distributed RAM (RAM64X1S)
对于 64X1 的单口 RAM 只要使用一个 LUT 就够了,地址 A0-A5 和 WA0-WA5 接到一起,当 WE 为 1 的时候为写操作,当 WE 0 的时候为读操作。

image.jpg
原语调用:
RAM64X1S #(
.INIT(64'h0000000000000000) // Initial contents of RAM
) RAM64X1S_inst (
.O(O),
// 1-bit data output
.A0(A0),
// Address[0] input bit
.A1(A1),
// Address[1] input bit
.A2(A2),
// Address[2] input bit
.A3(A3),
// Address[3] input bit
.A4(A4),
// Address[4] input bit
.A5(A5),
// Address[5] input bit
.D(D),
// 1-bit data input
.WCLK(WCLK), // Write clock input
.WE(WE)
// Write enable input
);


3) 64 X 1 Dual Port Distributed RAM (RAM64X1D)
       对于双口 RAM,如下图所示,使用了 2 个 LUT,第一个 LUT 的读写地址是连接到一起的,而第二个 LUT 的写地址和对一个 LUT 的写地址连接到一起,但是读地址是独立,所以双口 RAM 可以同时进行读和写操作。
image.jpg
       原语调用:
RAM64X1D #(
.INIT(64'h0000000000000000) // Initial contents of RAM
) RAM64X1D_inst (
.DPO(DPO),
// Read-only 1-bit data output
.SPO(SPO),
// Rw/ 1-bit data output
.A0(A0),
// Rw/ address[0] input bit
.A1(A1),
// Rw/ address[1] input bit
.A2(A2),
// Rw/ address[2] input bit
.A3(A3),
// Rw/ address[3] input bit
.A4(A4),
// Rw/ address[4] input bit
.A5(A5),
// Rw/ address[5] input bit
.D(D),
// Write 1-bit data input
.DPRA0(DPRA0), // Read-only address[0] input bit
.DPRA1(DPRA1), // Read-only address[1] input bit
.DPRA2(DPRA2), // Read-only address[2] input bit
.DPRA3(DPRA3), // Read-only address[3] input bit
.DPRA4(DPRA4), // Read-only address[4] input bit
.DPRA5(DPRA5), // Read-only address[5] input bit
.WCLK(WCLK),
// Write clock input
.WE(WE)
// Write enable input
);


4) 128 X 1 Single Port Distributed RAM (RAM128X1S)
       理解了前面的内容,理解 128X1 的 RAM 就不难了,下图中可以看出来,通过 2 个 LUT 的组合使用可以串联实现更大深度的分布式 RAM。下图中出现了 F7BMUX 的加入,F7BMUX 可以用于 LUT 输出的选通。
image.jpg
       原语调用:
RAM128X1S #(
.INIT(128'h00000000000000000000000000000000) // Initial contents of RAM
) RAM128X1S_inst (
.O(O),
// 1-bit data output
.A0(A0),
// Address[0] input bit
.A1(A1),
// Address[1] input bit
.A2(A2),
// Address[2] input bit
.A3(A3),
// Address[3] input bit
.A4(A4),
// Address[4] input bit
.A5(A5),
// Address[5] input bit
.A6(A6),
// Address[6] input bit
.D(D),
// 1-bit data input
.WCLK(WCLK), // Write clock input
.WE(WE)
// Write enable input
);


5) 128 X 1 Dual Port Distributed RAM (RAM128X1D)
       128x1 的双口 RAM 需要 4 个 LUT 实现,正好是一个 SLICEM,并且分别使用了 F7BMUX 和 F7AMUX.
image.jpg

原语调用:
RAM128X1D #(
.INIT(128'h00000000000000000000000000000000)
) RAM128X1D_inst (
.DPO(DPO),
// Read port 1-bit output
.SPO(SPO),
// Read/write port 1-bit output
.A(A),
// Read/write port 7-bit address input
.D(D),
// RAM data input
.DPRA(DPRA), // Read port 7-bit address input
.WCLK(WCLK), // Write clock input
.WE(WE)
// Write enable input
);

6)256 X 1 Single Port Distributed RAM (RAM256X1S)
256x1 的单口 RAM 需要 4 LUT 实现,也正好是一个 SLICEM,并且分别使用了 F7BMUX F7AMUX 以及一个 F8MUX.

image.jpg
原语调用:
RAM256X1S #(
.INIT(256'h0000000000000000000000000000000000000000000000000000000000000000)
) RAM256X1S_inst (
.O(O),
// Read/write port 1-bit output
.A(A),
// Read/write port 8-bit address input
.WE(WE),
// Write enable input
.WCLK(WCLK), // Write clock input
.D(D)
// RAM data input
);

3.6 分布式 ROM(Distributed ROM)
SLICEL 中的每个 LUT 都可以实现 64 x 1 ROM。提供三种配置:ROM64X1ROM128X1 ROM256X1ROM内容会在每种设备配置中加载。 下表显示了每种 ROM 配置大小所占用的 LUT 数量。
image.jpg
ROM32X1 #(
.INIT(32'h00000000) // Contents of ROM
) ROM32X1_inst (
.O(O),
// ROM output
.A0(A0), // ROM address[0]
.A1(A1), // ROM address[1]
.A2(A2), // ROM address[2]
.A3(A3), // ROM address[3]
.A4(A4) // ROM address[4]
);
ROM64X1 #(
.INIT(64'h0000000000000000) // Contents of ROM
) ROM64X1_inst (
.O(O),
// ROM output
.A0(A0), // ROM address[0]
.A1(A1), // ROM address[1]
.A2(A2), // ROM address[2]
.A3(A3), // ROM address[3]
.A4(A4), // ROM address[4]
.A5(A5) // ROM address[5]
);
ROM128X1 #(
.INIT(128'h00000000000000000000000000000000) // Contents of ROM
) ROM128X1_inst (
.O(O),
// ROM output
.A0(A0), // ROM address[0]
.A1(A1), // ROM address[1]
.A2(A2), // ROM address[2]
.A3(A3), // ROM address[3]
.A4(A4), // ROM address[4]
.A5(A5), // ROM address[5]
.A6(A6) // ROM address[6]
);
ROM256X1 #(
.INIT(256'h0000000000000000000000000000000000000000000000000000000000000000) // Contents of ROM
) ROM256X1_inst (

.O(O),
// ROM output
.A0(A0), // ROM address[0]
.A1(A1), // ROM address[1]
.A2(A2), // ROM address[2]
.A3(A3), // ROM address[3]
.A4(A4), // ROM address[4]
.A5(A5), // ROM address[5]
.A6(A6), // ROM address[6]
.A7(A7) // ROM address[7]
);


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

SRLC32E #(
.INIT(32'h00000000) // Initial Value of Shift Register
) SRLC32E_inst (
.Q(Q),
// SRL data output
.Q31(Q31), // SRL cascade output pin
.A(A),
// 5-bit shift depth select input
.CE(CE),
// Clock enable input
.CLK(CLK), // Clock input
.D(D)
// SRL data input
);
image.jpg

       举例说明了在 7 系列 FPGA Slice(一个配置为 SRL LUT)中实现的移位寄存器的时序特性
image.jpg

       如下图所示,1 SLICEM 内的 4 LUT 级联后可以实现 128bit 的移位寄存器

image.jpg

3.8 多路复选器(Multiplexers)
       7 系列 FPGA 中的 LTU 和相关的多路复选器可以实现以下功能:
  • 使用一个 LUT 41 多路复选器
  • 使用两个 LUT 81 多路复选器
  • 使用四个 LUT 161 多路复选器

4:1 复选器
       1 LUT 可以配置为 41 多路复选器。 41 多路复选器可以通过触发器在同一片中实现。 一个 slice 中最多可以实现四个 41 多路复选器,如下所示:
image.jpg
       LUTA 为例不经过 D 触发器的对应代码:
always@(*)
case (SELA[1:0])
2'b00: A = DATA_A[0];
2'b01: A = DATA_A[1];
2'b10: A = DATA_A[2];
2'b11: A = DATA_A[3];
default:A = 1'bx;
endcase
       继续以 LUTA 为例经过 D 触发器的对应代码:
always@(posedge CLK)
case (SELA[1:0])
2'b00: A <= DATA_A[0];
2'b01: A <= DATA_A[1];
2'b10: A <= DATA_A[2];
2'b11: A <= DATA_A[3];
default:A < = 1'bx;
endcase

8:1 复选器
       每个 slice 具有一个 F7AMUX 和一个 F7BMUX
       F7AMUX F7BMUX 原语:
MUXF7 MUXF7_inst (
.O(O),
// Output of MUX to general routing
.I0(I0), // Input (tie to LUT6 O6 pin)
.I1(I1), // Input (tie to LUT6 O6 pin)
.S(S)
// Input select to MUX
);
       这两个多路复选器组合了两个 LUT 的输出,以形成多达 13 个输入(或 81 多路复选器)的组合功能。 一个slice 中最多可以实现两个 81 MUX,如下图所示。
image.jpg
       LUTA LUTB 组从的 8:1 复选器为例不经过 D 触发器的对应代码:
always@(*)
if(AX)begin
case (SELA[1:0])
2'b00: A = DATA_A[0];
2'b01: A = DATA_A[1];
2'b10: A = DATA_A[2];
2'b11: A = DATA_A[3];
default:A = 1'bx;
endcase
end
else begin
case (SELB[1:0])

2'b00: B = DATA_B[0];
2'b01: B = DATA_B[1];
2'b10: B = DATA_B[2];
2'b11: B = DATA_B[3];
default:B = 1'bx;
endcase
end
assign AMUX = AX ? A : B;

       以上是没有经过优化的代码,代码可以优化为:
always@(*)
case ({AX,SELB[1:0]})
3'b000: AMUX = DATA_A[0];
3'b001: AMUX = DATA_A[1];
3'b010: AMUX = DATA_A[2];
3'b011: AMUX = DATA_A[3];
3'b100: AMUX = DATA_B[0];
3'b101: AMUX = DATA_B[1];
3'b110: AMUX = DATA_B[2];
3'b111: AMUX = DATA_B[3];
default: AMUX = 1'bx;
endcase

       继续以以 LUTA LUTB 组从的 8:1 复选器为例经过 D 触发器的对应代码:
always@(posedge CLK)
case ({AX,SELB[1:0]})
3'b000: AMUX <= DATA_A[0];
3'b001: AMUX <= DATA_A[1];
3'b010: AMUX <= DATA_A[2];
3'b011: AMUX <= DATA_A[3];
3'b100: AMUX <= DATA_B[0];
3'b101: AMUX <= DATA_B[1];
3'b110: AMUX <= DATA_B[2];
3'b111: AMUX <= DATA_B[3];
default: AMUX <= 1'bx;
endcase

16:1 复选器
       每个 slice 都有一个 F8MUX
       F8MUX 原语:
MUXF8 MUXF8_inst (
.O(O),
// Output of MUX to general routing
.I0(I0), // Input (tie to MUXF7 L/LO out)
.I1(I1), // Input (tie to MUXF7 L/LO out)
.S(S)
// Input select to MUX

);

       F8MUX 组合了 F7AMUX F7BMUX 的输出,以形成多达 27 个输入(或 161 多路复选器)的组合功能。 一slice 中只能实现一个 161 多路复选器,如图下图所示。
image.jpg
       16:1 复选器不经过 D 触发器的对应代码:
always@(*)
case ({BX,AX,SELB[1:0]})
4'b0000: AMUX = DATA_A[0];
4'b0001: AMUX = DATA_A[1];
4'b0010: AMUX = DATA_A[2];
4'b0011: AMUX = DATA_A[3];
4'b0100: AMUX = DATA_B[0];
4'b0101: AMUX = DATA_B[1];
4'b0110: AMUX = DATA_B[2];
4'b0111: AMUX = DATA_B[3];
4'b1000: AMUX = DATA_C[0];
4'b1001: AMUX = DATA_C[1];
4'b1010: AMUX = DATA_C[2];
4'b1011: AMUX = DATA_C[3];
4'b1100: AMUX = DATA_D[0];
4'b1101: AMUX = DATA_D[1];
4'b1110: AMUX = DATA_D[2];

4'b1111: AMUX = DATA_D[3];
default: AMUX = 1'bx;
endcase

       16:1 复选器经过 D 触发器的对应代码:
always@(posedge CLK)
case ({BX,AX,SELB[1:0]})
4'b0000: AMUX <= DATA_A[0];
4'b0001: AMUX <= DATA_A[1];
4'b0010: AMUX <= DATA_A[2];
4'b0011: AMUX <= DATA_A[3];
4'b0100: AMUX <= DATA_B[0];
4'b0101: AMUX <= DATA_B[1];
4'b0110: AMUX <= DATA_B[2];
4'b0111: AMUX <= DATA_B[3];
4'b1000: AMUX <= DATA_C[0];
4'b1001: AMUX <= DATA_C[1];
4'b1010: AMUX <= DATA_C[2];
4'b1011: AMUX <= DATA_C[3];
4'b1100: AMUX <= DATA_D[0];
4'b1101: AMUX <= DATA_D[1];
4'b1110: AMUX <= DATA_D[2];
4'b1111: AMUX <= DATA_D[3];
default: AMUX <= 1'bx;
endcas

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
CARRY4 CARRY4_inst (
.CO(CO),
// 4-bit carry out
.O(O),
// 4-bit carry chain XOR data out
.CI(CI),
// 1-bit carry cascade input
.CYINIT(CYINIT), // 1-bit carry initialization
.DI(DI),
// 4-bit carry-MUX data in
.S(S)
// 4-bit carry-MUX select input
);
进位链与功能生成器一起使用进位超前逻辑。有 10 个独立输入和 8 个独立输出:
输入
•S 输入 S0 S3
-进位超前逻辑的传播信号
-来自 LUT O6 输出
•DI 输入-DI1 DI4
-进位超前逻辑的生成信号
-来自 LUT O5 输出
-创建乘数
-SLICE BYPASS 输入(AXBXCX 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 资源起到理论支持作用,在后面编程的时候,也有利于加深理解硬件编程语言和硬件电路的对应关系。





您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

10

粉丝

114

主题
精彩推荐
热门资讯
    网友晒图
      图文推荐
        
        • 微信公众平台

        • 扫描访问手机版