Verilog中的信号类型

线网类型

线网类型表示一个或多个门或者其它类型的信号源驱动的硬件连线。如果没有驱动源,则线网的默认值为z。verilog中定义的线网类型有以下几种:     wire,tri,wor,trior,wand,triand,trireg,tri1,tri0,supply0,supply1。其中最主要的是wire/tri,其它的类型都是综合中用不到的线网。

wire线网用来连接线路中一个逻辑模块的输出和另一个逻辑模块的输入,通常用来表示单个门驱动或连续赋值语句驱动的连线型数据。下面是wire类型的声明例子。

wire x;

wire [3:0] s;

wire [2:1] s1; //范围可以不从0开始

tri类型线网表示电路的连接以三态方式进行。它和wire是等价的,它只是用来提高三态门代码的可读性。例如:

tri z;

tri [7:0] out;

比如下面的三态门代码,它们分析与综合后,是相同的逻辑电路。

module trigate1(in,en,out);

  input in;
input en;
output out;
wire out; assign out = en?in:'bz; endmodule module trigate2(in,en,out); input in;
input en;
output out;
wire out; bufif1(out,in,en);//或者可以用bufif1 mybufif1(out,in,en); endmodule
module trigate3(in,en,out); input in;
input en;
output out;
tri out; assign out = en?in:'bz; endmodule module trigate4(in,en,out); input in;
input en;
output out;
tri out; bufif1(out,in,en);//或者可以用bufif1 mybufif1(out,in,en); endmodule

在quartus中分析与综合上面代码中的四个模块,用rtl view看到的逻辑电路如下所示:trigate1, trigate2,trigate3,trigate4,都是对应形同的三态门。

用下面的testbench代码,从波形中我们可以看到这四个模块都实现三态门的逻辑。

