【干货分享】编写可综合的FPGA代码经验总结(一)

作者:张浩 ,来源:FPGA技术联盟

编写可综合的FPGA代码

在接触Verilog 语法参考手册的时候,我们发现其提供了一组非常丰富的功能来描述硬件。所以大家往往会疑惑那些Verilog语句是可综合的,那些是只能用于写Testbench的,其实,参考手册中只有一小部分语句是可综合的,但是这一小部分可综合的语法确是我们应用最为频繁的,可综合的意思就是可以通过物理工具进行编译、综合、布局布线,最终在FPGA上实现。

参考下面的例子。

reg [7:0] memory[1:2**22];

Initial begin

memory[1]=8’h1;

memory[2]=8’h2;

end

该示例虽然可以正常的仿真,但是用FPGA工具编译综合,最终在FPGA上实现。代码中定义了一个4M Byte的存储器,其实在FPGA中时没有这样的物理资源可以与其对应的,另外,FPGA编译综合工具在编译的时候也将忽略Initial块语句。

本文重点介绍如何设计可综合的Verilog代码。在设计可综合的Verilog代码的时候,我们应该遵循怎样的原则。

1. 坚持FPGA的同步设计原则

包括以下几个方面:

  • 使用同步复位电路。
  • 避免使用锁存器; 尽可能使用同步寄存器。
  • 避免使用门控,派生或分频时钟。
  • 使用时钟使能,而不是多个时钟。
  • 实现所有异步信号的正确同步。
  • 2. 理解综合工具的能力和局限性

    充分了解综合工具的能力和局限性将有助于提高FPGA设计的性能、逻辑性、以及资源利用率和可生产性。熟悉特定FPGA系列的内部构造,以及综合工具所忽略或不支持的语言以及建议的寄存器,状态机,三态和其他推荐的编码风格非常重要。

    3. 忽略语言结构

    FPGA综合工具会忽略延迟值和时间标度编译器指令。设计人员经常利用延迟来使分析仿真波形变得更容易,如下例所示。

    `define DLY 1

    always @(posedge clk) begin

    Data_out<=#`DLy data_in;

    end

    因为潜在的综合和仿真失配,所以不鼓励使用这样的结构。例如,如果上例中的“DLY超过时钟周期,则综合电路可能在功能上不正确,因为它不会匹配仿真结果。绝大多数FPGA综合工具都忽略编译器指令,例如celldefine和endcelldefine。

    FPGA综合工具忽略initial块描述。

    综合工具为Verilog门级原语(如nmos,pmos,cmos,pullup,pulldown,

    tranif0,tranif1,tran等)提供各种级别的支持。例如,XST不支持Verilog tranif原语,而Synplify则支持。 尽管Xilinx FPGA体系结构不具有门级原语的直接等价物,但一些综合工具将其转换为功能等效的门级开关。 以下是nmos转换的一个例子。

    module nmos_switch(output out,intput data,control);

    Assign out =control?Data :1’bz ;

    endmoudle

    4. 不支持的语句结构

    不支持的语句结构包括有:用户自定义的原语(UDP),repeat,wait,

    fork/join,deassign ,event,force/release 语句。也不支持模块内寄存器和网络的分层引用,如:

    module mymodule1;

    assign my_net =top.my_mudule2.my_net ;

    endmoudle

    相等和不相等运算符(===和!==)的支持级别取决于综合工具。有些综合工具在遇到一个等式和不等式运算符时会产生一个错误,而另一些则会将运算符转换为逻辑等式(==和!=)。

    5. 2种状态和4种状态的比较

    4态值('0','1','x','z')本质上是不可综合的。 FPGA架构仅支持2态值(逻辑“0”和“1”),综合工具将应用不同的规则来优化“z”和“x”综合的过程。这将导致综合和仿真结果之间的不匹配和其他错误。 在实现三态IO缓冲区的时候只使用'z'值。

    6. translate_on/translate_off

    translate_off和translate_on表示让综合工具忽略Verilog代码的一部分。这些指令通常用于忽略IP核模型中的行为代码部分。以下是使用这些指令的示例。

    module bram_2k_9 ( input clka, input [0 : 0] wea,

    input [10 : 0] addra,

    output [8 : 0] douta,

    input [8 : 0] dina);

    // synthesis translate_off

    // behavioral description of bram_2k_9

    // synthesis translate_on

    endmodule // bram_2k_9

    7. 特殊的编译指令也无法被综合

    syn_keep指令可防止综合工具删除指定的信号。它适用于网络和组合逻辑。 该指令通常用于禁用不需要的优化,并保留手动创建的复制。综合工具不同syn_keep的作用可能会不同。例如,XST不会将约束传播到综合网表,这并不妨碍物理实现工具的优化。syn_preserve防止寄存器优化。XST还支持“Equivalent Register Removal”选项,相当于syn_preserve。syn_noprune确保如果未使用实例化原型的输出,则原型未被优化。XST也支持“Optimize Instantiated Primittives”选项,相当于syn_noprune。

    8. parallel_case和full_case

    如果在case,casex或casez语句中指定了full_case指令,则会阻止综合工具创建其他逻辑以涵盖未描述的条件。使用full_case指令可能会有更紧凑的效果。parallel_case指令强制将case语句综合成为并行复用器而不是优先级编码结构。使用parallel_case指令可能会提高电路的时序性能。

    full_case和parallel_case指令的确切作用取决于综合工具。而且,使用这些指令也会导致综合和仿真不匹配。出于这些原因,不建议在FPGA设计中使用full_case和parallel_case指令。相反,设计师可以通过一个case语句的实现来达到同样的效果。例如,删除重叠的大小写条件会导致不必要的parallel_case指令。

    9. 编译器指令 `default_nettype

    Verilog-2001标准定义了一个`default_nettype编译器指令。 如果该指令被分配为“无”,则必须声明所有的1bit 信号网络。

    // no `default_nettype

    wire sum; // declaration is not required

    assign sum = a + b;

    `default_nettype none

    wire sum; // must be declared

    assign sum = a + b;


    文章转载自:FPGA技术联盟
    *本文由FPGA技术联盟授权转发,如需转载请联系作者本人

    最新文章

    最新文章