第2节优秀的HDL代码风格-Read_第1页
第2节优秀的HDL代码风格-Read_第2页
第2节优秀的HDL代码风格-Read_第3页
第2节优秀的HDL代码风格-Read_第4页
第2节优秀的HDL代码风格-Read_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第2节 优秀的hdl代码风格hdl代码3.2.1代码风格的含义代码风格有两层含义:其一是verilog的代码书写习惯;另一个则是对于一特定电路, 用哪一种形式的语言描述,才能将电路描述得更准确,综合以后产生的电路更为合理。 前者在2.5节已有涉及,本节主要介绍后者。代码风格有通用风格和专用风格两大类,前者指不依赖于fpga开发的eda软件工具 和fpga芯片类型,仅仅是从hdl语言出发的代码风格;后者指和开发软件以及硬件 芯片密切相关的代码风格,不仅需要关注eda软件在语法细节上的差异,还要紧密依 赖于固有的硬件结构。显然,前者具有较好的通用性,但性能未必最优。在使用时, 如果有后续的进一步开

2、发,建议使用通用风格;否则就可采用后者,以便极大地挖掘 芯片潜力。3.2.2通用代码风格的介绍1. 逻辑复用与逻辑复制在3.1.2节介绍过fpga设计中面积和速度的转化关系,该理念始终贯穿hdl代码设 计,二者典型的转换方式有逻辑复用和逻辑复制。前者通过速度换血积,后者通过血 积换収速度,两者各有相应的应用范围。逻辑复用逻辑复用是通过提高工作频率来节省而积的优化方法,经常用于存在多个资源可共享 单元的设计中,是大规模fpga设计的核心思想。为了便于理解,首先给出一个例子。例36幅度到功率转化模块中的逻辑复用。假设系统输入信号为i、q两路,每路速率 为5mbps、位宽为16比特,分别给出普通实现

3、和使用逻辑复用的实现代码。功能分析:计算功率需要先将i、q输入信号经过平方计算模块,然后再将2个平方和 相加输出即可。普通实现方式:图311功率统计模块的一般实现方式逻辑复用方式:图3-12采用逻辑复用方式实现功率统计模块经过比较对以发现,第1种实现方式需要两个16比特乘法器,第2种实现方式只需耍 1个乘法器,基本上将资源缩减到第1种方式的一半。目前,虽然有很多综合工具可以 提供逻辑复用的选项,但不能因为此而放松对代码编程的要求。主要原因有两点:首 先edai具的能力毕竟有限,很多情况下还是不能智能发现可以复用的逻辑;其次, 不同综合工具的优化参数以及能力并不相同,所以综合结果对于设计者是不确

4、定的。 所以,逻辑复用主要还是通过代码体现。逻辑复制逻辑复制是通过增加面积而改善设计时序的优化方法,经常用于调整信号的扇出。如 果信号具有高的扇出(如:吋钟和复位信号等),即要驱动很多后续电路,则要添加 缓存器來增强驱动能力,但这会增大信号的时延。通过逻辑复制,使用多个相同的信 号来分担驱动任务。这样,每路信号的扇出就会变低,就不需要额外的缓冲器来增强 驱动,即可减少信号的路径延迟。例如用于产生控制信号的监控模块一般都有高的扇 出,这时就往往需要考虑逻辑复制这一功能。图3-13(a)给出未采用逻辑复制的设计思 路,英占用资源较少,但延迟大,容易出错;而采用逻辑复制的设计如图3-13(b)所示,