`timescale 1ns/1ns

module trigate_tb;

   reg in1,in2,in3,in4;
reg en;
wire out1, out2;
tri out3,out4; trigate1 trigate1_0(.in(in1),.en(en),.out(out1));
trigate2 trigate2_0(.in(in2),.en(en),.out(out2));
trigate3 trigate3_0(.in(in3),.en(en),.out(out3));
trigate4 trigate4_0(.in(in4),.en(en),.out(out4)); initial
begin
en = 1'b0;
in1 = 1'b1;
#10
in2 = 1'b0;
#10
in3 = 1'b1;
#10
in4 = 1'b0; //en =0, out1/out2/out3/out4 都为高阻态
#10
en = 1'b1; //此时,out1=in1, ...,out4=in4
#10;
$stop; end endmodule

当一个线网有多个驱动源时,即对一个线网有多个赋值时,不同的线网产生不同的行为。例如:

wire r;

assign r = a & b;

assign r = c | d;

r有两个驱动源,由于它是线网,r的有效值由使用驱动源的值的线表决定(下面的wire/tri表),如果如上图所示,则r为x。

如果有多个驱动源,线网的有效值如下表:可以看到只要输入端有x,输出端一定为x,而z状态是最弱的,只要有其它状态都能改变输出值。输入为0和1,输出为x。

wire/tri

0

1

x

z

0

0

x

x

0

1

x

1

x

1

x

x

x

x

x

z

0

1

x

z

备注:在quartus+modelsim中,这样代码不能通过编译的,所以应该是不可综合的,只能在testbench中使用。

Error (10028): Can't resolve multiple constant drivers for net "r" at mulassign.v(7),。

module mulassign(a,b,r);
input a,b;
output r;
wire r; assign r = a;
assign r = b; endmodule

直接把module包含在testbench中,用vcs编译的。然后run simv,得到下面结果,和上面表中的值是匹配的:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 16:10 2018
                    0  0  0 final result 0}
                   10  1  1 final result 1}
                   20  0  1 final result x}
                   30  1  0 final result x}
                   40  z  z final result z}
                   50  x  1 final result x}
                   60  x  z final result x}
                   70  0  x final result x}

`timescale 1ns/1ns
`include "mulassign.v" module mulassign_tb;
reg a,b,c,d;
wire r;
mulassign mulassign_0(.a(a),.b(b),.c(c),.d(d),.r(r)); initial
begin
a = 1'b0;b=1'b0; c=1'b0; d= 1'b0; // 0 0
#10
a = 1'b1;b=1'b1; c=1'b0; d= 1'b1; //1,1
#10
a = 1'b0;b=1'b1; c=1'b0; d= 1'b1;//0 1
#10
a = 1'b1;b=1'b1; c=1'b0; d= 1'b0;//1,0
#10
a = 1'bz;b=1'bz; c=1'bz; d= 1'bz;
#10
a = 1'bx;b=1'b1; c=1'b0; d= 1'b1;
#10
a = 1'b0;b=1'b1; c=1'bx; d= 1'b1;
#10
a = 1'b0;b=1'b1; c=1'bz; d= 1'b1;
end initial
begin
$monitor($time,,,"%b & %b, %b | %b, final result %b}", a, b, c,d,r);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

wor和trior线网:对于wor如果某个驱动源为1,那么线网的值也是1,wor和三态或(trior)在语法和功能上是一致的。如果多个驱动源驱动这类网,网的有效值由下表决定:

wor/trior

0

1

x

z

0

0

1

x

0

1

1

1

1

1

x

x

1

x

x

z

0

1

x

z

module mulassign1(a,b,r);
input a,b;
output r;
wor r;
assign r = a;
assign r = b; endmodule
`timescale 1ns/1ns
`include "mulassign1.v" module mulassign_tb;
reg a,b;
wire r;
mulassign1 mulassign1_0(.a(a),.b(b),.r(r)); initial
begin
a = 1'b0;b=1'b0;
#10
a = 1'b1;b=1'b1;
#10
a = 1'b0;b=1'b1;
#10
a = 1'b1;b=1'b0;
#10
a = 1'bz;b=1'bz;
#10
a = 1'bx;b=1'b1;
#10
a = 1'bx;b=1'bz;
#10
a = 1'b0;b=1'bx;
end initial
begin
$monitor($time,,,"%b %b final result %b}", a, b,r);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

用上面的代码,用vcs编译后,运行simv可以得到如下的结果,可见是要某个信号源为1,则结果为1:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 17:37 2018
                    0  0  0 final result 0}
                   10  1  1 final result 1}
                   20  0  1 final result 1}
                   30  1  0 final result 1}
                   40  z  z final result z}
                   50  x  1 final result 1}
                   60  x  z final result x}
                   70  0  x final result x}

$finish called from file "mulassign1_tb.v", line 31.

wand和triand线网,线与(wand)如果某个驱动源为0,那么线网的值为0。线与和三态线与(triand)网在语法和功能上是一致的。

wand/triand

0

1

x

z

0

0

0

0

0

1

0

1

x

1

x

0

x

x

x

z

0

1

x

z

module mulassign2(a,b,r);
input a,b;
output r;
wand r;
assign r = a;
assign r = b; endmodule
`timescale 1ns/1ns
`include "mulassign2.v" module mulassign_tb;
reg a,b;
wire r;
mulassign2 mulassign2_0(.a(a),.b(b),.r(r)); initial
begin
a = 1'b0;b=1'b0;
#10
a = 1'b1;b=1'b1;
#10
a = 1'b0;b=1'b1;
#10
a = 1'b1;b=1'b0;
#10
a = 1'bz;b=1'bz;
#10
a = 1'bx;b=1'b1;
#10
a = 1'bx;b=1'bz;
#10
a = 1'b0;b=1'bx;
end initial
begin
$monitor($time,,,"%b %b final result %b}", a, b,r);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

用vcs编译后,运行simv,得到以下结果,可见只要有信号源为0,则结果为0:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 17:47 2018
                    0  0  0 final result 0}
                   10  1  1 final result 1}
                   20  0  1 final result 0}
                   30  1  0 final result 0}
                   40  z  z final result z}
                   50  x  1 final result x}
                   60  x  z final result x}
                   70  0  x final result 0}

$finish called from file "mulassign2_tb.v", line 31.

trireg线网,此线网存储数值,并且用于电容节点建模。当三态寄存器(trireg)的所有驱动源都处于高阻态,即值为z时,三态寄存器线网保存以前的值。三态寄存器线网的缺省初始值为x。

module mulassign3(a,b,r);
input a,b;
output r;
trireg r;
assign r = a;
assign r = b; endmodule
`timescale 1ns/1ns
`include "mulassign3.v" module mulassign_tb;
reg a,b;
wire r;
mulassign3 mulassign3_0(.a(a),.b(b),.r(r)); initial
begin
a = 1'b0;b=1'b0;
#10
a = 1'b1;b=1'b1;
#10
a = 1'bz;b=1'bz;
#10
a = 1'b0;b=1'b0;
#10
a = 1'bz;b=1'bz;
#10
a = 1'b1;b=1'b0;
#10
a = 1'bz;b=1'bz;
#10
a = 1'b0;b=1'bx;
end initial
begin
$monitor($time,,,"%b %b final result %b}", a, b,r);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

用上面的代码,vcs编译后,运行simv,得到以下结果:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 18:46 2018
0 0 0 final result 0}
10 1 1 final result 1}
20 z z final result 1}
30 0 0 final result 0}
40 z z final result 0}
50 1 0 final result x}
60 z z final result 0}
70 0 x final result x}

tri0和tri1线网,分别用来建模下拉电阻和上拉电阻。这类线网可用于线逻辑的建模,即线网有多于一个驱动源,tri0线网的特征是,若无驱动源驱动,它的值为0,tri1与其相反。

tri0/tri1

0

1

x

z

0

0

x

x

0

1

x

1

x

1

x

x

x

x

x

z

0

1

x

0(1)

module mulassign(a,b,r);
input a,b;
output r;
tri0 r;
assign r = a;
assign r = b;
endmodule
module mulassign1(a,b,r);
input a,b;
output r;
tri1 r;
assign r = a;
assign r = b;
endmodule

`timescale 1ns/1ns
`include "mulassign4.v" module mulassign_tb;
reg a,b;
wire r,r1;
mulassign mulassign_0(.a(a),.b(b),.r(r));
mulassign1 mulassign1_0(.a(a),.b(b),.r(r1)); initial
begin
a = 1'b0;b=1'b0;
#10
a = 1'b1;b=1'b1;
#10
a = 1'b0;b=1'b1;
#10
a = 1'b1;b=1'b0;
#10
a = 1'bz;b=1'bz;
#10
a = 1'bx;b=1'b1;
#10
a = 1'bx;b=1'bz;
#10
a = 1'b0;b=1'bx;
end initial
begin
$monitor($time,,,"%b %b final result %b %b}", a, b,r,r1);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

上面的代码vcs编译后,运行simv得到以下结果:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 19:09 2018
                    0  0  0 final result 0 0}
                   10  1  1 final result 1 1}
                   20  0  1 final result x x}
                   30  1  0 final result x x}
                   40  z  z final result 0 1}
                   50  x  1 final result x x}
                   60  x  z final result x x}
                   70  0  x final result x x}

supply0和supply1线网,supply0用于对地建模,即低电平0,supply1用于对电源建模,即高电平1。

如下例所示:

supply1  vdd;

supply0  gnd;

assign a=vdd; //connect to vdd

assign b=gnd; //Connectb to gnn

`timescale 1ns/1ns

