zhangquanling / FPGA_混饭吃的 / 高级篇:第1章 可编程逻辑设计指导原则

分享

   

高级篇:第1章 可编程逻辑设计指导原则

2011-11-05  zhangquan...

第1章 可编程逻辑设计指导原则


(1)面积和速度的平衡与互换原则。


           “面积”指一个设计所消耗FPGA/CPLD的逻辑资源数量:对于FPGA,可以用所消耗的触发器(FF)和查找表(LUT)来衡量;对于CPLD,常用宏单元(MC)衡量。


            “速度”指设计在芯片上稳定运行时所能达到的最高频率,这个频率由设计的时序状况决定,与设计满足的时钟周期、PAD to PAD time、clock setup time、clock hold time和clock-to-output delay等众多时序特征量密切相关。


            如果设计的时序余量比较大,运行的频率比较高,则意味着设计的健壮性更强,整个系统的质量更有保证;另一方面,设计所消耗的面积更小,则意味着在单位芯片上实现的功能模块更多,需要的芯片数量更少,整个系统的成本也随之大幅度消减。相比之下,满足时序、工作频率的要求更重要一些,当两者冲突时,采用速度优先的准则。


          从理论上讲,一个设计如果时序余量较大,所能跑的频率远远高于设计要求,那么就能通过功能模块复用减少整个设计消耗的芯片面积,用速度的优势换面积的节约;反之,如果设计的时序要求很高,普通方法达不到设计频率,那么一般可以通过将数据流串并转换,并行复制多个操作模块,对整个设计进行“乒乓操作”和“串并转换”的思想进行处理,在芯片输出模块处再对数据进行“并串转换”。


“面积换速度”的思想:首先将输入的高速数据进行串并转换,然后利用较低的速度对多个模块并行处理所分配的数据,最后将处理结果“并串转换”,完成数据速率的要求。这样我们在整个处理模块的两端看都是高速数据流。路由器设计的例子:


点击看大图


 


操作过程中还涉及很多的方法和技巧,例如,对高速数据流进行串并转换,采用“乒乓操作”方法提高数据处理速率等。


(2)硬件原则。


           for循环语句的使用:实际工作中,除了描述仿真测试激励(testbench)时使用for循环语句外,极少在RTL级编码中使用for循环,因为for循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,每条执行语句并不能有效地复用硬件逻辑资源,造成巨大的资源浪费。在RTL级描述中,遇到类似算法,推荐的方式是先搞清楚设计的时序要求,做一个reg型计数器,在每个时钟沿累加,并在每个时钟判断计数器情况,并相应的处理,能复用的处理模块尽量复用,即使所有操作都不能服用,也可采用case语句展开处理。


casex和casez 应用一定要小心,要注意是否可综合。


if……else……与case语句的使用:在verilog语法中,if……else……语句是有“优先级”的,一般来说第一个if的优先级最高,最后一个else的优先级最低。如果描述编码器,在有些综合器的参数中就有关于优先级编码器硬件原语的选项priority encoder extraction。而case语句是“平行”的结构,所有的case的条件和执行都没有“优先级”。而建立优先级结构(优先级树)会消耗大量的组合逻辑,所以能够使用case语句的地方尽量用case替换if……else…


