显式连续赋值语句:
assign #
隐式连续赋值语句:
ps. wire(strong0, weak1)[3:0]#(2, 1, 3) w = (a^b)&(m^n); //对于变量w:赋“0”值时的驱动强度较强,为strong:赋“1”值时的驱动强度较弱,为weak。比如,当0和1共同驱动变量w时,由于0定义的驱动强度较强,所以w为0。
注意事项:
在连续赋值中,只要赋值语句右边表达式任何一个变量有变化,表达式立即被计算, 计算的结果立即赋给左边信号(若没有定义延时量)。
连续赋值语句不能出现在过程块中。
多个连续赋值语句之间是并行关系,因此与位置顺序无关。
连续赋值语句中的延时具有硬件电路中惯性延时的特性,任何小于其延时量的信号变化脉冲都将被滤除掉,不会出现在输出端口。
过程语句 always
语句块 串行语句块begin-end
赋值语句 过程赋值语句=、<=
条件语句 if-else case, casez, casex
循环语句 for
编译向导语句 'define 'include 'ifdef, 'else, 'endif
不可综合描述语句:
过程语句 initial
语句块 并行语句块fork-join
赋值语句 过程连续赋值语句assign
循环语句 forever repeat while
编译向导语句 'define 'include 'ifdef, 'else, 'endif
initial过程语句通常用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值。
initial过程块在进行仿真时从模拟0时刻开始执行,它在仿真过程中只执行一次,在执
行完一次后该initial过程块就被挂起,不再执行。
initial
begin
语句I;
语句2;
语句n;
end
module initial_tb1:
reg A, B, C;
initial
begin
A = 0;B= 1;C = O;
#100 A= 1; B = 0;
#100 A = 0;C= I;
#100 B = 1;
#100 B = 0; C = 0;
end
endmodule
always@(<敏感事件列表>)
语句块;
@(a) //当信号a的值发生改变时
@(a or b) //当信号a或信号b的值发生改变时
@(posedge clock) //当clock的上升沿到来时
@(negedge clock) //当clock的下降沿到来时
@(posedge elk or negedge reset) //当clk的上升沿到来或reset信号的下降沿(低电平有效)到来时
注意事项:
在信号的形式定义方面,无论是对时序逻辑电路还是对组合逻辑电路进行描述,Verilog HDL要求在过程语句(initial和always)中,被赋值信号必须定义为“reg”类型。
敏感事件列表:
采用过程语句对组合电路进行描述时,需要把全部的输入信号列入敏感事件列表。
采用过程语句对时序电路进行描述时,需要把时间信号和部分输入信号列入敏感事件列表
四选一数据选择器
/*四选一数据选择器*/
module mux4_l(out, in0, in1, in2, in3, sel):
output out;
input in0, ini, in2, in3;
inpul[1 :0] sel;
reg out; 〃被赋值信号定义为“reg”类型
always @(in0 or ini or in2 or in3 or sel) 〃敏感事件列表
case(sel)
2'b00: out = inO;
2'b01: out = ini;
2'b10: out = in2;
Z'b11: out = in3;
default: out = 2'bx;
endcase
endmodule
同步置数、同步清零计数器:
module counter 1 (out, data, load, rst, elk);
output[7:0] out;
input[7:0] data;
input load, elk, rst;
reg[7:0] out;
always @(posedge elk) //clk上升沿触发
begin
if(!rst) out = 8'h00; //同步清零,低电平有效
else if(load) out = data; //同步置数
else out = out+ 1;
end
endmodule
异步清零计数器:
module counter2(rst, elk, out);
output[7:0] out;
input elk, rst;
reg[7:0] out;
always @(posedge clk or negedge rst) // clk 上升沿和 rst 低电平清零有效
begin
if(!rst) //异步清零
out = 0;
else out = out+1;
end
endmodule
串行语句块:其中的语句按串行方式顺序执行,可以用于可综合电路程序和仿真测试程序
块名即该块的名字,当块内有变量时必须有块名,否则在编译时将出现语法错误。块内声明语句是可选的,可以是参数说明语句‘integer型变量声明语句、reg型变量声明语句、time型变量声明语句和事件(event)说明语句。
begin:块名
块内声明语句;
语句1;
语句2;
...
语句n;
end
并行语句块:语句按并行方式执行,只能用于仿真测试程序,不能用于可综合电路程序。
fork:块名
块内声明语句:
语句1;
语句2;
...
语句n;
join
两者比较:
语句块 |
串行语句块(begin-cnd) |
并行语句块(fork-join) |
执行顺序 |
按照语句顺序执行 |
所有语句均在同一时刻执行 |
语句前面延迟 时间的意义 |
相对于前一条语句执行结束的相对时间 |
相对于并行语句块启动的时间 |
起始时间 |
首句开始执行的时间 |
转入并行语句块的时间 |
结束时间 |
最后一条语句执行结束的时间 |
执行时间最长的那条语句执行 结束的时间 |
行为描述的 意义 |
电路中的数据在时钟及控制信号的作用下, 沿数据通道中各级寄存器之间传送的过程 |
电路上电后,各电路模块同时开始工作的过程 |
阻塞赋值语句:变量=表达式;
当一个语句块中有多条阻塞赋值语句时,如果前面的赋值语句没有完成,则后面的语句就不能被执行,仿佛被阻塞了一样,因此称为阻塞赋值方式。
特点:
在串行语句块中,各条阻塞赋值语句将按照排列顺序依次执行;在并行语句块中的各条阻塞赋值语句则同时执行,没有先后之分。
执行阻塞赋值语句的顺序是,先计算等号右端表达式的值,然后立刻将计算的值赋给左边的变量,与仿真时间无关。
非阻塞赋值语句 :变量 <=表达式;
特点:
在串行语句块中,各条非阻塞赋值语句的执行没有先后之分,排在前面的语句不会影响到后面语句的执行,各条语句并行执行。
执行非阻塞赋值语句的顺序是,先计算右端表达式的值,然后等待延迟时间的结束,再将计算的值赋给左边的变量。
赋值语句和重新赋值语句:assign deassign:使用assign给寄存器型变量赋值之后,该值将一直保 持在这个寄存器上,直至遇到deassign。
assign <寄存器型变量>=<赋值表达式>;
deassign<寄存器型变量>;
强制语句和释放语句:force release:主要用于Verilog HDL仿真测试程序中,便于对某种信号进行临时性的赋值和测试。
force <寄存器或连线型变量>=<赋值表达式>;
release<寄存器或连线型变量>;
if语句:
if(条件表达式)语句块; //form 1
if(条件表达式) //form 2
语句块1;
else
语句块2;
if(条件表达式1) //form 3
语句块1;
else if(条件表达式2)
语句块2;
...
else if(条件表达式i)
语句块i;
else
语句块n;
case语句:
case(控制表达式)
值1:语句块1
值2:语句块2
...
值n:语句块n
default:语句块 n+l
endcase
case语句的真值表:
case | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
BCD数码管译码:
module BCD_decoder(out, in);
output[6:0]out;
input[3:0]in;
reg[6:0]out;
always@(in)
begin
case(in)
4'b0000:out = 7'b1111110;
4'b0001:out = 7'b0110000;
4'b0010:out = 7'b1101101;
4'b0011:out = 7'b1111001;
4'b0100:out = 7'b0110011;
4'b0101:out = 7'b1011011;
4'b0110:out = 7'b1011111;
4'b0111:out = 7'b1110000;
4'bl000:out = 7'blllllll;
4'bl001:out = 7'bllll011;
default:out = 7'bx;
endcase
end
endmodule
casez:比较双方有一位为z,即认为这一位永远为真
casez | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 1 |
1 | 0 | 1 | 0 | 1 |
x | 0 | 0 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
casex:比较双方有一位为x或z,即认为这一位永远为真
casex | 0 | 1 | x | z |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 1 | 1 | 1 |
x | 1 | 1 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
forever 语句
forever 语句或语句块;
module forever_tb;
reg clock;
initial
begin
clock = 0;
forever #50clock = ~clock;
end
endmodule
repeat 语句
repeat(循环次数表达式)
语句或语句块(循环体)
module repeat_tb; //使用repeat语句产生固定周期数的时钟信号。
reg clock;
inilial
begin
clock = 0;
repeat(8) clock = -clock; //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号
end
endmodule
while 语句
while(条件表达式)语句或语句块;
module while_tb;
reg clock;
initial
begin
clock = 0;
while(l)
#50 clock = ~clock;
end
endmodule
for语句
for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
module for_clk;
reg cik;
integer i;
initial
begin
elk = 0;
for(i = 0; i >= 0: i = i+1)
#50 elk = ~clk;
end
endmodule
8位移位寄存器
//采用赋值语句实现
module shift_registl(Q, D, rst, elk);
output [7:0] Q;
input D, rst, elk:
reg [7:0] Q;
always @(posedge elk)
if(!rst) Q <= 8'b000000;
else Q <= {Q[6:0], D};
endmodule
//采用for语句实现
module shift_regist2(Q, D, rst, elk);
output [7:0] Q;
input D, rst, elk;
reg [7:0] Q;
integer i;
always @(posedge elk)
if(!rst)Q<= 8'b000000;
else
begin
for (i = 7; i > 0; i = i-1) Q[i] <= Q[i-1];
Q[0] <= D;
end
endmodule
模块名〈参数值列表〉实例名(端口名列表);
端口位置对应方式
模块名〈参数值列表〉实例名(<信号名1>. <信号名2>, …,<信号名n>);
端口名对应方式
模块名〈参数值列表〉实例名(.端口名1<信号名1>, .端口名2<信号名2>, …,.端口名n<信号名 n>):
dff U4(.q(), ,d(out[2]), .clk(clock), .clr(clear)); //端口列表中第一项内的信号名是缺省的(空括号),表明端口 “q”悬空。
使用带有参数的模块实例语句修改参数值
模块名〈参数值列表〉调用名(端口名列表);
para l #(4, 3) U1(C1,D1); //利用位置对应方式将4传给a、3传给b,这和模块paral中定义参数的先后顺序有关;
paral #(.b(6), ,a(5)) U2(C2,D2); //利用名称对应方式将6传给b、5传给a,此时和模块paral中定义参数的顺序无关。
使用参数重定义语句defparam修改参数值
defparam
参数名1 =参数值1,
参数名2 =参数值2,
...
参数名n =参数值n;
module halfadder(a, b, s, c); 〃半加器模块 halfadder
input a, b:
output c, s;
parameter xor_delay = 2, and_delay = 3:
assign #xor_delay s = aAb;
assign #and_delay c = a&b;
endmodule
module fulladder(p, q, ci, co, sum); 〃全加器模块 fulladder
input p, q, ci;
output co, sum;
parameter or_delay = 1;
wire wl, w2, w3;
halfadder Ul(p, q, wl, w2);
halfadder U2(ci, w 1, sum, w3);
or #or_delay U3(co, w2, w3);
endmodule
module topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topi
input top la, top lb;
output topis, topic;
defparam U1 .xor_delay = 4,
U1 .and_delay = 5;
//名为U1的半加器实例中对参数xor_delay和参数and_delay值的修改
halfadder Ul(topla, top lb, topis, topic);
endmodule
module top2(top2p, top2q, lop2ci, top2co, top2sum); 〃修改全加器模块参数的模块 top2
input top2p, top2q, top2ci;
output top2co, top2sum;
defparam U2.U1.xor_delay = 6,
U2.U2.and_deIay = 7;
//名为U2的全加器实例中引用的名为U3的半加器实例中对参数xor_delay和
//参数and.delay值的修改
U2.or_delay = 5;
//名为U2的全加器实例中对参数or_delay值的修改
fulladder U2(lop2p, top2q, top2ci, top2co, lop2sum);
endmodule
Verilog HDL中内置有26个基本元件,其中14个是门级元件,12个为开关级元件
类型 | 元 件 |
|
基本门 |
多输入门 |
and, nand, or, nor, xor, xnor |
多输出门 |
buf, not |
|
三态门 |
允许定义驱动强度 |
bufif0, bufif1, notif0, notif1 |
MOS开关 |
无驱动强度 |
nmos, pmos, emos rnmos, rpmos, rcmos |
双向开关 |
无驱动强度 |
tran, tranif0, tranif1 rtran, rtranifO0, rtranif1 |
上拉、下拉电阻 |
允许定义驱动强度 |
pullup, pulldown |
门级模块调用
多输入门元件
元件名<实例名>(<输出端口>,<输入端口 1>,<输入端口 2>, <输入端口 n>);
and Al (outl, ini, in2);
or O2 (a, b, c, d);
xor X1 (x_out, pl, p2);
多输出门元件
元件名<实例名>(<输出端口 1>,<输出端口 2>,…,〈输出端口 n>,〈输入端口>);
not NOT_1 (outl, out2, in);
buf BUF_1 (bufoutl, bufout2, bufout3, bufin);
三态门元件
元件名<实例名>(<数据输出端口>,<数据输入端口>,<控制输入端口>);
bufifl BF1 (data_bus, mem_data, enable);
bufifO BFO (a, b, c);
notifl NT1 (out, in, Ctrl);
notifD NTO (addr, a_bus, select);
2线-4线译码器
module decoder2_4(in0, ini, en, outO, outl, out2, out3);
output outO, outl, out2, out3;
input inO, ini, en;
wire wirel, wire2;
not Ul(wirel» inO),
U2(wire2, ini);
nand U3(outO, en, wirel, wire2),
U4(outl, en, wire 1, ini),
U5(out2, en, inO, wire2),
U6(out3, en, inO, ini);
endmodule
Verilog HDL提供了十几种开关级基本元件,它们是实际的MOS管的抽象表示。这些
开关级基本元件分为两大类:一类是MOS开关,一类是双向开关。每一大类又可分为电阻
型(前缀用r表示)和非电阻型。
MOS开关:nmos、pmos、cmos
nmos和pmos开关的实例化语言格式如下:
nmos/pmos 实例名(out, data, control);
coms开关的实例化语言格式如下:
cmos 实例名(out, data, ncontrol, pcontrol)
双向开关:无条件双向开关(tran)和有条件双向开关(tranif0、tranif1)
tran 实例名(inoutl > inout2);
tranifO/tranifl 实例名(inoutl, inout2, control);
nmos
module aNMOS(din, ctr, out);
input din, ctr;
output out;
nmos Ul(oul, din, ctr);
endmodule
2输入与非门的cmos电路
module nnand2(a, b, y);
input a, b;
output y;
supplyO Gnd;
supply1 Vdd: //supplyO 和 supply!为内部参
//量,分别表示低电平和高电平
wire iml;
pmos gl(y, Vdd, a);
pmos g2(y, Vdd, b);
nmos g3(y, iml, a);
nmos g4(iml, Gnd, b);
endmodule