verilog语法注意部分
l generate语句
Verilog-2001添加了generate循环,允许产生module和primitive的多个实例化,同时也可以产生多个variable,net,task,function,continous assignment,initial和always。在generate语句中可以引入if-else和case语句,根据条件不同产生不同的实例化。
为此,Verilog-2001还增加了以下关键字:generate,endgenerate,genvar,localparam。genvar为新增数据类型,存储正的integer。在generate语句中使用的index必须定义成genvar类型。localparam与parameter有些类似,不过其不能通过redefinition改变值。除了可以在generate语句中使用if-else,case外,还能使用for语句进行循环。
下面是一个使用generate的例子,根据a_width和b_width的不同,实例化不同的multiplier。
module multiplier (a, b, product);
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[i], b[i]);
xor g2 (sum[i],n1, c[i]);
and g3 ( n2, a[i], b[i]);
and g4 ( n3, n1, c[i]);
or g5 (c[i+1],n2, n3);
end
endgenerate
endmodule
generate执行过程中,每一个generated net在每次循环中有唯一的名字,比如n1在4次循环中会产生如下名字:
addbit[0].n1
addbit[1].n1
addbit[2].n1
addbit[3].n1
这也是为什么在begin-end块语句需要名字的一个原因。同样,实例化的module,gate等在每次循环中也有不同的名字。
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数据类型为有符号类型,而reg和wire类型为无符号类型。而且integer大小固定,即为32位数据。在Verilog-2001中对符号运算进行了如下扩展。
Reg和wire变量可以定义为有符号类型:
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的初始值为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
转载:http://blog.sina.com.cn/s/blog_625507140100ux11.html
verilog语法注意部分的更多相关文章
- Verilog语法基础讲解之参数化设计
Verilog语法基础讲解之参数化设计 在Verilog语法中,可以实现参数化设计.所谓参数化设计,就是在一个功能模块中,对于一个常量,其值在不同的应用场合需要设置为不同的置,则将此值在设计时使用 ...
- verilog语法实例学习(4)
Verilog模块 Verilog中代码描述的电路叫模块,模块具有以下的结构: module module_name[ (portname {, portname})]; //端口列表 [parame ...
- verilog语法实例学习(1)
本文档中通过verilog实例来学习verilog语法.Verilog是一种硬件描述语言,它具有并发性和时序性.并发性是指不同硬件模块的同时操作,时序性是指信号的赋值或操作在时钟的边沿进行.由于作者本 ...
- verilog语法学习目录
verilog语法实例学习(1) Verilog中的注释 Verilog中的信号 标识符 信号的值 Verilog中的数字 Verilog中的参数 verilog语法实例学习(2) 线网类型 变量类型 ...
- 跟着我从零开始入门FPGA(一周入门XXOO系列)-1、Verilog语法
(本连载共七部分,这是第一部分) 作者:McuPlayer2013 (EETOP FPGA版块版主) 原帖地址:http://bbs.eetop.cn/thread-385362-1-1.html ...
- verilog语法实例学习(12)
verilog中的综合和不可综合总结 Verilog中综合的概念 综合就是EDA工具或者说综合工具把我们编写的verilog代码转化成具体电路的过程.Verilog中有很多语法,结构,过程,语句,有些 ...
- verilog语法实例学习(6)
函数和任务 函数 https://wenku.baidu.com/view/d31d1ba8dd3383c4bb4cd283.html verilog中函数的目的是允许代码写成模块的方式而不是定义独立 ...
- verilog语法实例学习(5)
子电路模块 子电路模块的使用 一个verilog模块能够作为一个子电路包含在另一个模块中.采用这种方式,所有的模块都必须定义在一个文件中,那么verilog编译器就必须被告知每个模块的所属.模块例化的 ...
- verilog语法实例学习(2)
Verilog中的信号类型 线网类型 线网类型表示一个或多个门或者其它类型的信号源驱动的硬件连线.如果没有驱动源,则线网的默认值为z.verilog中定义的线网类型有以下几种: wire,tr ...
- Verilog语法
语法子集很小,易用. 模块:module…endmodule 端口:input,output,inout(双向特殊) inout比较难用,有一张真值表,需要大家观察后书写,基本原则就是输入时一定是高阻 ...
随机推荐
- 【数学期望】【高斯消元】bzoj3143 [Hnoi2013]游走
和hdu5955很像.也是注意从结点1出发,其概率要在方程左侧+1. 边的期望和点的期望之间转换巧妙 http://blog.csdn.net/thy_asdf/article/details/473 ...
- FireDac Pooling
1.建立FDManager的ConnectionDef.并设置此Pooling为True. 2.建立Thread类进行多个FDConnection连接DB. 3.本列是oracle远程数据.如下图: ...
- 静态NAT地址转换
1.配置路由器端口ip(两个端口需要设置两个网段) Router(config)#inter f0/1 Router(confiog-if)#ip add 202.1.1.2 255.255.255. ...
- 使用virtualenv为应用提供了隔离的Python运行环境
在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4.所有第三方的包都会被pip安装到Python3的site-packages目录下. 如果我们要同时开发多个应用程序,那这 ...
- JavaScript跳转到页面某个锚点#
JavaScript跳转到页面某个锚点: scroll(0, document.getElementById('锚点ID').offsetTop);
- 网络采集软件核心技术剖析系列(3)---如何使用C#语言下载博文中的全部图片到本地并可以离线浏览
一 本系列随笔概览及产生的背景 本系列开篇受到大家的热烈欢迎,这对博主是莫大的鼓励,此为本系列第三篇,希望大家继续支持,为我继续写作提供动力. 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受 ...
- Android 多线程之HandlerThread 完全详解
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- 加入新的linux系统调用
上一篇详解了linux系统调用的原理,接下来依据上一篇的原理简介怎样创建新的linux系统调用 向内核中加入新的系统调用,须要运行3个步骤: 1. 加入新的内核函数 2. 更新头文件unistd.h ...
- C语言中的联合体union所占内存方式
当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union).在C Programming Language 一书中对于联合体是这么描述的: 1)联合体是一个结构: ...
- 警惕rapidxml的陷阱(二):在Android上默认内存池分配数组过大,容易导致栈溢出
上一篇随笔中提到了,rapidxml在每个xml对象中维护了一个内存池,自己管理变量的生存周期.看起来很好,但我们在实际使用中还是出现了问题. 项目中我们的模块很快写好了,在windows和linux ...