原创 【原创】Verilog-2001新增特性(实例分析)

2008-12-21 16:09 11863 9 12 分类: FPGA/CPLD

       Verilog-2001标准在2001年就发布了,不过翻了一些Verilog书籍,对Verilog-2001的新增特性很少有提及,即使提到了,也只是寥寥数语带过,其实在Verilog-2001中做了很多有用的改进,给编程带来很大的帮助,有必要详细了解。







       在Quartus II软件中现在支持的Verilog标准有三类,即Verilog-1995,Verilog-2001,以及SystemVerilog-2005.具体用那种标准进行编译综合,需要在设置对话框中进行设置,如下图所示:


点击看大图







       下面对Verilog-2001新增特性进行详细说明,部分说明用实例进行解析。


l         generate语句


Verilog-2001添加了generate循环,允许产生moduleprimitive的多个实例化,同时也可以产生多个variablenettaskfunctioncontinous assignmentinitialalways。在generate语句中可以引入if-elsecase语句,根据条件不同产生不同的实例化。


为此,Verilog-2001还增加了以下关键字:generateendgenerategenvarlocalparamgenvar为新增数据类型,存储正的integer。在generate语句中使用的index必须定义成genvar类型。localparamparameter有些类似,不过其不能通过redefinition改变值。除了可以在generate语句中使用if-elsecase外,还能使用for语句进行循环。


下面是一个使用generate的例子,根据a_widthb_width的不同,实例化不同的multiplier


module multiplier (a, b, product);<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


parameter a_width = 8, b_width = 8;


localparam product_width = a_width+b_width;


input [a_width-1:0] a;


input [b_width-1:0] b;


output[product_width-1:0]product;


generate


if((a_width < 8) || (b_width < 8))


CLA_multiplier #(a_width, b_width)


u1 (a, b, product);


else


WALLACE_multiplier #(a_width, b_width)


u1 (a, b, product);


endgenerate


endmodule


在下面的例子中,在generate语句中使用了for语句。


module Nbit_adder (co, sum, a, b, ci);


parameter SIZE = 4;


output [SIZE-1:0] sum;


output co;


input [SIZE-1:0] a, b;


input ci;


wire [SIZE:0] c;


genvar i;


assign c[0] = ci;


assign co = c[SIZE];


generate


for(i=0; i<SIZE; i="i"+1)


begin:addbit


wire n1,n2,n3; //internal nets


xor g1 ( n1, a, b);


xor g2 (sum,n1, c);


and g3 ( n2, a, b);


and g4 ( n3, n1, c);


or g5 (c[i+1],n2, n3);


end


endgenerate


endmodule


generate执行过程中,每一个generated net在每次循环中有唯一的名字,比如n14次循环中会产生如下名字:


addbit[0].n1


addbit[1].n1


addbit[2].n1


addbit[3].n1


这也是为什么在begin-end块语句需要名字的一个原因。同样,实例化的modulegate等在每次循环中也有不同的名字。


addbit[0].g1


addbit[1].g1


addbit[2].g1


addbit[3].g1


 


l         constant functions


Verilog的语法要求定义向量的宽度或数组大小时其值必须是一个确定的数字或一个常量表达式。比如:


parameter WIDTH = 8;


wire [WIDTH-1:0] data;


Verilog-1995标准中,常量表达式只能是基于一些常量的算术操作。而在Verilog-2001中增加了constant function,其定义与普通的function一样,不过constant function只允许操作常量。下面是一个使用constant function的例子,clogb2函数返回输入值2次方的次数。


module ram (address_bus, write, select, data);


parameter SIZE = 1024;


input [clogb2(SIZE)-1:0] address_bus;


...


function integer clogb2 (input integer depth);


begin


for(clogb2=0; depth>0; clogb2=clogb2+1)


depth = depth >> 1;


end


endfunction


...


endmodule


 


l         Indexed vector part selects


Verilog-1995中,可以选择向量的任一位输出,也可以选择向量的连续几位输出,不过此时连续几位的始末数值的index需要是常量。而在Verilog-2001中,可以用变量作为index,进行part select


[base_expr +: width_expr] //positive offset


[base_expr -: width_expr] //negative offset


       其中base_expr可以是变量,而width_expr必须是常量。+:表示由base_expr向上增长width_expr位,-:表示由base_expr向上递减width_expr位。例如:


reg [63:0] word;


reg [3:0] byte_num; //a value from 0 to 7


wire [7:0] byteN = word[byte_num*8 +: 8];


       如果byte_num的值为4,则word[39:32]赋值给byteN


 


l         多维数组


Verilog-1995只允许一维数组,而Verilog-2001允许多维数组。


//1-dimensional array of 8-bit reg variables


//(allowed in Verilog-1995 and Verilog-2001)


reg [7:0] array1 [0:255];


wire [7:0] out1 = array1[address];


//3-dimensional array of 8-bit wire nets


//(new for Verilog-2001)


wire [7:0] array3 [0:255][0:255][0:15];


wire [7:0] out3 = array3[addr1][addr2][addr3];


而且在Verilog-1995中不能对一维数组中取出其中的一位,比如要取出上面array1[7][5],需要将array1[7]赋给一个reg变量比如arrayreg <= array1[7],再从arrayreg中取出bit5,即arrayreg[5]。而在Verilog-2001中,可以任意取出多维数组中的一位或连续几位,比如:


//select the high-order byte of one word in a


//2-dimensional array of 32-bit reg variables


reg [31:0] array2 [0:255][0:15];


wire [7:0] out2 = array2[100][7][31:24];


 


l         符号运算


Verilog-1995中,integer数据类型为有符号类型,而regwire类型为无符号类型。而且integer大小固定,即为32位数据。在Verilog-2001中对符号运算进行了如下扩展。