5、 延迟小,但占用的资源多。因一(a)未采用逻辑复制的设计模式(b)采用逻辑复制的设计模式图3-13逻辑复制实例示例逻辑复用和逻辑复制是资源与速度的对立统一,目的都是为了提高设计性能、达到设 计li标,但一个是为了节省面枳来提高速度,另一个却是为了提高速度来占用额外的 面积,两者z间存在转换和平衡的关系。在实际工程屮,经常可以看到这两种方法的 应用。在xst以及synplify pro综合工具中,用户可以设定最大扇出数,当某信号的 扇出超过最大扇出值吋,该信号会自动被综合工具复制,以降低扇出。2. 逻辑结构逻辑结构主要分为链状结构(chain architecture)和树状结构(tree ar

6、chitecture)。 一般来讲,链状结构具有较人的时延,后者具有较小的时延。所谓的链状结构主要指 程序是串行执行的,树状结构是串并结合的模式,具体如例37所示。例3-7表3-3给出具有链状结构和树状结构的4输入加法器的实现实例。表3-3 4输入加法器的实现从上例可以明显看出树状结构的优势,它能够在同等资源的情况下,缩减运算时延, 从而提高电路吞吐量以节省面积。3. if和case语句的使用原则 if和case语句的区别if语句指定了一个有优先级的编码逻辑,而case语句生成的逻辑是并行的,不具有优 先级。if语句可以包含一系列不同的表达式,而case语句比较的是一个公共的控制表 达式。通常

7、if-else结构速度较慢,但占用的面积小,如果对速度没有特殊要求而对面 积有较高要求,则可用if -else语句完成编解码。case结构速度较快,但占用面积较大, 所以用case语句实现对速度要求较高的编解码电路。嵌套的if语句如果使用不当,就 会导致设计的更大延时,为了避免较大的路径延时,最好不要使用特别长的嵌套if结 构。如想利用if语句來实现那些对延时要求苛刻的路径时,应将最高优先级给最迟到 达的关键信号。有时为了兼顾面积和速度,可以将if和case语句合用。 if和case实例下面给出两个分别使用if和case语句的实例,希望读者从中体会到二者的不同。例3-8使用if语句实现一个4选

8、1的数据通路选择器。module sdata_if(clk, reset, x, s, y);input elk;input reset;input 3:0 x;input 1:0 s;output y;reg y;always (posedge elk) begin if (reset) beginy <= 0 ;endelse beginif(s = 2*b00) y <= x0;else if (s = 2'b01) y <= x;else if (s = 2'b10) y <= x2;elsey <= x3;endend en dmodul

9、e 上述程序经过综合后,其中数据选择部分的rtl级结构如图314所示。从中可以看出 状态变量s1:0通过y13、y14、y15以及y16是串行输入到复用器中的,且具有严格 的逻辑顺序,其逻辑级数为4。图314用if语句实现的4选1选择器rtl级结构图例3-9使用case语句实现一个4选1的8位数据选择器。module sdata_case(clk, reset, x, s, y);in put elk;in put reset;input 3:0 x;input 1:0 s;output y;reg y;always (posedge elk) beginif(!reset) beginy &

10、lt;= o ;endelse begincase(s)2*b00: y <= x0;2*b01: y <= x1;2*b10: y <= x2;2*b11: y <= x3;endcaseendend endmodule 上述程序经过综合后,其中数据选择部分的rtl级结构如图3-15所示。从中可以看出 状态变量s1:0通过y13、y14、y15以及y16是并行输入到复用器中的,因此逻辑级 数只有1级。图3-15用case语句实现的4选1选择器rtl级结构图4. 关键路径信号处理原则在verilog设计屮,经常会遇到由于信号路径过长或信号来的比较晚,从而造成建立时 间不

11、够的情况1°这种引起电路建立吋问不够的信号路径就称为关键路径。在复杂电 路设计中必须有效地处理关键信号,尽量减少其时延,提高电路的工作频率。简单组合电路关键路径的提取方法简单组合电路的关键路径提取方法就是拆分逻辑,将复杂逻辑变成多个简单组合电路 的进一步组合,缩减关键信号的逻辑级数,如例310所示。例3-10简单关键电路的提取实例。对于语句:assign y = a & b& c | d & e&b;从屮可以看出,信号b为关键信号。现将其简单路径计算,再经过关键路径逻辑。assign temp = a& b& c&d;assig