(3)系统原则。


           对设计的全局有个宏观的合理安排,比如时钟域、模块复用、约束、面积和速度等问题。


          一般来说,实时性要求高、频率快的功能模块适合使用FPGA/CPLD实现。而FPGA和CPLD相比,更适合实现规模较大、频率较高、寄存器资源使用较多的设计。使用FPGA/CPLD设计时,应该对芯片内部的各种底层硬件资源、可用的设计资源有一个较深刻的认识,FPGA一般触发器资源比较丰富,CPLD组合逻辑资源更丰富一些,这直接影响着两者使用的编码风格。


        RAM资源的使用: altera高端器件(如stratix II、stratix GX、stratix等)内部同时含有3种块RAM结构,分别是M512 (512bit)RAM、M4K RAM(4kbit)、M-RAM(512kbit),其中M512 RAM适合做一些灵活的小块buffer、FIFO、DPRAM、SPRAM、ROM等;M4K RAM应用最广,适用于一般的需求;M-RAM适合做大块数据的缓冲区,如在通信的SDH/SONET传输领域,有一些900Kbit的大数据包,用M-RAM实现缓冲结构非常方便。


      软核的使用:FPGA的一个发展趋势是越来越多的FPGA产品将包含DSP或CPU等软处理核,从而FPGA将由传统的硬件设计手段逐步过渡为系统级设计工具。内嵌在FPGA之中的DSP或CPU处理模块比较适合应用于运算密集的FIR滤波器、编码解码、FFT等操作,其工作效率可以达到系统DSP和CPU 的几百倍。


       串行收发器的使用:很多高端FPGA内嵌了SERDES以完成高速串行信号的收发。SERializer和DESerializer的英文缩写,即串行收发器,它由两部分组成:发端是串行发送单元SERializer,用高速时钟调制编码数据流;接收端为串行接收单元DESerializer,其主要作用是从数据流中恢复出时钟信号,并解调还原数据,根据其功能,接收单元还有一个名称叫时钟数据恢复器(CDR,clock and data recovery)。FPGA中SERDES技术的应用很好的解决了高速系统数据传输的瓶颈,节约了单板面积,提高了系统的稳定性,是高速系统设计的强有力支撑。


     根据设计的速度要求,要合理选择器件的速度等级,并在设计中正确地分频不同速度等级的布线资源与时钟资源,需要提醒的是:选择高等级的器件和改善布线资源分配仅仅是提高芯片工作速度的辅助手段,设计速度主要由电路的整体结构、代码的coding style等因素决定,善用芯片内部的PLL或DLL资源完成时钟的分频、倍频、移相等操作不仅简化了设计,并且能有效地提高系统各的精度和稳定性。


 


(4)同步设计原则。


同步设计原则:


早期PLD设计经常采用行波计数器(ripple counter)或者异步脉冲生成器等典型的异步逻辑设计方式以节约设计所消耗的面积资源,但异步逻辑设计的时序正确性完全依赖于每个逻辑元件和布线的延迟,所以其时序相对繁杂而困难,并且极易产生亚稳态、毛刺等,造成设计稳定性下降和设计频率不高,但FPGA/CPLD的一个显著发展趋势是低成本器件不断经济化,器件资源不再成为设计的主要矛盾,而同步时序电路对全面提高设计的频率和稳定性至关重要,从这个层面上来讲,尽量使用同步时序电路更加重要。


现代PLD设计推荐采用同步时序设计方式。


 


同步时序设计的注意事项:


稳定可靠的数据采样必须遵从以下两个原则:


. setup时间原则:在有效时钟沿到达前,数据输入至少已经稳定了采样寄存器的setup时间之久。


. hold时间原则:在有效时钟沿到达后,数据输入至少还将稳定保持采样寄存器的hold时间之久。


 


同步时序电路的延迟:最常用的设计方法是用分频或倍频的时钟或者同步计数器完成所需的延迟。换句话说,同步时序电路的延迟被当做一个电路逻辑来设计,对于比较大的和特殊定时要求的演示,一般要用高速时钟产生一个计数器,根据计数器的计数控制延时;对于比较小的延时,可以用D触发器打一下,这种做法不仅仅使信号延时了一个时钟周期,而且完成了信号与时钟的初次同步,在输入信号采样和增加时序约束余量中使用,另外许多初学者用行为级(behavioral level)方法描述延时,如“#5 a <= 4’b0101;”这种行为级描述方法常用于仿真测试激励,但是在电路综合时会被忽略,并不能起到延时作用。


 


Verilog定义为reg型,不一定综合成寄存器


Verilog代码中最常用的两种数据类型是wirereg,一般来说,wire型指定的数据和网线通过组合逻辑实现,而reg型指定的数据不一定就是用寄存器实现。


 


可编程逻辑常用设计思想和技巧


4种思想和技巧:乒乓操作、串并转换、流水线操作和数据接口同步)


“乒乓操作”:常用于数据流控制的处理技巧。


       特点:


1.把乒乓操作模块当作一个整体,站在这个模块的两端看数据,输入数据流和输出数据流都是连续不断的,非常适合对数据流进行流水线式处理,因此乒乓操作常常应用于流水线式算法,完成数据的无缝缓冲与处理。