module mulassign_tb;
wire a,b;
supply1 vdd;
supply0 gnd;
assign a=vdd; //connect to vdd
assign b=gnd; //Connectb to gnn initial
begin
$monitor($time,,,"%b %b }", a, b);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 19:29 2018
                   0  1  0 }

$finish called from file "supply_tb.v", line 13.

未说明的线网,在Verilog HDL中,有可能不必声明某种线网类型,在这样的情况下,缺省线网类型为1位wire类型线网。可以使用`default_nettype编译器指令改变隐式线网说明,例如:`default_nettype wand,但是default_nettype不能是supply0/supply1。

向量和标量线网:在定义向量线网时可选用关键词scalared或vectored。如果一个线网定义时使用了关键词vectored,那么就不允许位选操作和部分选择该线网。如果没有定义关键词,缺省值为scalared。

下面的代码可以用vcs编译,运行simv,得到结果,好像vcs和modelsim中,使用vectored定义wire,这个不允许位选操作和部分选择该线网并不成立。

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Dec 27 20:53 2018
                   0  10101010  010z }

$finish called from file "wirev_tb.v", line 12

`timescale 1ns/1ns

module mulassign_tb;
wire vectored [7:0] a;
wire vectored [3:0] b;
assign a=8'b10101010;
assign b[3:1]=a[4:2]; initial
begin
$monitor($time,,,"%b %b }", a, b);
#400 $finish;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule;

变量类型

线网提供了一种逻辑元件互联的方式,但线网不能以行为的方式来描述电路,保持电路中间的信号值。为了达到这个目的,verilog提供了变量,可以在一条verilog语句中给一个变量赋值,这个变量会一直保持这一个值,直到被随后的赋值语句覆盖。变量的类型以下几种:reg和integer,time, real/realtime

integer i;

reg[2:0] count;

count=0;

for(i=0;i<4;i=i+1)

count = count +1

上面的代码中count是电路行为级模型,所以不能用wire,只能用reg。注意:integer主要用来控制循环变量,本身并不对应电路的结点。

integer可以作为普通reg类型使用,典型应用为高层次行为建模。使用整数型形式说明如下:

integer integer1,integer2,...,integerN[msb:lsb];

例如:

integer A,B,C; //表示三个integer类型变量

integer Hist [3:6]; //一组四个integer类型变量。

一个整数型寄存器可存储有符号数,并且算术操作符提供2的补码运算结果。整数不能作为位向量访问。一种截取位值的方法是将整数赋值给一般的reg类型变量,然后从中选取相应的位。

================

reg [31:0] Breg;

integer Bint;

Breg = Bint; //直接访问Bint[6]和Bint[20:10]是不允许的,但是Breg[6]和Breg[20:10]是允许的了。

time类型的寄存器用于存储和处理时间, time是一个无符号整数变量,位宽是64位。例如:time Events [0:31]; //时间值数组

time CurrTime; //currtime存储一个时间值。

real和realtime类型,real是有符号的浮点数,双精度。real寄存器使用如下:

real real_reg 1, real_reg2, . . ., real_regN;

real和realtime类型和使用完全相同。real说明的变量的缺省值为0,不允许对real声明值域、位界限或字节界限。real类型和reg类型没有一一对应的关系。

下面是time和real/real time的实例代码,从结果中可以看出time和real/realtime的区别,time只显示10ns倍数的整数,而realtime和real则可以显示精确的时间。

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11; Dec 26 09:14 2018

t1 = 0, t2 = 0.000000, t3 = 0.000000, set = 0

t1 = 2, t2 = 1.600000, t3 = 1.600000, set = 1

t1 = 3, t2 = 3.200000, t3 = 3.200000, set = 2

V C S S i m u l a t i o n R e p o r t

`timescale 10ns/1ns
module test;
reg [7:0] set;
time t1;
realtime t2;
real t3;
parameter p=1.6;
initial
begin
set = 0;
t1 = $time;
t2 = $realtime;
t3 = $realtime;
$display("t1 = %d, t2 = %f, t3 = %f, set = %d",t1,t2,t3,set);
#p set=1;
t1 = $time;
t2 = $realtime;
t3 = $realtime;
$display("t1 = %d, t2 = %f, t3 = %f, set = %d",t1,t2,t3,set);
#p set=2;
t1 = $time;
t2 = $realtime;
t3 = $realtime;
$display("t1 = %d, t2 = %f, t3 = %f, set = %d",t1,t2,t3,set);
end
endmodule

