FPGA知识汇集-值得收藏的Verilog代码风格2-FPGA新闻资讯社区-FPGA CPLD-ChipDebug

FPGA知识汇集-值得收藏的Verilog代码风格2

05 使用可变的比特范围选择

部分选择位宽时,可用如下的方法:先定义一个范围起点,然后增加或减小一个常量值。如下为使用可变的比特范围选择示例。

wire[31:0] part_sel_in,

reg[0:31] part_sel_out

assign part_ sel_out(24 +:8] = part. sel in[7-: 8];

assign part_sel_out([16 +:8] = part sel_in[15 -: 8];

assign part_sel_out[15 -:16] = part_sel_in[16 +: 16];

使用上面的方法不容易出错,可以防止位宽不匹配情况的出现。下面的描述则容易发生错误。

assign part_sel_out(24:31] = part_ sel_in[7:0];

assign part_sel_out[16:24] = part_sel_in[15:8]; //错误

assign part_sel_out [15:0] =  part_sel_in[16:31] ;

06

 

使用for语句

 

在许多情况下,可以使用for语句实现移位寄存器、对各位比特进行交换、执行奇偶校验等。持续关注,后续将描述如何使用for语生成并行CRC。

下面是一个使用for语句的例子。

module for_loop( output reg loop_out

                             input [15:0] loop_in);

integer iy;

always @(*) begin

       for (iy=0;iy<16;iy=iy+1) begin

            loop_ out = loop_out ^loop_in[iy];

        end

end

endmodule // for_loop

建议避免使用for语句进行逻辑复制,并且仅在简单的重复操作中使用它,如位的交换。在循环语句中使用for语句会产生逻辑级联,这可能会导致逻辑利用率和时序性能不能达到最佳。

07 使用函数

下面是Verilog 函数执行异或操作的简单示例。

module function_ example( input a,b, output func_out);

    function func_xor;

         input a, b;

        begin

              func_xor=a^b;

         end

        endfunction

    assign func_ out = func_ xor(a,b) ;

endmodule // function_ example

建议使用Verilog函数来实现组合逻辑和其他需非阻塞赋值的操作(如同步逻辑)。使用函数可使程序更加紧凑且代码更加模块化。所有的综合工具都支持Verilog函数。

08

 

使用generate块

在Verilog-2001中引入了generate(生成)块,可以使得模块、函数、变量、信号和连续赋值的多次例化更加容易。以下是使用generate的两个示例。

//模块的条件例化

parameter COND1 = 1;

generate

if (COND1) begin : my_module1_ inst

    my. modulel inst (.clk(clk), .di(di), .do(do));

end

else begin : my_ module2_ inst

   my. module2 inst (.cIk(clk), .di(di), .do(do));

end

endgenerate

//在generate块中使用for循环

genvar ii;

generate

   for(ii=0;ii<32;ii=ii+1)begin:for  loop

       my  modulel inst (.clk(clk), .di(di[ii]),do(do[ii]));

  end

end

endgenerate

09

开发可移植代码

在本篇中,代码的可移植性是指以最少的代码修改为前提,使得FPGA设计能够由不同的综合工具和不同的FPGA目标器件综合。

即使代码的可移植性并不是项目开始时的一个重要要求,但是他极可能在项目的后期展示出其优点。在高技术产业化经营中,市场需求迅速改变,正因如此,大量的代码需要在一个完全不同的项目中重用,该项目采用不同的FPGA目标器件或不同供应商的器件。预测代码能具有多久的效用几乎是不可能的。代码可以打包成IP核,并授权给不同的客户,也可以作为收购项目,由另一家公司接手;或者可能需要调整到一个新的、 更具成本效益的FPGA目标器件中实现。

开发可移植代码的第一个建议,是将FPGA的特定元件分离出来包装成单独的文件或库。例如,Altera和其他FPGA供应商有不同的嵌入式存储器原语。然而,类似于RAM、ROM和FIFO等组件,其外部接口是非常相近的。不要在代码中对Xilinx BRAM原语直接例化,可使用一个带通用地址、数据和控制信号的wrapper,这将使得代码更具有可移植性。

提高可移植性的第二个建议是开发通用的RTL代码,而不是直接例化特定的FPGA器件。直接例化将在后续持续更新详细描述。

综合工具支持的Verilog 语言的子集不同。例如,XST不支持Verilog 开关级原语,但Synplify支持。建议使用大多数综合工具支持的语法结构。

10

 

简单的代码开发

设计者应一直努力使得开发的代码简单。与每一种编程语言类似,Verilog允许从功能角度考虑,书写阐述性的语句,但代码不易读懂。下面的简单示例说明了这一点。

   reg [5:0] sel;

   reg [3:0] result1,result2,a,b;

   always @(*) begin

        result1=se1[0]? a+b : se1[1]? a – b:

        sel[2] ? a & b : sel[3]? a^ b :

        sel[4] ? ~a : ~b;

    if(~|sel)

    resultl = 4’b0;

end // always

always @(*) begin

casex (sel )

    6’bxxxxx1: result2 = a + b;

    6’bxxxx10: result2= a – b;

    6’bxxx100: result2= a & b;

    6’bxx1000: result2 = a ^+ b;

    6’bx10000: result2 = ~a;

    6’b100000: result2 = ~b;

    default:    result2 = 4’b0;

 endcase

end // always

实现resut1和resul2的逻辑在功能上是等效的。然而,result1 中使用了嵌套的三元操作符和两个赋值语句,因此结构不清晰,需要更多的分析才能理解。而result2中的逻辑由于使用了case语句,因此更加清晰易懂。

通常情况下,代码的结构清晰度更重于实现效率。同一段代码在其编写完成后要被多个开发者阅读。编写结构清晰、易读的代码更易于调试, 也不易于隐藏错误。

09

 

使用Lint工具

Lint工具执行仿真和综合前的RTL代码规则检查。它们有助于揭示不能由仿真和综合工具发现的复杂和模糊问题。Lint 工具检查的设计规则包括时钟域交叉、组合逻辑环路、模块连接、编码风格、隐含锁存器、异步复位、状态重叠等。关注公众号,有详细描述Lint 工具的篇章。

10

 

参考文献

[“Standard Gotchas: Subrleties in the Verilog and SystemVerilog Standards That EveryEngineer Should Know”,by Stuart Sutherland. Published in the proceedings of SNUGBoston, 2006..

http://www. stheriand-hd. com/papers/2007- SNUG-SanJose  gotcha   again  paper.pdf

请登录后发表评论

    没有回复内容