2.可以节约缓冲区空间。


3. 可以用低速模块处理高速数据流。所要求的数据处理速率仅仅为输入数据速率的1/2


“串并转换”:面积换速度,SERDES技术就是串并转换的典型应用。


 


“流水线操作”:是高速设计的一个常用设计手段。如果某个设计的处理流程分为若干步骤,而且整个数据处理是“单流向的”,即没有反馈或者迭代运算,前一个步骤的输出是下一个步骤的输入,则可以考虑采用流水线设计方法提高系统的工作效率。


 


异步时钟域数据同步


很多设计工作部稳定都是源于异步时钟域数据同步不稳定。


异步时钟域数据同步,也被称为数据接口同步,指任何两个时钟不同步的数据域之间可靠地进行数据交换的问题,数据的时钟域不同步主要有两种情况:


. 两个域的时钟频率相同,但是相差不固定,或者相差固定但是不可测,简称为同频异相问题。


. 两个时钟域频率根本不同,简称为异频问题。


 


两种不推荐的异步时钟域操作方法:


一种是通过增加buffer或者其他门延时调整采样;另一种是盲目使用时钟正负沿调整数据采样。


(1)       通过增加buffer等组合逻辑延迟线调整采样时间。


在早期逻辑电路图设计阶段,有些设计者习惯通过手工加入buffer或者非门调整数据延迟的习惯,从而保证本级模块的时钟对上级模块数据的建立、保持时间的要求,这种做法主要应用场合为:一是使用分立逻辑元件(如74系列)搭建数字逻辑电路;另一种是在ASIC设计领域。但是是由你过组合逻辑方法产生延迟容易产生毛刺,而且时序余量较差,一旦外界条件变换(环境试验、特别是高低温试验),采样时序就有可能完全紊乱,造成电路瘫痪,电路的可维护性和继承性都很差。


但是如果使用者使用了同一个时钟的两个沿,但是保证没有在同一个周期内同时使用双沿,则不会增加时钟频率。


 


(2)       盲目使用时钟正负沿调整数据采样。


很多人习惯随意使用时钟的正负沿调整采样,甚至产生一系列不同相位或不同占空比的时钟,使用其正负沿调整数据。该做法不推荐,原因如下:


. 第一,如果在一个时钟周期内使用时钟的双沿同时操作,则使用该时钟的同相倍频时钟也能实现相同的功能,换句话说,一个时钟周期内,使用时钟的双沿同时操作,相当于使用了一个同相的倍频时钟,此时因为设计的时钟频率提升,所有相关的使用约束都会变得更紧,不利于可靠实现。


. 第二,FPGAPLLDLL都能较好地保证某个时钟沿的jitterskew和占空比等各种参数指标,而对于另一个时钟沿的指标控制并不是那么严格,特别对于综合、实现等EDA的软件,如果明确对另外一个沿进行相关,这个沿的时序分析不一定完善,其综合或实现结果就不一定能严格满足用户期望的时序要求(如setuphold时间等),往往造成在该沿操作部稳定的结果。


 


两类异步时钟域操作的解决方法:


(1)       同频异相问题。


简单解决方法是用后级时钟对前级数据采样两次,即通常所述的用寄存器打两拍,这样有效减少了亚稳态的传播,使后级电路数据都是有效电平值。但这种做法并不能保证两级寄存器采样后的数据是正确的电平值,因为一旦setuphold时间不满足,采样发生亚稳态,则经判决时间(resolution time)后,可能判决到错误电平值。所以这种方法仅仅适用于对少量错误不敏感的功能单元。


可靠的做法是用DPRAMFIFO或者一段寄存器buffer完成异步时钟域的数据转换。把数据存放在DPRAMFIFO的方法如下:将上级芯片提供的数据随路时钟作为写信号,将数据写入DPRAMFIFO,然后使用本级的采样时钟将数据读出即可,由于时钟频率相同,所以DPRAMFIFO两端的数据吞吐率一致。


(2)       异频问题。