Regwire变量可以定义为有符号类型:


reg signed [63:0] data;


wire signed [7:0] vector;


input signed [31:0] a;


function signed [128:0] alu;


函数返回类型可以定义为有符号类型。


带有基数的整数也可以定义为有符号数,在基数符号前加入s符号。


16'hC501 //an unsigned 16-bit hex value


16'shC501 //a signed 16-bit hex value


操作数可以在无符号和有符号之间转变。通过系统函数$signed$unsigned实现。


reg [63:0] a; //unsigned data type


always @(a) begin


result1 = a / 2; //unsigned arithmetic


result2 = $signed(a) / 2;//signed arithmetic


end


增加了算术移位操作,在Verilog-1995中只有逻辑移位操作。比如D的初始值为<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />8’b10100011,则:


D >> 3 //logical shift yields 8'b00010100


D >>> 3 //arithmetic shift yields 8'b11110100


 


l         指数运算


Verilog-2001中增加了指数运算操作,操作符为**


always @(posedge clock)


result = base ** exponent;


 


l         递归函数和任务


Verilog-2001中增加了一个新的关键字:automatic。该关键字可以让任务或函数在运行中从新调用该任务和函数。


function automatic [63:0] factorial;


input [31:0] n;


if (n == 1)


factorial = 1;


else


factorial = n * factorial(n-1);


endfunction


 


l         组合逻辑敏感信号通配符


在组合逻辑设计中,需要在敏感信号列表中包含所有组合逻辑输入信号,以免产生锁存器。在大型的组合逻辑中比较容易遗忘一些敏感信号,因此在Verilog-2001中可以使用@*包含所有的输入信号作为敏感信号。


always @* //combinational logic sensitivity


if (sel)


y = a;


else


y = b;


 


l         使用逗号隔开敏感信号


Verilog-2001中可以用逗号来代替or隔开敏感信号。


always @(a or b or c or d or sel)


always @(a, b, c, d, sel)


 


l         Automatic width extension beyond 32 bits


Verilog-1995中,在不指定基数的情况下为大于32位的变量赋高阻值,只能使其低32位为高阻值,其他高位会被设置为0,此时需要指定基数值才能将高位赋值为高阻。


Verilog-1995:


parameter WIDTH = 64;


reg [WIDTH-1:0] data;


data = 'bz; //fills with 'h00000000zzzzzzzz


data = 64'bz; //fills with 'hzzzzzzzzzzzzzzzz


而在Verilog-2001中并没有这一限制。


Verilog-2001:


parameter WIDTH = 64;


reg [WIDTH-1:0] data;


data = 'bz; //fills with 'hzzzzzzzzzzzzzzzz


 


l         组合端口及数据类型定义


Verilog-1995中,端口定义和数据类型定义需要在两条语句中执行,而Verilog-2001中可以将其组合在一起。


module mux8 (y, a, b, en);


output reg [7:0] y;


input wire [7:0] a, b;


input wire en;


 


l         ANSI格式的端口定义


在定义端口的同时并定义其数据类型,比上一个改进更简洁。


module mux8 (output reg [7:0] y,


input wire [7:0] a,


input wire [7:0] b,


input wire en );


 


function [63:0] alu (


input [63:0] a, b,


input [7:0] opcode );


 


l         定义reg并初始化


Verilog-1995中定义和初始化reg需要两条语句,而在Verilog中可以合成一条语句。


Verilog-1995:


reg clock;


initial


clk = 0;


Verilog-2001:


reg clock = 0;


需要更加详细的说明,请下载下列附件。


pdf


pdf

PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

用户377235 2011-12-21 09:01

谢谢

用户52478 2011-11-5 23:42

generate的例子第一个没看懂

用户1406579 2009-5-22 22:36

正需要学习一下,谢谢了
相关推荐阅读
用户1332143 2009-08-16 21:47
时序电路亚稳态分析
这篇文章是我对电子设计中,亚稳态问题的一种分析和总结。文章通过对数字电路中器件的工作机制的介绍,引出亚稳态问题的发生机制。并通过对亚稳态问题发生机制的探讨,用以得到一种能够清楚地,有的放矢地解决亚稳态...
用户1332143 2009-08-16 10:52
【推荐】ADF4350配置软件下载
p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">  随着现代半导体工艺的不断发展, 几十纳米级的CMOS工艺给数字电路带来了很大的恩惠, 但对模拟...
用户1332143 2009-08-14 12:47
【原创】基于NiosII及FT245BM的USB接口设计
以前做的一个项目,FPGA接收AD采集数据后,通过串口发送回PC机,由于串口传输速率较低,对于实时性要求较高的场合不太适用,因此站长选用FT245BM芯片来实现USB接口传输,本文主要讲解FT245B...
用户1332143 2009-08-13 14:56
【原创】MAXII:UFM中晶振的使用
MAXII系列CPLD中带有UFM模块,本文主要讲解UFM中晶振的使用,具体内容请点击下面链接MAXII:UFM中晶振的使用...
用户1332143 2009-03-01 21:53
【原创】如何使用FPGA进行信号调制
       最近要做一个通信收发系统项目,以前对收发器的射频前段关注的比较多,而对基带部分的信号处理一直没有仔细研究。因此,正好借这个项目,熟悉整个基带部分的信号处理流程。       基带部分主要...
用户1332143 2009-02-27 21:56
寒假回来——FPGA市场评论
寒假在家里电脑不能上网,好久没来更新自己的博客了,首先感谢大家对我博客的支持。回来后马上开始了一个863项目,一直没有时间来写博客,今天总算有时间,上来看看。回来这段时间关注了下FPGA的相关新闻,发...
我要评论
3
9
关闭 站长推荐上一条 /3 下一条