有符号数

Verilog中,线网和变量都可以声明成有符号数(signed),其中integer类型总是有符号的。例如:reg signed [15:0] a; 我们来看看下面的代码:

reg signed [7:0] a, b;

reg signed [3:0] c;

reg signed [7:0] sum1, sum4;

// same width. can be applied to signed and unsigned

sum1 = a + b;

// automatic sign extension

sum4 = a + c;

第一条语句将引用一个常规的加法器,因为a、b和sum1具有相同的位宽。

第二条语句,所有的右手边变量都具有signed数据类型,c被自动扩展符号位到8位。因此,无需再手动添加符号位。

在小型的数字系统中,我们通常可以选用有符号数或者无符号数。然而,在一些大型的系统中,会包括不同形式的子系统。Verilog是一种弱类型语言。无符号变量和有符号变量可以在同一表达式中混用。根据Verilog的标准,只有当所有右手边的变量具有signed数据类型属性的时候,扩展符号位才被执行。否则,所有的变量都只扩展0。考虑下面的代码片段:

reg signed [7:0] a, sum;

reg signed [3:0] b;

reg [3:0] c;

sum = a + b + c;

由于c不具有signed数据类型属性,因此右手边的变量b和c的扩展位为0。

Verilog有两个系统函数,$signed和$unsigned(),用以将括号内的表达式转换为signed和unsigned数据类型。比方说,我们可以转换c的数据类型,