解决方法是使用DPRAMFIFO。思路同上。用上级随路时钟写入上级数据,然后用本级时钟读出数据,但是由于时钟频率不同,所以两个端口的数据吞吐率不一致,设计时一定要开好缓冲区,并通过监控(fullhalfempty等指示)确保数据流不会溢出。


 


异步时钟域的转换核心问题就是要保证下级时钟对上级数据采样的setup时间和hold时间。如果触发器的setup时间和hold时间不满足,就可能出现亚稳态,此时,触发器输出端Q在有效时钟沿之后比较长的一段时间内处于不确定的状态,在这段时间内Q端产生毛刺并不断震荡,最终固定在某一电压值,此电压值并不一定等于原来数据输入端D的数值,这段时间称为决断时间(resolution time)。经过resolution time之后Q端将稳定到01上,但究竟是0还是1是随机的,与输入没有必然关系。


亚稳态破坏系统的稳定性。


只要系统中有异步元件,亚稳态就无法避免,因此设计的电路首先要减少亚稳态导致的错误,其次要使系统对产生的错误不敏感。前者要靠同步设计来实现,后者根据不同的设计应用有不同的处理方法。


使用两级寄存器采样可以有效地减少亚稳态继续传播的概率。其原理是即使第一个触发器的输出端存在亚稳态,经过一个clk周期后,第二个触发器D端的电平仍未稳定的概率非常小,因此第二个触发器Q端基本不会产生亚稳态。理论上如果再添加一级寄存器,使同步采样达到3级,则末级输出为亚稳态的概率几乎为0.


两级寄存器采样仅能降低亚稳态的概率,但并不能保证第二级输出的稳态的电平就是正确电平,由于经过resolution time之后寄存器输出的电平是一个不确定的稳态值,也就是说这种处理方法并不能排除采样错误的产生,这时就要求说设计的系统对采样错误有一定的容忍度。


 


Altera推荐的coding style


良好的coding style对设计的工作频率,说消耗的芯片面积,甚至整个系统的稳定性都非常重要,而且良好规范的coding style将更便于设计的移植,如从一个器件族移植到另一个器件族,或者同一个器件族不同速度等级之间的移植,还包括altera FPGA利用hard copy向结构化ASIC的移植等。


   “好的coding style会使综合、实现等优化事半功倍,达到最优化的结果;不良的coding style会使综合、实现南辕北辙,甚至产生错误的结果。”,所以,综合、实现等EDA工具的优化能力和正确性最终取决于设计的coding style的优劣。


 


Coding style分为一般性coding style和针对综合工具、实现工具、器件类型的coding style。另有一部分coding style是针对altera器件的特点和硬件结构的,与器件紧密联系。使用altera推荐的coding style能够正确地实例化底层单元模块,合理地利用其固有的硬件结构,以达到最优化的设计效果。


这里所说的coding style主要是基于RTL级而言的。


