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
没有回复内容