sum = a + b + $signed(c);

现在,右手边的所有变量都具有signed数据类型属性,因此b和c将扩展符号位。

在复杂的表达式中,混用signed和unsigned数据类型将引入一些微妙的错误,因此应当避免混用。如果真的很有必要,那么表达式需要保持简单,同时通用转换函数,以确保数据类型的一致性。

数组

Verilog中,wire和reg类型都可以声明为多维数组,形式和c语言多维数组很像。例如:

reg [7:0] a[0:1023][0:511];

wire和reg类型的区别

wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)。reg表示一定要有触发,输出才会反映输入的状态。reg相当于存储单元,wire相当于物理连线。

reg表示一定要有触发,没有输入的时候可以保持原来的值,但不直接和实际的硬件电路对应。两者的区别是:寄存器型数据保持最后一次的赋值,而线网型数据需要持续的驱动。wire使用在连续赋值语句中,而reg使用在过程赋值语句(initial ,always)中。wire若无驱动器连接,其值为z,reg默认初始值为不定值 x 。

verilog语法实例学习(2)的更多相关文章

  1. verilog语法实例学习(4)

    Verilog模块 Verilog中代码描述的电路叫模块,模块具有以下的结构: module module_name[ (portname {, portname})]; //端口列表 [parame ...

  2. verilog语法实例学习(1)

    本文档中通过verilog实例来学习verilog语法.Verilog是一种硬件描述语言,它具有并发性和时序性.并发性是指不同硬件模块的同时操作,时序性是指信号的赋值或操作在时钟的边沿进行.由于作者本 ...

  3. verilog语法实例学习(12)

    verilog中的综合和不可综合总结 Verilog中综合的概念 综合就是EDA工具或者说综合工具把我们编写的verilog代码转化成具体电路的过程.Verilog中有很多语法,结构,过程,语句,有些 ...

  4. verilog语法实例学习(6)

    函数和任务 函数 https://wenku.baidu.com/view/d31d1ba8dd3383c4bb4cd283.html verilog中函数的目的是允许代码写成模块的方式而不是定义独立 ...

  5. verilog语法实例学习(5)

    子电路模块 子电路模块的使用 一个verilog模块能够作为一个子电路包含在另一个模块中.采用这种方式,所有的模块都必须定义在一个文件中,那么verilog编译器就必须被告知每个模块的所属.模块例化的 ...

  6. verilog语法实例学习(13)

    verilog代码编写指南 变量及信号命名规范  1. 系统级信号的命名.  系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号:系统信号以字符串Sys开头.  2. 低电平有效的 ...

  7. verilog语法实例学习(11)

    同步时序电路的一般形式 时序电路由组合逻辑以及一个或多个触发器实现.一般的架构如下图所示:W为输入,Z为输出,触发器中存储的状态为Q.在时钟信号的控制下,触发器通过加在其输入端的组合逻辑输入,使得电路 ...

  8. verilog语法实例学习(10)

    常用的时序电路介绍 T触发器和JK触发器 在D触发器输入端添加一些简单的逻辑电路,可以生成另一种类型的存储元件.比如下图所示的T触发器.该电路有一个上升沿触发的触发器和两个与门,一个或门,以及一个反相 ...

  9. verilog语法实例学习(9)

    常用的时序电路介绍 寄存器 一个触发器可以存储一位数据,由n个触发器组成的电路可以存储n位数据,我们把这一组触发器叫做寄存器.寄存器中每个触发器共用同一个时钟. 下面是n位寄存器的代码,我们通过一个参 ...