(1)       结构层次化编码(hierarchical coding


(2)       模块化划分的技巧(design partitioning


模块划分的基本原则如下:


1.       对每个同步时序设计的子模块的输出使用寄存器。使用寄存器分割同步时序单元的好处有:便于综合工具权衡所分割的子模块中的组合电路部分和同步时序电路部分,从而达到更好的时序优化效果,这种模块划分符合时序约束的习惯,便于利用约束属性进行时序约束。


2.       将相关的逻辑或者可以服用的逻辑划分在同一模块内(呼应系统原则)。可最大程度上复用资源,减少设计所消耗的面积;更利于综合工具优化某个具体功能的时序关键路径;


3.       将不同优化目标的逻辑分开。


对于时序紧张的部分,应独立划分为一个模块,其优化目标为“speed”,以便于时序约束,也便于综合和实现工具进行优化;将资源消耗过大的部分划分为独立的模块,优化目标设定为“area”,有利于区域布局与约束。这种同时考虑两种优化目标会使综合器陷入互相制约的困境,耗费巨大的综合优化时间也得不到令人满意的综合优化结果。


4.       将松约束的逻辑归到同一个模块。


5.       将存储逻辑独立划分成模块。大多数的仿真器对大面积的RAM都有独特的内存管理方式,以提高仿真效率。


6.       合适的模块规模。


庞大的模块将要求对综合器同时处理更多的逻辑结构,对综合器的处理能力和计算机的配置提出了较高的要求;不利于发挥目前非常流行的增量综合与实现技术的优势。


 


组合逻辑的注意事项:


1.       避免组合逻辑反馈环路(combinational loops)。组合逻辑反馈环路是PLD设计的大忌,最容易因震荡、毛刺、时序违规等引起整个系统的不稳定和不可靠。


具体操作方法:. 牢记任何反馈环路必须包含寄存器;


              . 检查综合、实现报告的warning信息,发现combinational loops后进行相应的修改。


(3)       替换延迟链(delay chains)。避免使用异步的delay chains


(4)       替换异步脉冲产生单元(pulse generator


在异步设计中,常用delay chains完成脉冲产生。这类异步方法设计的脉冲产生电路的脉冲宽度取决于delay chains的门延迟和线延迟。会带来稳定性、可靠性问题,故必须避免使用。同步时序设计脉冲电路的常用方法设计的脉冲宽度不因器件改变或设计移植而改变,恒等于时钟周期,而且避免了异步设计的诸多不确定因素,其时序路径编译计算、STA分析和仿真验证。


(5)       慎用锁存器(latch)。同步时序设计要尽量避免使用latch。如在设计组合逻辑时使用不完全的条件判断语句,如有if没有else或者不完整的case语句等;另一种情况是设计中有组合逻辑的反馈环路等异步逻辑。


 


时钟设计的注意事项:


同步时序电路推荐的时钟使用方式:时钟经全局时钟输入引脚输入,通过FPGA内部专用PLLDLL进行倍频/分频移相等调整与运算,然后经FPGA内部全局时钟布线资源驱动到达芯片内所有寄存器和其他模块的时钟输入端。


对于内部逻辑产生的时钟必须在组合逻辑产生的时钟后插入寄存器,否则会使设计部稳定,对于时钟路径必须插入寄存器以过滤毛刺。


另外组合逻辑产生的时钟的jitterSkew都比较大,如果时钟产生逻辑的延迟比数据路径的延迟更大,会带来负的skew,负的skew同步逻辑设计而言是灾难性的,所以使用组合逻辑产生内部时钟仅仅适用于时钟频率较低、时钟精度要求不高的情况;另外这类时钟应该使用全局布线资源或者第二全局布线资源之类的快速布线资源布线,而且需要对组合逻辑电路附加一定的约束条件。


 


Ripple counter(行波计数器):结构为一组寄存器级联,每个寄存器的输出端接到下一级寄存器的时钟管脚,这种计数器常常用于异步分频电路,典型的异步时序逻辑。异步时序逻辑会带来各种各样的时序问题,在同步时序电路设计中必须严格避免使用ripple counter


 


时钟选择:为适应不同数据速率要求,经常要进行时钟切换。切换的最佳途径是使用FPGA/CPLD内部的专用clock MUX(全局时钟网络),这些MUX反应速度快,锁定时间短,切换瞬间带来的抖动和冲击小。如果器件没有专用的clock MUX,应尽量满足:


. 时钟切换控制逻辑在配置后将不再改变;


. 时钟切换后,对所有相关电路复位,以保证所有寄存器、状态机和RAM等电路的状态不会锁死进入死循环;


. 所有设计系统对时钟切换过程发生的短暂错误不敏感。


 


门控时钟:一种常用减少功耗的手段,在同步时序电路中,应该尽量不适用Geted Clock。门控时钟会污染clock的质量,通过门控后产生毛刺并使时钟的skewjitter等指标恶化。如果真的要减少功耗,可采用低核电压FPGAcore电压为1.0v),FPGA休眠功能,动态部分重构技术,clock MUX等技术。


 


时钟同步使能端:大多数如寄存器等同步单元都支持时钟的同步使能(synchromous clock enable),通过使用synchromous clock enable端完成某些逻辑功能,有时可以节约芯片面积并提高设计频率。


 


全局异步复位资源:大多数FPGA都具有专用的全局异步复位/置位资源,这类资源通常使用专用的低skew、低delay布线资源,直接到达寄存器、block RAM等底层单元,以保证高性能的复位/置位效果。Altera器件中一般使用全局时钟网络驱动全局同步或异步复位/置位信号。全局同步或异步置位/复位信号的应用比较复杂,不是所有的情况都推荐使用,但是一般情况下使用全局同步或异步复位/置位信号可以简化设计、节约芯片面积。


 


使用pipeline技术优化时序:即流水线时序优化方法,其本质是调整一个较长的组合逻辑路径中寄存器位置,用寄存器合理分割该组合逻辑路径,从而降低了对路径的clock-to-outputsetup 等时间参数的要求,达到提高设计频率的目的。但是必须注意的是pipeline优化技术只能合理地调整寄存器位置,而不应该凭空增加寄存器级数,所以pipeline有时也被称为register balance


 


模块复用与resource sharing:不要依靠综合工具的优化能力进行优化,主要还是要通过提高coding style的修养来提高代码质量。


 


逻辑复制:扇出非常大时,为了增加信号的驱动能力,必须插入多级buffer,这样就在一定程度上增加了这个型号路径的延迟,这时我们可以复制生成这个信号的逻辑,使多路同频同相的信号驱动后续电路,平均到每路的扇出变低,不需要加buffer也能满足驱动能力的要求,这样就节约了该信号的路径时延。


     逻辑复制与前面的resource sharing是两个对立统一的概念。Resource sharing目的是为了节省面积资源,而逻辑复制的目的是为了提高工作频率。当使用逻辑复制手段提高工作频率的时候,必然会增加面积资源,对立统一,是面积与速度的平衡。


 


信号敏感表:时序逻辑的信号敏感表比较好写,在信号敏感表写明时钟信号的正负触发沿即可,关于信号敏感表的主要问题几种在组合逻辑的信号敏感表的写法,需强调的是:


(1)       将操作进程(verilog always blockVHDLprocess block)中使用到的所有输入信号和条件判断信号都列在信号敏感表中。


(2)       希望通过证件信号敏感表来完成某项逻辑功能的大错特错;


(3)       不完整的信号敏感表会造成前仿真结果和综合、实现后仿真结果不一致;


(4)       一般综合工具对于不完整的信号敏感表的默认做法是,将处理进程中用到的所有输入和判断条件信号都默认到综合结果的信号敏感表中,并对原设计代码敏感表中遗漏的信号报警告信息。


 


状态机设计的一般原则:


(1)       选择状态机的编码方式。Binarygray-code编码使用最少的触发器,较多的组合逻辑,而one-hot编码反之。由于CPLD更多地提供组合逻辑资源,而FPGA更多地提供触发器资源,所以CPLD多使用gray-code,而FPGA多使用one-hot编码。另一方面,对于小型设计使用gray-codebinary编码更有效,而大型状态机使用one-hot更高效。


(2)       两种状态机的设计方法。第一种,将状态机转移和状态的操作、判断等写到一个模块中;另一种是将状态转移单独写成一个模块,将状态的操作和判断等写到另一个模块中。后者方式较好。


因为:状态转移是用寄存器实现的,是同步时序部分。状态转移条件的判断是通过组合逻辑判断实现的,之所以后者更合理就在于第二种编码将同步时序和组合逻辑分别放到不同的程序块中实现,这样不但便于阅读、理解、维护,更重要的是鲤鱼综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。


(3)       初始状态和默认状态。


(4)       指定默认输出值。所有输出指定一个默认的输出值;所有输出最好用寄存器打一拍。


(5)       状态机输出逻辑复用。将输出逻辑独立出来,单独写一个部分。


 


三态信号的设计:altera推荐在设计顶层中所有的双向总线(既做输入又做输出的总线)定义为三态信号。但必须注意的是,禁止在除顶层以外的其他子层次定义双向端口,除非是顶层中直接驱动双向端口的,禁止赋值高阻态Z


 


Stratix IIALM可以配置成6输入LUT,使用6-LUT可以同时完成3bit加法;


大多数FPGA都是基于LE结构的,一个LE由一个4输入查找表加上一个触发器组成

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。如发现有害或侵权内容,请点击这里 或 拨打24小时举报电话:4000070609 与我们联系。

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多
    喜欢该文的人也喜欢 更多

    ×
    ×

    ¥.00

    微信或支付宝扫码支付:

    开通即同意《个图VIP服务协议》

    全部>>