Verilog入门设计(三)——组合电路和逻辑电路的仿真

一、测试平台(Test Bench)

  测试平台的作用是给我们的设计进行验证,通过给被测试模块施加激励信号,观察其输出,然后判断其逻辑功能与时序关系正确与否来判断这个设计是否符合需求。
在这里插入图片描述
  从图中可以看出,测试模块向待测木块施加激励信号,激励信号必须定义为reg类型,以保持其信号值。待测模块在激励作用下产生输出,输出信号必须定义为wire型。测试模块将输出信息按规定的格式以文本或图形输出,供用户检测。

1、测试程序一般结构

module 仿真模块名;//无端口列表

数据类型说明  //其中激励信号定义为reg类型,输出信号定义为wire类型
parameter、integer等定义
待测模块调用

激励向量定义(always、initial结构等,if-else/for/case/while/repeat/disable等控制语句)

显示格式定义($monitor、$display、$time等)
endmodule
  • 测试模块只有模块名,没有端口列表;输入信号(激励信号)必须定义为reg型,以保持其信号值;输出信号(显示信号)必须定义为wire型;
  • 在测试模块中调用待测试模块,在调用时应注意端口排列的顺序与模块定义时一致;
  • 一般用always、initial等过程快来定义激励信号,使用系统任务和系统函数来定义输出格式;在激励型号的定义中,可使用如下一些控制语句:if-else, for,forever,case,while,repeat,wait,disable,force,release,begin-end,fork-join等,这些控制语句一般只用在always、initial、function、task等过程快中。

2、激励信号产生方式举例

2.1 initial语句产生激励信号

`timescale 1ns/100ps
module test1;	//定义模块名
reg A,B,C;		//定义输入输出端口,本例只有输入端口,声明为reg类型
initial
begin
A=0;B=1;C=0;
#10 C=1;		//#n表示延迟10个时间单位,时间单位由timescale确定,本例中一个时间单位为1ns,精度为100ps。#10表示延迟10ns
#10 A=1;B=0;
#10 A=0;
#10 C=0;
end
initial $monitor($time,,,"A=%d,B=%d,C=%d",A,B,C);	//显示
endmodule

2.2 always语句产生激励信号

例1:

`timescale 1ns/1ns
module always_clk;
reg clk;
parameter CYCLE=100;
always #(CYCLE/2) clk=~clk;
initial clk=1;
initial $monitor($time,,,"clk=%d",clk);
endmodule

例2:

`timescale 1ns/1ns
module test2;
reg clk1,clk2;
parameter CYCLE=100;	//定义参数
always
 begin
  	       {clk1,clk2}=2'b10;
#(CYCLE/4) {clk1,clk2}=2'b11;
#(CYCLE/4) {clk1,clk2}=2'b10;
#(CYCLE/4) {clk1,clk2}=2'b01;
#(CYCLE/4) {clk1,clk2}=2'b10;

 end
initial $monitor($time,,,"clk1=%b,clk2=%b",clk1,clk2);
endmodule

二、组合电路的仿真

1、8位乘法器的仿真

(1)待测试模块

/*8位乘法器代码*/
module mult8(out,a,b);	//8位乘法器源码
parameter size=8;
input[size-1:0] a,b;	//定义两个操作数
output[2*size-1:0] out; //结果
assign out=a*b;		//乘法计算
endmodule

(2)测试模块

/*8位乘法器的验证程序*/
`timescale 10ns/1ns
module mult_tb;		//定义模块名
reg[7:0] a,b;		//定义输入信号
wire[15:0] out;		//定义输出信号
integer i,j;
mult8 m1(out,a,b);	//调用测试模块
initial			//激励波形设定
begin
 a=0;b=0;
 for(i=1;i<255;i=i+1)
   #10 a=i;
end

initial
begin
 for(j=1;j<255;j=j+1)
   #10 b=j;
end

initial 
begin
 $monitor($time,,,"%d*%d=%d",a,b,out);//定义显示格式
 #2560 $finish;		//延迟2560*10ns后结束仿真
end
endmodule

(3)仿真结果
在这里插入图片描述

2、8位加法器的仿真

(1)待测试模块


module adder8(sum,cout,a,b,cin);
parameter size=8;
input[size-1:0] a,b;
input cin;
output[size-1:0] sum;
output cout;
assign {cout,sum}=a+b+cin;
endmodule

(2)测试模块

`timescale 1ns/100ps
module adder8_tb;
reg[7:0] a,b;
reg cin;
wire[7:0] sum;
wire cout;

integer i,j;

adder8 a0(sum,cout,a,b,cin);

initial		//输入激励信号a的波形
begin
 a=0;b=0;cin=0;
 for(i=0;i<255;i=i+1)
 #10 a=i;
end

initial		//输入激励信号b的波形
begin
 for(j=0;j<255;j=j+1)
 #10 b=j;
end

initial	
begin	//输入激励信号cin的波形
 forever #200 cin=~cin;
end

initial
begin
$monitor($time,,,"%d+%d+%b={%b+%d}",a,b,cin,cout,sum);
 #2500 $finish;
end
endmodule

(3)仿真结果在这里插入图片描述

3、2选1数据选择器的仿真

(1)待测试模块

module mux2_1(out,in1,in2,sel);
input in1,in2,sel;
output out;
assign out=sel?in1:in2;
endmodule

(2)测试模块

`timescale 1ns/100ps
module mux2_1_tb;
reg in1,in2,sel;
wire out;

mux2_1 m1(out,in1,in2,sel); //调用待测试模块

initial 	//激励波形设置
begin
 in1=0;in2=0;sel=0;
 forever #10 in1=~in1;
end

initial 	
begin
 forever #20 in2=~in2;
end

initial 	
begin
 forever #50 sel=~sel;
end

initial
begin
$monitor($time,,,"in1=%b in2=%b sel=%b out=%b",in1,in2,sel,out);
#5000 $finish;
end
endmodule

(3)仿真结果
在这里插入图片描述

三、时序电路的仿真

8位计数器的仿真

(1)待测试模块

//带同步复位的8位计数器
module count8(out,reset,clk);
input reset,clk;
output reg[7:0] out;
always@(posedge clk)
begin
 if(!reset)
    out<=8'b00000000;
 else
    out<=out+1;
end
endmodule

(2)测试模块

`timescale 1ns/100ps
module count8_tb;
reg reset,clk;
wire[7:0] out;

count8 c1(out,reset,clk); //调用待测模块

initial
begin
 clk=0;reset=1;
 forever #10 clk=~clk;
end

initial
begin
 #100 reset=0;
 #110 reset=1;
end

initial 
$monitor($time,,,"clk=%b reset=%b out=%d",clk,reset,out);
endmodule

(3)仿真结果
在这里插入图片描述