随机推荐

  1. Web大前端面试题-Day4

    1. 如何实现瀑布流? 瀑布流布局的原理:1) 瀑布流布局要求要进行布置的元素等宽,   然后计算元素的宽度,   与浏览器宽度之比,得到需要布置的列数;2) 创建一个数组,长度为列数,   里面的值 ...

  2. android 对称加密,非对称加密 android 常见的加密

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha android 常见的加密 ======== 不可逆加密:md5,sha1 可逆的加密中 ...

  3. P4745 B’s problem(b)

    P4745 B’s problem(b) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 NOIP春季系列课程 描述 题目描述 小B生活在一个很奇怪的国家里, ...

  4. [POI2014]Rally

    OJ题号:BZOJ3832.洛谷3573 思路: 建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$. 对于每条边$i$,设定一个权值$w_i=diss_ ...

  5. hdu 3534 树形dp ***

    题意:统计一棵带权树上两点之间的最长距离以及最长距离的数目 链接:点我 首先统计出结点到叶子结点的最长距离和次长距离. 然后找寻经过这个点的,在这个为根结点的子树中的最长路径个数目. #include ...

  6. BZOJ3500 : PA2008 Cliquers

    设g[i]表示n=i时的答案,则OEIS上可以找到如下递推式: g[i]=g[i-1]+g[i-2]-g[i-5]-g[i-7]+... 其中符号为++--交替,第i项为f[i],f[1]=1,f[2 ...

  7. AIM Tech Round 3 (Div. 1) B. Recover the String 构造

    B. Recover the String 题目连接: http://www.codeforces.com/contest/708/problem/B Description For each str ...

  8. centos7 打造基于python语言Selenium2自动化开发环境

    1. 准备 安装模块 # yum groupinstall "Development tools" # yum install zlib-devel bzip2-devel ope ...

  9. excel宏整理

    工作以后发现excel很强大,用好excel已经成功工作中很重要的一部分内容,最近写了一些宏, 整理如下: 根据excel生成sql脚本的sc_template Sub GenSCTemplateFi ...

  10. TIDB VS COCKROACHEB

    分布式事务 要支持分布式事务,首先要解决的就是分布式系统时间的问题,也就是我们用什么来标识不同事务的顺序.通常有几种做法: TrueTime,TrueTime 是 Google Spanner 使用的 ...