1、Xilinx FPGA 内部结构深入分析Xilinx FPGA 内部结构深入分析作者 :fpga001。论坛 :芯片动力(SocVista)。网页地址 :IOB的结构请大家看到手册的第1页,这是IOB的review部分。IO block 是高手的领地,一般接触FPGA第一年都不会太关心到这个部分。注意看,IOB有三个数据通道:输入、输出、三态控制。每个通道都有一对存储器件,他们可以当做寄存器或者锁存起来使用,视乎你的设置。输入通道有可编程的延迟模块,可以确保hold time为零。(这是在什么场合使用?请达人补充!)另外可以看到输入输出通道都有完备的DDR支持,这个在后面可以看到。所有图都请参
2、考PDF原文,这里就不再粘贴了。可编程输入延迟看到手册第3页,这个像两根鱼骨似的构造就是输入延迟了。输入延迟一共16节,每节250ps,所以总共的延迟在04ns之间。这个鱼骨的构造非常巧妙,前面8节直接级联,只有一个输出。这样8节以内的调整就跳过这根长鱼骨;而超过8节的调整就直接利用第一根鱼骨,然后在后面的8节中进行微调。调整的输出分别供给IOB中的异步和同步单元,异步就是直接穿过IOB,同步则是经由存储单元流出IOB。异步单元精度较高,可以单节调整,所以精度为250ps;同步单元精度稍低,两个节为单位调整,所以精度只有500ps。上述内容看图便知可编程输入延迟的设置输入延迟的设置只能在Ima
3、ge配置的时候建立,在设备工作期间无法改变。我想有两种方法可以改变输入延迟的设置:1. 通过延迟原语在代码中设置;2. 通过FPGA editor在P&R完成后在ngc文件中修改。存储单元存储单元可以配置为D触发器,就是我们常说的FF,Xilinx称之为FD;也可以配置为锁存器,Xilinx称之为LD。输出和三态通路各有一对寄存器外加一个MUX。利用这种2+1的组合可以产生DDR操作,Xilinx称之为ODDR2。每个存储单元都有6个接口信号:时钟+时钟时能,数据输入+输出,置位复位+翻转输入除了这些信号,存储单元还有一些属性设置:- FF/Latch可以用来配置存储单元的类型;- Sync/
4、Async 配置置位复位的方式;- SRHIGH/SRLOW 配置是置位(1)还是复位(0);INIT1/INIT0 配置置位复位的初始值,一般置位(1)复位(0);DDR支持输入、输出、三态。这三个IOB通道都可以实现DDR支持。输出和三态通道可以实现ODDR2原语,这个原语的实现原理可以参考p5的图3.两个相差180度的时钟和两路信号进入一对寄存器并通过DDR专用MUX输出,即可得到DDR数据输出。实现相差180度,有两种方法。一种是通过DCM直接产生这两个信号。另外的方法是同一时钟,但是连入寄存器的时钟端口时,一路取反。输入通道则实现 IDDR2原语。如果输出、三态通路实现的是DDR的调
5、制的话,这一路其实就是DDR的解调,也就是1分为2。当然,这里需要提供两路相差180度的时钟。另外ODDR2还有一个重要用途,就是用于产生随路时钟。只要把两路数据固定为1和0,这样产生的DDR数据其实就是0/1交叉的时钟信号了,这个一想就明白了吧。这样做的好处是:数据和时钟都经过IOB寄存器处理,具有相同的延迟特性,从而实现了所谓的源同步“级联”重定时特性提高DDR的性能在IDDR2和ODDR2的典型实现(图4图6)中,存在一个问题.以IDDR2为例,我们可以发现,在经典实现中,输出的两路数据分别与时钟的两个边沿对齐。但是,强调一下,后端的系统中往往只有一个时钟,工作在上升沿。那么对于下降沿对
6、齐输出的数据,从下降沿开始到上升沿被采样,只有半个时钟的余量来稳定输出并满足setup。由于FPGA系统比较复杂从IOB出来的数据要进入到下一个存储单元可能会经历非常漫长的逻辑和路由延迟。要在半个时钟内完成,有很大的挑战性,尤其是在高速系统中,往往有很大的困难。Spartan3E的解决办法是,利用相邻从属IOB的存储单元,对下降沿输出的数据马上做一次上升沿抽样。由于两个IOB相邻,不存在复杂的逻辑和路由延迟,因此虽然余量也是半个时钟,但一般情况下甚至高速系统下也可以成功实现。这样数据就回到了上升沿时钟域。到了上升沿时钟域,则数据有一个时钟的时间余量,处理起来就和普通的情况一样了。以上是关于ID
7、DR2的讨论,对于ODDR2有着类似的情况,大家可以自己理解一下。参考图6图7即可。想到一个资源守恒的公理,就是自然界普遍存在的trade off 现象。如果添加一个寄存器抽样,则系统负担降低;反之如果想少使用资源,不使用这个抽样寄存器,则全系统的负担会提高。这个例子告诉我们两个道理1. trade off 普遍存在2. 四两可以拨千斤SelectIO 信号标准S3E可以支持很多接口信号标准,比如最常见的 LVTTL、LVCMOS系列、PCI系列。此外,还支持差分信号标准,典型的比如LVDS系列。要实现指定的信号标准有两个必要条件:1. 内在设置:在UCF文件中对指定pin设置IOSTANDA
8、RD属性,这样FPGA会自动切换指定IOB的信号标准;2. 外在设置:每个信号标准都要求指定的Vcco(有些还要求指定的Vref),因此要在PCB板上提供相应的Vcco支持。再来说说差分信号,他的优点是差分信号固有的噪声消除特性来提高数据的可靠性,从而提高单路数据的传输速率。差分信号的命名有套规则,比如:IO_L43P_3和IO_L43N_3就表示 Bank3里面第43对差分线的正负两根线。差分信号的termination差分信号一般传输速率较高,因此对信号的完整性有严格要求。方法之一就是使用termination来防止信号反射。为了减少用户的外部负担,S3E实现了内部的差分terminati
9、on。使用方法就是在UCF中加入下列语句。INST DIFF_TERM = ;上拉下拉电阻pullup、pulldown的主要目的就是将悬空的管脚引导到确定的状态,避免未知的干扰。所以在悬空的管脚,确定输入的管脚以及三态管脚上用的比较多。要修改管脚的pullup、pulldown、float 属性,可以在BitGen的时候从Generate Programming File的属性中选择保持电路三态信号在没有驱动的时候悬空,为了防止悬空,有一个保持电路可以帮助信号保持在前一逻辑状态。具体使用方法- 使用 KEEPER 属性- 使用 KEEPER 库原语注意,如果使用了上下拉电阻,则该属性被重置,
10、因为实现的功能是类似的。差异是上下拉将悬空信号拉回确定值,而KEEPER是保持回前一逻辑值。电平转换速率 SlewRateSlewRate用于设置IOB输出电平的切换速率。速率太低则很多接口时序得不到保障,因此有时候需要使用高速的切换速率。实现的方法就是加大驱动电流,从2mA到16mA,每2mA有一个选择。电流越大,当然驱动能力越强,相应的电平切换速率也更快。但是高速的切换会导致PCB电路的传输线效应,所以只要能满足应用,尽量采用低速的SlewRateBank内的IOB组织S3E的四边各有一个IOB 的BanK。每个Bank可以有自己独立的Vcco和Vref,所以一般的,每个bank可以有自己
11、独立的电平标准。有些电平标准有相同的Vcco,则在该Bank内可以支持多个电平标准。对于差分信号,每个Bank都可以支持下面三个差分标准中的任意两个- LVDS_25- MINI_LVDS_25- RSDS_25但是不能做到同时支持这三个标准Bank内部电平标准的规则Vcco规则:- 所有Vcco必须连接,即使不使用某个bank;- 同属于某个Bank的所有Vcco必须设置为相同的电平- 所有Vcco必须和指定的电平标准电压相符- 如果某个bank没有指定电平标准,则将其连接到任意电平,比如2.5或者3.3VVref规则:(前提是该电平标准要求使用Vref)- 所有Vref必须连接,即使不使用
12、某个bank;- 同属于某个Bank的所有Vref必须设置为相同的电平- 所有Vref必须和指定的电平标准电压相符如果某个bank对应的电平标准不需要Vref来偏置输入切换门限,则该Vref管脚可以用做用户IO或者输入管脚。专用的输入管脚专用输入管脚一般用IP_Lxxx_x 表示。对于专用输入管脚,没有差分termination。静电保护在每个IO上都有静电保护,大家看文档的图1就明白了。在pad-Vcco之间有P-N偏置保护。在pad-GND之间有N-P偏置保护。在静电过大的时候,通过这两个保护二极管可以直接将电流泄洪到电源与地IOB的电源支持Vcco用于对驱动输出的支持。Vccint用于驱
13、动内部逻辑。Vccaux是辅助电源,用于优化FPGA性能(这个谁有补充?)在上电、配置、用户模式下,IO的行为分析- 上电状态首先,电源稳定。Vcco、Vccint、Vccaux 作为内部“上电复位电路”的必要电源输入,必须达到稳定状态。这些基本电源稳定了才能实现上电复位,芯片才能进入配置状态。其次,IO高阻上拉,切断外部接口。HSWAP管脚被施加一个低电平。注意,这个低电平会维持到配置结束。这个低电平的作用是将用户IO全部上拉。我想这样做的目的是令所有IO进入确定状态,避免对配置操作的干扰。最后,全局复位,切断边缘存储通道。FPGA内部设置“全局置位复位”,异步方式将所有IOB存储单元清零-
14、 配置阶段首先,确定配置模式。INIT_B 高电平,并抽样M0,M1,M2的值,据此确定配置模式。然后,下载数据到FPGA。注意,整个配置期间,IO继续保持高阻上拉状态。最后,释放GSR。释放全局GSR,IOB寄存器回到默认的Low状态,除非设计中改变了SR输入的极性,否则都是Low状态。- Design Operation阶段首先,全局三态释放,打通外部接口。GTS释放,令所有IO都进入活跃状态,未使用的 IO则被弱下拉。通过在BitGen中设置属性,可以修改GTS释放后未使用IO的状态设置,比如上拉、下拉、悬空。其次, 全局写使能,打通内部存储通道。在一个时钟后,GWE全局写使能被释放。这
15、样RAM和寄存器就都可以写入了,也就是设计可以动作起来了。注意,在该阶段HSWAP释放,所以他也可以被用作普通的GPIO。【上面的这个内容是写到现在最重要的一部分,对于理解整个FPGA的启动过程非常有帮助。】CLB概览CLB是可配置逻辑块的简称。这是FPGA整个矩形配置结构中的基本单元。1CLB = 2X2 Slice1Slice = 2 (LUT+FF)+ 其他运算、进位、MUX资源每个CLB都是相同的,所以知道一个就知道了全部。接下来重点研究CLB。Slice上面讲到了一个CLB有2*2个Slice。这个4个slice可以分成左右两对,我们来看他们的主要区别。左边的是SLICE-M,带有存
16、储增强功能(分布式存储器,移位寄存器等)。右边的是SLICE-L,没有存储增强功能。那么为什么左右不一样呢?我认为,提供SLICE-M的目的就是为了让通用FPGA能够对存储应用有更多支持。那为什么右边的没有存储增强呢?最重要的原因是减小CLB右侧的面积,从而降低整个芯片的价格成本。同时,纯粹的logic设计可以提供比混杂设计的SLICE-M更优的性能。Logic Cell 的概念Slice 结构概览终于讲到Slice了。这个是研究FPGA的重中之重。接下来要分成若干小点分别讲述,如果要观察全部结构则最好参考14页的图12.这个图是Slice-M的结构图,注意里面的虚线部分是SliceM专有结构
17、,在slice-L中并不存在。通过比较,SliceL的结构也就非常清晰了。逻辑通路与bypass通路一个slice可以简单分成上下两部分,两部分的结构基本一致,有着近乎相同的元素。下半部分一般冠以前缀或者后缀“F”,上半部分则冠以前缀或者后缀“G”。现在以F为例,来研究一下主要的数据通路。参考的图片主要还是14页的图12,这个图太经典了。先来说明一下逻辑路径,这个路径必然经过LUT,否则就不能成为逻辑路径,而只能成为旁路路径。总结一下,主要的逻辑路径是5个:1. 从LUT输出后,再通过X口,离开CLB2. 从LUT输出后再经过XOR运算(加法或乘法应用),再通过X口,离开CLB3. 从LUT输
18、出后再经过F5MUX(等价于LUT-5扩展),在通过X口或者F5,离开CLB4. 上述三种情况中,不从X口输出,而是经由FF输出,通过XQ,离开CLB5. 从LUT输出后再经过CYMUX,参与到加法运算的进位链中大家有兴趣的话,可以自己用笔标示一下这些通路,非常清晰。如果要记忆的话,其实也很简单,一是逻辑运算后的直接输出和寄存器输出;二是加法、乘法的直接输出和寄存器输出;三是LUT4到LUT5甚至更多级的运算扩展输出。资料中还提到了旁路bypass通路,这个通路的特点是必然不经过LUT,所以称为旁路。旁路的应用比较多,但是为了集中精力,这里不再展开,大家自己研究吧。LUT 查找表LUT就是 l
19、ookup table的简称,可以称为查找表。因为一个逻辑运算的与非门实现和ROM形式的查找表实现是完全等价的,这个在数电知识里学过的。在FPGA中,逻辑电路的实现,主要就是依靠LUT。当然在SliceM中,LUT的能力更强,可以被配置成为 Distributed RAM 或者 16位移位寄存器。此外,在Spartan3E中,所有的LUT都是LUT-4也就是4输入的,但是他们可以扩展为LUT-5/6/7/8,方法就是我们接下来要介绍的wide MUXWide Multiplexers构造高阶LUTi的神兵利器有了LUT4,如何实现LUT5?这个问题的答案其实很简答。对于4位输入的逻辑可以用LU
20、T实现,那么对于一个5位输入的实现,就可以这样来做。首先假设第5比特为0,在这个前提下,5位逻辑就变成了4位逻辑,用一个LUT4(F)实现。然后假设第5比特为1,在这个前提下,5位逻辑也变成了4位逻辑,用另一个LUT4(G)实现。最后,我们把这两个LUT4的输出值用一个MUX连接,当第5比特为0,我们就选通F,为1则选通G。这样通过整合两个LUT4和一个MUX,另外用第5比特作为选通信号,我们得到了一个等价的LUT5。循环使用上述方法,我们可以进一步得到LUT-6/7/8.可以发现这里非常重要的一个资源就是MUX,Spartan3E称为wide multiplexer。在一个Slice中,下半
21、部分只提供F5MUX,也就是用于构造LUT5的MUX。而在上半部分中则没有F5MUX,因为一个slice刚好两个LUT4,有一个F5MUX就够了。但是上半部分提供了一个FiMUX,这个i可以是6、7、8。这样,上半部的FiMUX就为扩展更大规模的LUT-i提供了物质基础。如果要细究一下哪些slice提供F6/7/8 MUX,可以这样来归纳。一个CLB中的下面两个slice,只能提供F6MUX。上面的两个slice中,SliceM提供F7MUX,SliceL提供F8MUX。另外,LUT作为4比特逻辑能够实现2:1MUX功能,因此借助wide MUX可以实现更高阶的MUX。最后重点关注一下F5MU
22、X中提高性能的一个细节。F5MUX的选通输出,如果要构造LUT-6,就可以直接将输出绕回本Slice的F6MUX。为此,F5MUX特意创建了两个输出口,一个输出到CLB外,一个则利用本地反馈电路快速绕回到FiMUX进行级联。进位与算术逻辑这是Slice结构部分的高阶知识。Slice的主角是LUT,他有个缺陷,就是比较适合完成普通的逻辑设计,也就是单比特输出的运算。但是在设计中,大量用到算术逻辑,最常见的就是乘法和加法,这些运算的特点就是多个输出。比如带进位的1比特加法运算,结果有两个比特,一个是部分和,一个是进位。如果用LUT来实现的话,这么一个简单的运算都至少需要两个LUT来完成,非常浪费。
23、为了避免这种浪费,Xilinx想出了妙计,就是在Slice中添加几个简单的XOR和AND门。这些门数量极少,但是画龙点睛,把算术逻辑激活了。比如上面的单比特加法,只使用一个LUT,然后搭配简单的几个门就搞定了,大大节省资源。我们看以参考经典的图12和图20、21,我们发现,支持算术逻辑的单元并不多。在slice的上下两侧各有这样一套资源。每套资源都是一个三元组:AND、XOR、CYMUX。结合图20、21,我们可以领悟到,这些资源其实就是为了实现“部分和”运算和“部分积”运算而实现的。从而构造出一个完整的、高效的算术逻辑运算通道。对于加法和乘法,产生部分和以及部分积是在横向完成的,并且没有积累
24、,所以时序上没有问题。但是进位链由于具有累积效应,因此必须有专门的针对性设计。我们可以看到Spartan3E里面就有这样的一条进位链自下往上,通过一堆级联的MUX快速输出。这个就是Xilinx的进位链优化电路。赞!存储单元存储单元是通用的设计,可以配置成为FF,也可以配置成为Latch。关于两者的差异,请自己查阅手册。基本上存储单元的输入数据来自两个部分:1. LUT组合逻辑输出;2. 旁路数据一个存储单元有12个输入输出口,当然配置在不同的类型下,会使用到不同的接口。D-Q 是输入输出数据信号,我给他列成一对;C-CE 是时钟和时钟使能,也是一对;G-GE 是配置为latch时的门和门使能信
25、号,又是一对;S-R 是同步set/reset信号,两者取反,所以等效于一个信号;PRE-CLR 是异步set/reset信号,两者取反,所以等效于一个信号;SR-REV和S-R以及PRE-CLR是一个系列,只不过他们是CLB的输入信号,在Slice内部,他们化身成了S-R以及PRE-CLR。注意SR是一个通用用法,你可以通过SRLOW和SRHIGH属性来将其设置为SET用途还是Reset用途。提一下REV,这个信号和SR同时作用,当他有效时,set/reset的值就取反。感觉很全面,不过又感觉好无聊,尽整一些没用的东西。分布式存储 Distributed RAM一个SliceM LUT 存储
26、16位数据 (RAM 16)。通过多个LUT的组合,可以对宽度和深度进行扩展,比如 16x4,32x2,64x1。要提高地址空间就需要有地址线的扩展,LUT4只接收4位地址,扩展的地址由BX、BY两个旁路信号提供。有了这两个信号,地址就是6位的,深度就是64。写操作是同步的,也就是和写时钟(SliceM的CLK)同步。读操作则是异步的,随时反映当前读地址的内容。接下来重点研究一下SliceM如何构造dual port RAM。这个非常巧妙。建议大家对照图12、23进行研究。注意SliceM中上面的LUT可以同时读写,而下面的是只读的。这和dual port的定义有关,dual port是一侧只
27、读、一侧只写,所以有一个LUT完全可以只读,来减小控制逻辑。由于在逻辑上只有一个存储空间,所以两块LUT的内容必须一致。这就要求所以写操作必须同时反映到两个LUT,要完成这一点,必须令写使能、写地址、写数据同时反映到两个LUT。观察图12的两个LUT的WS (写使能)、WG-WF (写地址)、D1 (写数据) 的级联关系就明白了。好了,到此我们保证了写操作的正确性和两块LUT的内容一致性。那么读操作怎么完成呢?我们观察到,除了WG-WF,还有一个名为A4:1的地址总线。这个地址总线独立于写地址总线,从而确保了独立的读操作。然后读出的数据由LUT的D端输出。作为Dualport RAM使用的时候
28、,读数据从下端LUT的D口输出。最后,介绍一个使用注意:1. INIT属性用于初始化RAM;2. 如果只要ROM功能,则SliceL也可以提供;3. 全局写使能信号GWE在配置阶段关闭,可以防止对RAM初始值的干扰;总之,通过上面的内容我们明白了,SliceM和SliceL在存储支持上的最大区别:- SliceL只能支持读功能,比如 ROM- SliceM则支持读写以及DualPort实现,因此在读写地址独立和输入数据通道等方面做了增强移位寄存器- 构造Slice-M的LUT有个优势,就是可以构造16位的移位寄存器。由于一个SliceM内有两个LUT,所以可以级联构造32位寄存器。进一步,一个
29、CLB内有上下两个SliceM,可以构造64位的移位寄存器。事实上,以此类推,多个CLB可以进一步构造更长的移位寄存器。- 例化要使用移位寄存器可以使用SRL16 (Shift Register LUT 16 bit),他有很多变种,可以构造出多种形式的近似的移位寄存器。他的输出有两个,一个是可寻址的输出,这是可变长度的移位寄存器的输出。另外一个名为MC15,是LUT中的最后一个比特,用于多个移位寄存器级联时使用。因为级联的上级SR总是从最后一个比特连到下一个SR。移位寄存器有原语,好像是SSRL16,大家可以试用一下。在Xilinx的技术文档中可以找到更多的SR形式。- 不包括FF很多人疑惑
30、,SR中是否有FF存在,其实图25清楚的回答了这个问题。可以看到SR是完全由SliceM的LUT实现的,FF不在其内。当然可以在SR之外和FF连接,构造更长的SR。Block RAM 概览在spartan3E系列中,每个FPGA基本有4-36个BRAM。每个这样的BRAM都是DualPort的、可配置的18Kbit存储器。为什么是18Kbit呢,可以这样记忆,16K做数据,2K做校验位。当然你一定要放18K数据也是可以的,但是涉及初衷肯定是考虑了校验位的需要。所以以后如果使用小的内存就用我们前面讲过的Slice(LUT)分布式RAM。如果要大块的,就不要麻烦了,直接例化BRAM。BRAM有几种主要的可配置项:- 初始值(比如可以放启动软件代码)- 端口aspect ratio,这个我会在后面介绍,简单讲就是输入输出数据长度的不对称配置- 写状态下的数据输出模式- 单端口双端口配置BRAM的片上位置BRAM和乘法器相邻,两者一起以12纵列的形式放
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1