Verilog HDL举例1.docx
《Verilog HDL举例1.docx》由会员分享,可在线阅读,更多相关《Verilog HDL举例1.docx(18页珍藏版)》请在冰豆网上搜索。
![Verilog HDL举例1.docx](https://file1.bdocx.com/fileroot1/2023-1/23/5aba2352-8ba5-4bf3-94a8-42b7701cc8c0/5aba2352-8ba5-4bf3-94a8-42b7701cc8c01.gif)
VerilogHDL举例1
组合逻辑设计
数据比较器
//---------------compare.v-----------------
modulecompare(equal,a,b);
inputa,b;
outputequal;
assignequal=(a==b)?
1:
0;//a等于b时,equal输出为1;a不等于b时,
//equal输出为0。
endmodule
测试模块源代码:
`timescale1ns/1ns//定义时间单位。
`include"./compare.v"//包含模块文件。
在有的仿真调试环境中并不需要此语句。
//而需要从调试环境的菜单中键入有关模块文件的路径和名称
modulecomparetest;
rega,b;
wireequal;
initial//initial常用于仿真时信号的给出。
begin
a=0;
b=0;
#100a=0;b=1;
#100a=1;b=1;
#100a=1;b=0;
#100$stop;//系统任务,暂停仿真以便观察仿真波形。
end
comparecompare1(.equal(equal),.a(a),.b(b));//调用模块。
endmodule
仿真波形(部分):
时序逻辑设计
2分频器
//half_clk.v:
modulehalf_clk(reset,clk_in,clk_out);
inputclk_in,reset;
outputclk_out;
regclk_out;
always@(posedgeclk_in)
begin
if(!
reset)clk_out=0;
elseclk_out=~clk_out;
end
endmodule
测试模块的源代码:
//-------------------clk_Top.v-----------------------------
`timescale1ns/100ps
`defineclk_cycle50
moduleclk_Top.v
regclk_in,reset;
wireclk_out;
always#`clk_cycleclk_in=~clk_in;
initial
begin
clk_in=0;
reset=1;
#100reset=0;
#100reset=1;
#10000$stop;
end
half_clkhalf_clk(.reset(reset),.clk_in(clk_in),.clk_out(clk_out));
endmodule
仿真波形:
利用条件语句实现较复杂的时序逻辑电路
分频器将20M的时钟分频为500K的时钟。
基本原理与1/2分频器是一样的,但是需要定义一个计数器,以便准确获得1/40分频
模块源代码:
//---------------fdivision.v-----------------------------
modulefdivision(RESET,F20M,F500K);
inputF20M,RESET;
outputF500K;
regF500K;
reg[7:
0]j;
always@(posedgeF20M)
if(!
RESET)//低电平复位。
begin
F500K<=0;
j<=0;
end
else
begin
if(j==19)//对计数器进行判断,以确定F500K信号是否反转。
begin
j<=0;
F500K<=~F500K;
end
else
j<=j+1;
end
endmodule
测试模块源代码:
//---------------fdivision_Top.v------------------------
`timescale1ns/100ps
`defineclk_cycle50
moduledivision_Top;
regF20M_clk,RESET;
wireF500K_clk;
always#`clk_cycleF20M_clk=~F20M_clk;
initial
begin
RESET=1;
F20M_clk=0;
#100RESET=0;
#100RESET=1;
#10000$stop;
end
fdivisionfdivision(.RESET(RESET),.F20M(F20M_clk),.F500K(F500K_clk));
endmodule
仿真波形:
设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别
通过分别采用阻塞赋值语句和非阻塞赋值语句的两个看上去非常相似的两个模块blocking.v和non_blocking.v来阐明两者之间的区别。
模块源代码:
//-------------blocking.v---------------
moduleblocking(clk,a,b,c);
output[3:
0]b,c;
input[3:
0]a;
inputclk;
reg[3:
0]b,c;
always@(posedgeclk)
begin
b=a;
c=b;
$display("Blocking:
a=%d,b=%d,c=%d.",a,b,c);
end
endmodule
//-------------non_blocking.v-------------------
modulenon_blocking(clk,a,b,c);
output[3:
0]b,c;
input[3:
0]a;
inputclk;
reg[3:
0]b,c;
always@(posedgeclk)
begin
b<=a;
c<=b;
$display("Non_Blocking:
a=%d,b=%d,c=%d.",a,b,c);
end
endmodule
测试模块源代码:
//-------------compareTop.v-----------------------------
`timescale1ns/100ps
`include"./blocking.v"
`include"./non_blocking.v"
modulecompareTop;
wire[3:
0]b1,c1,b2,c2;
reg[3:
0]a;
regclk;
initial
begin
clk=0;
forever#50clk=~clk;
end
initial
begin
a=4'h3;
$display("____________________________");
#100a=4'h7;
$display("____________________________");
#100a=4'hf;
$display("____________________________");
#100a=4'ha;
$display("____________________________");
#100a=4'h2;
$display("____________________________");
#100$display("____________________________");
$stop;
end
non_blockingnon_blocking(clk,a,b2,c2);
blockingblocking(clk,a,b1,c1);
endmodule
仿真波形(部分):
用case语句描述的4选1数据选择器
modulemux4_1(out,in0,in1,in2,in3,sel);
outputout;
inputin0,in1,in2,in3;
input[1:
0]sel;
regout;
always@(in0orin1orin2orin3orsel)
case(sel)
2'b00:
out=in0;
2'b01:
out=in1;
2'b10:
out=in2;
2'b11:
out=in3;
default:
out=2'bx;
endcase
endmodule
同步置数,同步清零的计数器
modulecount(out,data,load,reset,clk);
output[7:
0]out;
input[7:
0]data;
inputload,clk,reset;
reg[7:
0]out;
always@(posedgeclk)
begin
if(!
reset)out=8'h00;
elseif(load)out=data;
elseout=out+1;
end
endmodule
用always语句实现组合逻辑电路
简单的指令译码电路的设计示例。
通过对指令的判断,对输入数据执行相应的操作,包括加、减、与、或和求反。
//---------------alu.v--------------------------
`defineplus3'd0`defineminus3'd1`defineband3'd2
`definebor3'd3
`defineunegate3'd4
modulealu(out,opcode,a,b);
output[7:
0]out;
reg[7:
0]out;
input[2:
0]opcode;
input[7:
0]a,b;//操作数。
always@(opcodeoraorb)//电平敏感的always块
begin
case(opcode)
`plus:
out=a+b;//加操作。
`minus:
out=a-b;//减操作。
`band:
out=a&b;//求与。
`bor:
out=a|b;//求或。
`unegate:
out=~a;//求反。
default:
out=8'hx;//未收到指令时,输出任意态。
endcase
end
endmodule
如果不使用default或else对缺省项进行说明,则易生成意想不到的锁存器,这一点一定要加以注意。
指令译码器的测试模块源代码:
//-------------alu_Top.v-----------------
`timescale1ns/1ns
`include"./alu.v"
modulealutest;
wire[7:
0]out;
reg[7:
0]a,b;
reg[2:
0]opcode;
parametertimes=5;
initial
begin
a={$random}%256;//Givearadomnumberblongsto[0,255].
b={$random}%256;//Givearadomnumberblongsto[0,255].
opcode=3'h0;
repeat(times)
begin
#100a={$random}%256;//Givearadomnumber.
b={$random}%256;//Givearadomnumber.
opcode=opcode+1;
end
#100$stop;
end
alualu1(out,opcode,a,b);
endmodule
仿真波形(部分):
用begin-end串行块产生信号波形
`timescale10ns/1ns
modulewave1;
regwave;
parametercycle=10;
initial
begin
wave=0;
#(cycle/2)wave=1;
#(cycle/2)wave=0;
#(cycle/2)wave=1;
#(cycle/2)wave=0;
#(cycle/2)wave=1;
#(cycle/2)$finish;
end
endmodule
用fork-join并行块产生信号波形
`timescale10ns/1ns
modulewave2;
regwave;
parametercycle=5;
initial
fork
wave=0;
#(cycle)wave=1;
#(2*cycle)wave=0;
#(3*cycle)wave=1;
#(4*cycle)wave=0;
#(5*cycle)wave=1;
#(6*cycle)$finish;
join
endmodule
持续赋值方式定义的2选1多路选择器
moduleMUX21_1(out,a,b,sel);
inputa,b,sel;
outputout;
assignout=(sel==0)?
a:
b;
endmodule
2选1多路选择器(else部分写全)
moduleMUX21_2(out,a,b,sel);
inputa,b,sel;
outputout;
regout;
always@(aorborsel)
begin
if(sel==0)out=a;
elseout=b;
end
endmodule
隐含的锁存器
moduleburied_ff(c,b,a);
outputc;
inputb,a;
regc;
always@(aorb)
begin
if((b==1)&&(a==1))c=a&b;
end
endmodule
模为60的BCD码加法计数器
modulecount60(qout,cout,data,load,cin,reset,clk);
output[7:
0]qout;
outputcout;
input[7:
0]data;
inputload,cin,clk,reset;
reg[7:
0]qout;
always@(posedgeclk)
begin
if(reset)qout<=0;
elseif(load)qout<=data;
elseif(cin)
begin
if(qout[3:
0]==9)//低位是否为9
begin
qout[3:
0]<=0;//回0
if(qout[7:
4]==5)qout[7:
4]<=0;//判断高位是否为5
elseqout[7:
4]<=qout[7:
4]+1;
end
else
qout[3:
0]<=qout[3:
0]+1;
end
end
assigncout=((qout==8'h59)&cin)?
1:
0;
endmodule
BCD码—七段数码管显示译码器
moduledecode4_7(decodeout,indec);
output[6:
0]decodeout;
input[3:
0]indec;
reg[6:
0]decodeout;
always@(indec)
begin
case(indec)
4'd0:
decodeout=7'b1111110;
4'd1:
decodeout=7'b0110000;
4'd2:
decodeout=7'b1101101;
4'd3:
decodeout=7'b1111001;
4'd4:
decodeout=7'b0110011;
4'd5:
decodeout=7'b1011011;
4'd6:
decodeout=7'b1011111;
4'd7:
decodeout=7'b1110000;
4'd8:
decodeout=7'b1111111;
4'd9:
decodeout=7'b1111011;
default:
decodeout=7'bx;
endcase
end
endmodule
用casez描述的数据选择器
modulemux_casez(out,a,b,c,d,select);
outputout;
inputa,b,c,d;
input[3:
0]select;
regout;
always@(selectoraorborcord)
begin
casez(select)
4'b?
?
?
1:
out=a;
4'b?
?
10:
out=b;
4'b?
100:
out=c;
4'b1000:
out=d;
endcase
end
endmodule
用for语句描述的七人投票表决器
modulevoter7(pass,vote);
outputpass;
input[6:
0]vote;
reg[2:
0]sum;
integeri;
regpass;
always@(vote)
begin
sum=0;
for(i=0;i<=6;i=i+1)
if(vote[i])sum=sum+1;
if(sum[2])pass=1;//至少4人
elsepass=0;
end
endmodule
用for语句实现2个8位数相乘
modulemult_for(outcome,a,b);
parametersize=8;
input[size:
1]a,b;
output[2*size:
1]outcome;
reg[2*size:
1]outcome;
integeri;
always@(aorb)
begin
outcome=0;
for(i=1;i<=size;i=i+1)
if(b[i])outcome=outcome+(a<<(i-1));
end
endmodule
用repeat实现8位二进制数的乘法
modulemult_repeat(outcome,a,b);
parametersize=8;
input[size:
1]a,b;
output[2*size:
1]outcome;
reg[2*size:
1]temp_a,outcome;
reg[size:
1]temp_b;
always@(aorb)
begin
outcome=0;
temp_a=a;
temp_b=b;
repeat(size)
begin
if(temp_b[1])//最低位为1,执行加法
outcome=outcome+temp_a;
temp_a=temp_a<<1;//a左移1位
temp_b=temp_b>>1;//b右移1位
end
end
endmodule
同一循环的不同实现方式
moduleloop1;
integeri;
initial
for(i=0;i<4;i=i+1)
begin
$display("i=%h",i);
end
endmodule
moduleloop2;
integeri;
initialbegin
i=0;
while(i<4)
begin
$display("i=%h",i);
i=i+1;
end
end
endmodule
moduleloop3;
integeri;
initialbegin
i=0;
repeat(4)
begin
$display("i=%h",i);
i=i+1;
end
end
endmodule
输出i=?
使用了`include语句的16位加法器(相对路径、绝对路径)
`include"adder.v"
moduleadder16(cout,sum,a,b,cin);
outputcout;
parametermy_size=16;
output[my_size-1:
0]sum;
input[my_size-1:
0]a,b;
inputcin;
addermy_adder(cout,sum,a,b,cin);
endmodule
//adder子模块
moduleadder(cout,sum,a,b,cin);
parametersize=16;
outputcout;
output[size-1:
0]sum;
inputcin;
input[size-1:
0]a,b;
assign{cout,sum}=a+b+cin;
endmodule
条件编译举例
modulecompile(out,A,B);
outputout;
inputA,B;
`ifdefadd
assignout=A+B;
`else
assignout=A-B;
`endif
endmodule