12、n y = b & temp;通过关键路径提取,将信号b的路径由2级变成1级。拆分逻辑的方法就是布尔 逻辑扩展,也被称为香农扩展,其原理如下式所示:可以看出,拆分逻辑可通过复制逻辑,缩短那些组合路径长的关键信号的路径 延迟,从而提高工作频率。 复杂always块中关键路径的提取方法对于always模块屮时间要求非常紧的信号,需要通过分布提取方法,让关键路径先行, 保证改写后的描述与原always块逻辑等效。例3-11给出了提取并改善always模块中 关键信号的实例。例3-11 always块中关键路径的提取和优化实例。always(w or x or y or z or in1 or

13、 in2) begin if(!w) beginif(x&&(! (y&&z)out = in1;elseout = in2;else if(y&&z)out =in1;endelse beginout = out;endend其中,若z=0,则原代码等效于if (!w) out = in1; else out = out;o若z=1,则源代码 等效于 if (!w && x && !y ) out = in1; else if(!w && x && y) out = in2; el

14、se out = out;。 对于信号y也有类似的分析结果,因此y、z都是关键信号。因此通过优先首先计算关 键路径,改写为:always(w or x or y or z or in1 or in2) begin temp = y && z;if(!temp) begin if(x&&!w) out = in1;elseout = in2;else if(temp)out =in1;endelse beginout = out;end5. 避免出现意外锁存器锁存器是电平触发的存储器,触发器是边沿触发的存储器,在同步电路设计屮要尽量 避免出现锁存器。在verilo

15、g hdl设计中,很容易由于条件判断语句表述的不完整,而 造成设计川会出现意想不到的锁存器。本质上,锁存器和d触发器的逻辑功能是基本 相同的,都可存储数据,且锁存器的资源更少,具备更高的集成度。但锁存器对毛刺 敏感,不能异步复位,因此在上电后处于不确定的状态。此外,锁存器还会使静态时 序分析变得非常复杂,不具备对重用性。在fpga芯片中,基本的单元是由查找表和触 发器组成的,若生成锁存器反而需要更多的资源。因此,在设计屮需要避免产生锁存 器。这一事件具体可分为两种情况:其一是在if语句中,另一种是在case语句中。下 面将对if和case语句造成的锁存器分别进行分析。 由if语句造成的锁存器例

16、给出了在always块中使用if语句,但缺乏else分支而造成锁存器的情 况。例3-12表3-4给出由于if语句不完整而生成意外的锁存器示例表34 if语句不完整的情况其经过sy叩lify pro综合后,得到的rtl图分别如图3-16以及(b)所示。存在锁存器的rtl结构因(b)不存在锁存器的rtl结构图3-16 if语句生成锁存器的rtl示意图可以看出,左边的语句块只有在a的值为1的情况下,datajn的值才能传递给 data_out,但没有指定在a的值为0的情况'f data_out的取值。这样在always语句块 屮,如果没有改变变暈的赋值,变暈值将保持不变,生成锁存器。如果希望

17、在a=0时, data_out值为0,那么程序就如右例所示。本例说明利用else分支就不会生成锁存器。由case语句造成的锁存器例3-13给出了在always块中使用case语句,由于缺乏default分支而造成锁存 器的情况。例3-13表3-5给出由于case语句不完整而生成意外的锁存器示例表3-5 case语句不完整的情况左边的例子中,当a1:0的值为?00、201时,分别将datajnl或data_in2赋给 data_out,在a为其余值的时候就生成了锁存器,data_out保持上一次的赋值保持不 变;右边的例子比较明确,在a的值不等于?00、26时,data_out的值为0,不会 生

18、成锁存器。以上两个例子给出了如何避免牛成意外锁存器。因此,如果用到if语句,最好有else 分支;如果用到else语句,最好有default语句。即使需要锁存器,也通过else分支 或default分支来显示说明。按照上而的建议,可以避免意想不到的错误,提高程序的 稳健性和可读性。6. 流水线技术的使用 流水线技术的工作原理流水线能动态地提升器件性能,它的基木思想是对经过多级逻辑的长数据通路进行重 新构造,把原来必须在一个时钟周期内完成的操作分成在多个周期内完成。这种方法 允许更高的工作频率,因而提高了数据吞吐量。因为fpga的寄存器资源非常丰富,所 以对fpga设计而言,流水线是一种先进的而

19、又不耗费过多器件资源的结构。但是采用 流水线后,数据通道将会变成多时钟周期,所以要特别考虑设计的其余部分,解决增 加通路带来的延迟。流水线设计的结构示意图如图3-17所示。图3-17(b)流水线的结构示意图流水线的基本结构是将适当划分的n个操作步骤串连起來。流水线操作的最大特点是 数据流在各个步骤的处理,从时间上看是连续的;其操作的关键在于时序设计的合理 安排、前后级接口间数据的匹配。如果前级操作的时间等于后级操作的时间,直接输 入即可;如杲前级操作时间小于后级操作时间,则需要对前级数据进行缓存,才能输 入到后级;如果前级操作时间大于后者,则需要串并转换等方法进行数据分流,然后 再输入到下一级

20、。流水线技术实例例3-14使用verilog实现具有4级流水线结构的8位加法器。module adder8_4(cout ,sum ,clk ,cina ,cinb ,cin);in put 7 :0ci na ,cinb;in put elk ,cin;output 7 :0 sum;output cout;reg cout ;reg coutl, cout2, cout3;reg 2 :0sum1;reg 4:0 sum2;reg 6:0 sum3;reg 7 :0sum;always (posedge elk) begin / 低二位相加coutl 5sum1 = cina 1 :0 +

21、 cinb 1 :0 + cin;endalways (posedge elk) begin 相加,并且将低4位拼接起来;cout2 ,sum2 = cina3,cina3 :2 + cinb3,cinb3 :2 +coutl 5sum1;endalways (posedge elk) begin 相加,并且将低六位拼接起来;cout3 , sum3 = cina5,cina 5:4 + cinb5,cinb 5:4 + cout2 ,sum2;endalways (posedge elk) begin 高2位相加,并且将8位拼接起來;cout ,sum = cina7,cina 7 :6 +

22、 cinb7,cinb7 :6 +cout3 5sum3;endendmodule图318给出了 synplify综合后的rtl结构图,其中有4个2位加法器,添加了较多的 辅助逻辑,使加法的运算时延降低到对2个比特的处理,从而可以应用在高速设讣中。图3-18具有4级流水线结构加法器的rtl图3.2.3专用代码风格的简要说明专用代码风格是指从fpga器件特征角度考虑,尽可能利用芯片结构以及内嵌的底层宏 单元,以取得最佳的综合和实现效果。对于同一个设计,使用适合于fpga体系结构特 点的优化设计方法,可以大大提高芯片利用率和设计实现速度。1. xilinx fpga的体系结构特点刈inx fpga

23、芯片的三种可构造单元是:(1)可编程输入、输出块iob,主要为逻辑阵 列与外部芯片引脚之间提供一个可编程接口; (2)可编程逻辑块clb, clb主要由一 个组合逻辑、几个触发器、若干个多选一电路和控制单元组成,若干个clb有规则地 组成fpga逻辑单元阵列结构,以完成用户指定的逻辑功能;(3)各种连线资源,包 括可编程的开关矩阵,内部连接点和金属线。它们位于芯片内部的逻辑块之间,经编 程后形成连线网络,以连接芯片内的逻辑块及传递逻辑信息。组合逻辑功能通过用户可编程的查找表实现。查找表是由静态存储器构成函数发生器, 在此基础上再增加触发器来形成的,它是即可实现组合逻辑功能乂可实现时序逻辑功 能

24、的基本逻辑单元电路。srl16是xilinx器件中独有的一种移位寄存器查找表,有4 个输入用來选择输出序列的长度,能够以极少的硬件资源实现数据缓存和组合逻辑。每个clb屮包含两个触发器,clb的组合逻辑功能较少,触发器资源十分丰富。每个 clb屮包含一个高速进位逻辑。专用进位电路速度远远大于采用传统的加速方法所能 增加的速度。算术进位逻辑为有关算术运算中许多新的应用问题提供了有效的解决途 径。同时,xilinx提供了片上ram,特别是大量块ram,可以配置成双口 ram或rom,存 储量大、速度快,且不占用逻辑资源,在设计实现中有着广泛的应用。内嵌的宏单元包括硬核乘加器、硬核处理器、数字时钟处

25、理模块以及高速串行接口, 处理能力强,处理能力为片上最高,且不存在时序问题。如果合理地利用宏单元,可 达到事半功倍的效果。2. xilinx fpga芯片专用代码风格时钟信号的分配策略时钟分配网络是fpga芯片中的特殊布线资源,由特定的引脚和特定的驱动器驱动,只 能驱动芯片上触发器的时钟输入端或除了时钟输入端外有限的一些负载,其冃的是为设 计提供小延迟偏差和扭曲可忽略的时钟信号。首先,使用全局时钟,可为信号提供最短的延时和可忽略的扭曲。全局网线由全局缓 冲器bufg來驱动,使用bufg时,时钟信号经bufg驱动后通过长线同时接到每个触 发器的时钟端,减少传输延迟。如不使用bufg,时钟信号按一

26、般布线连接到不同clb, 时钟信号到达各触发器的延迟不一致,使同步时序电路出现不同步的现象。其次,fpga特别适合于同步电路设计,尽可能减少使用的吋钟信号种类。如ttl电路 设计中,经常采用的由组合逻辑生成多个时钟分别驱动多个触发器的设计方法对fpga 的设计不适用。因为这样做使得时钟种类很多,不能利用专用的时钟驱动器和专用的 时钟布线资源,时钟信号只能由通用的布线资源拼凑而成,各个负载点上的时钟延迟 偏差很大,会引起数据保持时间问题,降低工作速度。第三,减小时钟摆率的另一种更有效方法是使用一个时钟信号,生成多个时钟使能信 号,分别驱动触发器的时钟使能端,所有触发器的数据装入都rh同一个时钟控

27、制,但 只有时钟使能信号有效的触发器才会装入数据,时钟使能信号无效的触发器则保持数 据。这种方法充分发挥了 fpga器件体系结构的优势。图3-19所示电路为分频器的一般设计和优化设计的对比。两种设计方法相比较,图(a) 电路使用两个全局缓冲,实现两个触发器的界步控制。图(b)电路将异步控制转化为同 步控制,只占用一个全局缓冲,利用时钟使能信号ce控制触发器的动作。因此图b电 路占用更少的全局时钟资源,而且使用一种时钟信号更利用同步控制和减小时钟摆率。(a)分频器的普通设计(b)分频器的优化设计图3-19分频器两种设计电路的比较第四,要避免吋钟信号毛刺。由图320所示电路可知,当二进制计数器从0

28、111向1000 变化时,必然会出现一个门门的过渡过程,d触发器的时钟就会产生毛刺,毛刺出现 的时间很短,但对于高速处理来讲,足以使触发器误动作。图b所示电路就是使用同 步时钟,并使用时钟使能ce端避免时钟信号毛刺的设计电路。h"(a)会产生毛刺的传统设计(b)能消除毛刺的优化电路图3-20两种设计电路的比较 srl16结构的使用srl16是一种基于查找表(lut)的移位寄存器,可用于构建高密度dsp结构,如滤 波器,能够大幅消减硬件资源。在virtex-5芯片中为6输入的查找表,在其余系列芯 片中都为4输入查找表。其位宽(b)和深度(d)可以任意配置,最大的特点就是占 用slice

29、资源特别少。其占用slice资源m的计算公式为:英中,r函数的意义是取整。从上式可以看出,深度为1的移位寄存器和深度 为16的移位寄存器所占用的slice资源是一样的。例315使用srl16生成位宽为8,深度为10的移位寄存器。module lut_ram(clk5 d, q);input elk;input 7 : 0 d;output 7 : 0 q;srl16 based ram srl16 based ram(.clk(clk),d(d),q(q);en dmodule其中 srl16_based_ram 例化了 xilinx 提供的 ram_based_shiftreg 的 ip core,使用srl16结构完成了移位寄存器。上述程序经过synplify pro综合后,得到的rtl结构 如图所示。图3-21 srl16结构移位寄存器的rtl结构示意图在modelsim 6.2b中完成仿真,其结果如图3-22所示图3-22 srl16结构移位寄存器的仿真结果示意图 触发器资源的分配技术由于fpga是一种触发器密集型可编程器件,因此系统的逻辑设计就应该充分利用触发 器资源,尽可能降低每个组合逻辑操作的复杂度。首先,应尽量使用库屮的触发器资源。因为f

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论