Verilog
程序设计语句
数据流建模
显式连续赋值语句:
<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。
注意事项:
- 赋值目标只能是线网类型(wire)。
-
在连续赋值中,只要赋值语句右边表达式任何一个变量有变化,表达式立即被计算, 计算的结果立即赋给左边信号(若没有定义延时量)。
-
连续赋值语句不能出现在过程块中。
-
多个连续赋值语句之间是并行关系,因此与位置顺序无关。
-
连续赋值语句中的延时具有硬件电路中惯性延时的特性,任何小于其延时量的信号变化脉冲都将被滤除掉,不会出现在输出端口。
行为级建模
可综合描述语句:
过程语句 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过程语句通常用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值。
initial过程块在进行仿真时从模拟0时刻开始执行,它在仿真过程中只执行一次,在执
行完一次后该initial过程块就被挂起,不再执行。
initialbegin语句I;语句2; 语句n;end
module initial_tb1:reg A, B, C;initialbeginA = 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过程语句
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上升沿触发beginif(!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 低电平清零有效beginif(!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 1if(条件表达式) //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:语句块ndefault:语句块 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)begincase(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;endcaseend
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;initialbeginclock = 0;forever #50clock = ~clock;end
endmodule
repeat 语句
repeat(循环次数表达式) 语句或语句块(循环体)
module repeat_tb; //使用repeat语句产生固定周期数的时钟信号。reg clock;inilialbeginclock = 0;repeat(8) clock = -clock; //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号end
endmodule
while 语句
while(条件表达式)语句或语句块;
module while_tb;reg clock;initialbeginclock = 0;while(l)#50 clock = ~clock;end
endmodule
for语句
for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
module for_clk;reg cik;integer i;initialbeginelk = 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;elsebeginfor (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); 〃半加器模块 halfadderinput 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); 〃全加器模块 fulladderinput 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);
endmodulemodule topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topiinput 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); 〃修改全加器模块参数的模块 top2input 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
Verilog
程序设计语句
数据流建模
显式连续赋值语句:
<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。
注意事项:
- 赋值目标只能是线网类型(wire)。
-
在连续赋值中,只要赋值语句右边表达式任何一个变量有变化,表达式立即被计算, 计算的结果立即赋给左边信号(若没有定义延时量)。
-
连续赋值语句不能出现在过程块中。
-
多个连续赋值语句之间是并行关系,因此与位置顺序无关。
-
连续赋值语句中的延时具有硬件电路中惯性延时的特性,任何小于其延时量的信号变化脉冲都将被滤除掉,不会出现在输出端口。
行为级建模
可综合描述语句:
过程语句 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过程语句通常用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值。
initial过程块在进行仿真时从模拟0时刻开始执行,它在仿真过程中只执行一次,在执
行完一次后该initial过程块就被挂起,不再执行。
initialbegin语句I;语句2; 语句n;end
module initial_tb1:reg A, B, C;initialbeginA = 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过程语句
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上升沿触发beginif(!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 低电平清零有效beginif(!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 1if(条件表达式) //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:语句块ndefault:语句块 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)begincase(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;endcaseend
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;initialbeginclock = 0;forever #50clock = ~clock;end
endmodule
repeat 语句
repeat(循环次数表达式) 语句或语句块(循环体)
module repeat_tb; //使用repeat语句产生固定周期数的时钟信号。reg clock;inilialbeginclock = 0;repeat(8) clock = -clock; //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号end
endmodule
while 语句
while(条件表达式)语句或语句块;
module while_tb;reg clock;initialbeginclock = 0;while(l)#50 clock = ~clock;end
endmodule
for语句
for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
module for_clk;reg cik;integer i;initialbeginelk = 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;elsebeginfor (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); 〃半加器模块 halfadderinput 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); 〃全加器模块 fulladderinput 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);
endmodulemodule topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topiinput 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); 〃修改全加器模块参数的模块 top2input 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