赞
踩
显式连续赋值语句:
<net_declaration><range><name>;
assign #<delayxname> = Assignment expression;
隐式连续赋值语句:
<net_declaiation><drive_strength><range>#<delay><name> = assignment expression;
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。