北京航空航天大学
电子电路设计数字部分实验报告
实验一 简单组合逻辑设计... 2
实验二 简单分频时序逻辑电路的设计... 3
一.实验目的:1.掌握最基本组合逻辑电路的实现方法。... 3
2.学习时序电路测试模块的编写。... 3
3.学习综合和不同层次的仿真。... 3
实验三 利用条件语句实现计数分频时序电路... 5
实验四 阻塞赋值与非阻塞赋值的区别... 7
实验五 用always块实现较复杂的组合逻辑:... 10
实验六 在 Verilog HDL中使用函数... 12
实验七 在Verilog HDL中使用任务(task) 14
实验八 利用有限状态机进行时序逻辑的设计... 17
实验九 楼梯灯... 19
实验思考与总结... 29
实验一 简单组合逻辑设计
一.实验目的:
1.掌握基本组合逻辑电路的实现方法。
2.初步了解两种基本组合逻辑电路的生成方法。
3.学习测试模块的编写。
4.通过综合和布局布线了解不同层次仿真的物理意义。
二.实验设备:
安装Modelsim-6.5c的PC机。
三.实验内容:
描述一个可综合的数据比较器,比较数据a 、b的大小,若相同,则给出结果1,否则给出结果0
四.综合仿真结果
实验二 简单分频时序逻辑电路的设计
一.实验目的:1.掌握最基本组合逻辑电路的实现方法。
2.学习时序电路测试模块的编写。
3.学习综合和不同层次的仿真。
二.实验设备:
安装Modelsim-6.5c的PC机。
三.实验内容:
用always块和@(posedge clk)或@(negedge clk)的结构表述一个1/2分频器的可综合模型,观察时序仿真结果
四.实验代码
module half_clk(reset,clk_in,clk_out);
input clk_in,reset;
output clk_out;
reg clk_out;
always@(posedge clk_in)
begin
if(!reset)
clk_out=0;
else
clk_out=~clk_out;
end
endmodule
`timescale 1ns/100ps
`define clk_cycle 50
module top;
reg clk,reset;
wire clk_out;
always #`clk_cycle clk=~clk;
initial
begin
clk=0;
reset=-1;
#10 reset=0;
#110 reset=1;
#100000 $stop;
end
half_clk m0(.reset(reset),.clk_in(clk),.clk_out(clk_out));
endmodule
五.综合仿真结果
实验三 利用条件语句实现计数分频时序电路
一.实验目的:
1.掌握条件语句在简单时序模块设计中的使用。
2.学习在Verilog模块中应用计数器。
3.学习测试模块的编写、综合和不同层次的仿真。
二.实验设备:
安装Modelsim-6.5c的PC机。
三.实验内容:
仿真一个可综合风格的分频器,将10MB的时钟分频为500KB的时钟,定义一个计数器,原理同1/2分频器一样,只不过分频变为1/20。
四.实验代码
module fdivision(RESET,F10M,F500K);
input RESET,F10M;
output F500K;
reg F500K;
reg[7:0]j;
always @(posedge F10M)
if(!RESET)
begin
F500K <= 0;
j<=0;
end
else
begin
if(j==9)
begin
j<=0;
F500K =~ F500K;
end
else
j<=j+1;
end
endmodule
`timescale 1ns/1ps
`define clk_cycle 50
module division_Top;
reg F10M,RESET;
wire F500K_clk;
always #`clk_cycle F10M=~F10M;
initial
begin
RESET=1;
F10M=0;
#100 RESET=0;
#100 RESET=1;
#10000 $stop;
end
fdivision fdivision(.RESET(RESET),.F10M(F10M),.F500K(F500K_clk));
endmodule
五.综合仿真结果
实验四 阻塞赋值与非阻塞赋值的区别
一.实验目的:
1.通过实验,掌握阻塞赋值与非阻塞赋值的概念和区别。
2.了解非阻塞和阻塞赋值的不同使用场合。
3.学习测试模块的编写、综合和不同层次的仿真。
二.实验设备:
安装Modelsim-6.5c的PC机。
三.实验内容:
两个模块,一个阻塞赋值,一个非阻塞赋值,观察两者之间的区别
四.实验代码
module blocking(clk,a,b,c);
output [3:0]b,c;
input [3:0]a;
input clk;
reg [3:0]b,c;
always @(posedge clk)
begin
b=a;
c=b;
$display("Blocking:a=%d,b=%d,c=%d",a,b,c);
end
endmodule
//non_blocking.v
module non_blocking(clk,a,b,c);
output [3:0]b,c;
input [3:0]a;
input clk;
reg [3:0]b,c;
always @(posedge clk)
begin
b<=a;
c<=b;
$display("Non_Blocking:a=%d,b=%d,c=%d",a,b,c);
end
endmodule
//comepareTop.v
`timescale 1ns/100ps
module conpareTop;
wire[3:0]b1,c1,b2,c2;
reg[3:0]a;
reg clk;
initial
begin
clk=0;
forever #50 clk=~clk;
end
initial
begin
a=4'h3;
$display("___________");
#100 a=4'h7;
$display("___________");
#100 a=4'hf;
$display("___________");
#100 a=4'ha;
$display("___________");
#100 a=4'h2;
$display("___________");
#100 $display("___________");
$stop;
end
non_blocking non_blocking(clk,a,b2,c2);
blocking blocking(clk,a,b1,c1);
endmodule
五.综合仿真结果
实验五 用always块实现较复杂的组合逻辑:
一.实验目的:
1.掌握用always实现较大组合逻辑电路的方法。
2.进一步了解assign与always两种组合电路实现方法的区别和注意点。
3.学习测试模块中随机数的产生和应用。
4.学习综合不同层次的仿真,并比较结果
二.实验设备:
安装Modelsim-6.5c的PC机。
三.实验内容:
设计一个简单的指令译码电路,该电路通过对指令的判断,对输入数据执行相应的操作,包括加、减、与、或和求反,并且无论是指令作用的数据还是指令本身发生变化,都有要作出及时的反应。
四.实验代码
`define plus 3'd0
`define minus 3'd1
`define band 3'd2
`define bor 3'd3
`define unegate 3'd4
module alu(out,opcode,a,b);
output [7:0]out;
reg [7:0]out;
input [2:0]opcode;
input [7:0]a,b;
always @(opcode or a or b)
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
`timescale 1ns/1ns
module alutest;
wire [7:0]out;
reg [7:0]a,b;
reg [2:0]opcode;
parameter times=5;
initial
begin
a={$random}%256;
b={$random}%256;
opcode=3'h0;
repeat(times)
begin
#100 a={$random}%256;
b={$random}%256;
opcode=opcode+1;
end
#100 $stop;
end
alu alu1(out,opcode,a,b);
endmodule
五.综合仿真结果
实验六 在 Verilog HDL中使用函数
一.实验目的:
1.了解函数的定义和在模块设计中的使用。
2.了解函数的可综合性问题。
3.了解许多综合器不能综合复杂的算术运算。
二.实验设备:
安装Modelsim-6.5c的PC机。
三.实验内容:
做一个函数调用的示例,采用同步时钟触发运算的执行,每个clk时钟周期执行一次运算,在测试模块中,调用系统任务$display及在时钟的下降沿显示每次运算的结果。
四.实验代码
module tryfunct(clk,n,result,reset);
output [31:0]result;
input [3:0]n;
input reset,clk;
reg [31:0]result;
always @(posedge clk)
begin
if(!reset)
result<=0;
else
begin
result<=n*factorial(n)/((n*2)+1);
end
end
function [31:0]factorial;
input [3:0]operand;
reg [3:0]index;
begin
factorial=operand? 1:0;
for(index=2;index<=operand;index=index+1)
factorial=index*factorial;
end
endfunction
endmodule
//测试模块代码
`timescale 1ns/100ps
`define clk_cycle 50
module tryfunctTop;
reg [3:0]n,i;
reg reset,clk;
wire [31:0]result;
initial
begin
clk=0;
n=0;
reset=1;
#100 reset=0;
#100 reset=1;
for(i=0;i<=15;i=i+1)
begin
#200 n=i;
end
#100 $stop;
end
always #`clk_cycle clk=~clk;
tryfunct m(.clk(clk),.n(n),.result(result),.reset(reset));
endmodule
五.综合仿真结果
练习题仿真结果
实验七 在Verilog HDL中使用任务(task)
一.实验目的:
1.掌握任务在Verilog模块设计中的应用。
2.学会在电平敏感列表的always中使用拼接操作、任务和阻塞赋值等语句,并生成复杂组合逻辑的高级方法。
二.实验设备:
安装Modelsim-6.2b的PC机。
三.实验内容:
利用电平敏感的always块和一个比较两变量大小排序的任务,设计出4个并行输入数的高速排序组合逻辑。
四.实验代码
module sort4(ra,rb,rc,rd,a,b,c,d);
output [3:0]ra,rb,rc,rd;
input [3:0]a,b,c,d;
reg [3:0]ra,rb,rc,rd;
reg [3:0]va,vb,vc,vd;
always @(a or b or c or d)
begin
{va,vb,vc,vd}={a,b,c,d};
sort2(va,vc);
sort2(vb,vd);
sort2(va,vb);
sort2(vc,vd);
sort2(vb,vc);
{ra,rb,rc,rd}={va,vb,vc,vd};
end
task sort2;
inout [3:0]x,y;
reg [3:0]tmp;
if(x>y)
begin
tmp=x;
x=y;
y=tmp;
end
endtask
endmodule
`timescale 1ns/100ps
module task_Top;
reg [3:0]a,b,c,d;
wire [3:0] ra,rb,rc,rd;
initial
begin
a=0;
b=0;
c=0;
d=0;
repeat(50)
begin
#100 a={$random}%15;
b={$random}%15;
c={$random}%15;
d={$random}%15;
end
#100 $stop;
end
sort4 sort4(.a(a),.b(b),.c(c),.d(d),.ra(ra),.rb(rb),.rc(rc),.rd(rd));
endmodule
五.综合仿真结果
练习题仿真结果
实验八 利用有限状态机进行时序逻辑的设计
一.实验目的:
1.掌握利用有限状态机实现一般时序逻辑分析的方法。
2.掌握用Verilog编写可综合的有限状态机的标准模板。
3.掌握用Verilog编写状态机模块的测试文件的一般方法。
二.实验设备:
安装Modelsim-6.2b的PC机。
三.实验内容:
设计一个简单的状态机,功能是检测一个5位的二进制序列“10010”。
四.实验代码
module seqdet(x,z,clk,rst,state);
input x,clk,rst;
output z;
output [2:0]state;
reg [2:0]state;
wire z;
parameter IDLE='d0,A='d1,B='d2,C='d3,D='d4,E='d5,F='d6,G='d7;
assign z=(state==E&&x==0)?1:0;
always @(posedge clk)
if(!rst)
begin
state<=IDLE;
end
else
casex(state)
IDLE:if(x==1)
begin
state<=A;
end
A:if(x==0)
begin
state<=B;
end
B:if(x==0)
begin
state<=C;
end
else
begin
state<=F;
end
C:if(x==1)
begin
state<=D;
end
else
begin
state<=G;
end
D:if(x==0)
begin
state<=E;
end
else
begin
state<=A;
end
E:if(x==0)
begin
state<=C;
end
else
begin
state<=A;
end
F:if(x==1)
begin
state<=A;
end
else
begin
state<=B;
end
G:if(x==1)
begin
state<=F;
end
default:state<=IDLE;
endcase
endmodule
`timescale 1ns/1ns
module seqdet_Top;
reg clk,rst;
reg [23:0]data;
wire [2:0]state;
wire z,x;
assign x=data[23];
always #10 clk=~clk;
always @(posedge clk)
data={data[22:0],data[30]};
initial
begin
clk=0;
rst=1;
#2 rst=0;
#30 rst=1;
data='b1100_1001_0000_1001_0100;
#500 $stop;
end
seqdet m(x,z,clk,rst,state);
endmodule
五.综合仿真结果
实验九 楼梯灯
一.实验目的:
掌握用Verilog编写简单程序
二.实验设备:
安装Modelsim-6.2b的PC机。
三.实验内容:
Ø 楼下到楼上依次有3个感应灯:灯1、灯2、灯3。当行人上下楼梯时,各个灯感应到后自动点亮,若在8s内感应信号消失,则点亮8s,若感应信号存在时间超过8s,则感应信号消失4s后灯自动关闭。
Ø 任务1:做出如上逻辑电路设计并仿真;
Ø 任务2:考虑去抖情况,对于感应信号到达存在毛刺(小于0.5s),设计合适逻辑并剔出。
任务3:若为节约能源,下一个灯点亮的同时将自动关闭上一个灯,做出如上逻辑设计并仿真(仅考虑一个人的情况)
四.实验代码
module stairled(light,switch,clk10,rst);
input clk10,rst;
input[2:0]switch;
output[2:0]light;
reg[2:0]state1,state2,state3;
reg[7:0]count1,count2,count3;
reg[2:0]light;
reg[2:0]counter1,counter2,counter3;
parameter
IDLE1=3'b000,IDLE2=3'b000,IDLE3=3'b000,
state1_main=3'b001,state2_main=3'b001,state3_main=3'b001,
state1_pos=3'b010,state2_pos=3'b010,state3_pos=3'b010,
state1_neg=3'b011,state2_neg=3'b011,state3_neg=3'b011,
state1_spe_01=3'b100,state2_spe_01=3'b100,state3_spe_01=3'b100,
state1_spe_02=3'b101,state2_spe_02=3'b101,state3_spe_02=3'b101;
/*
The first always block!!!To deal with light1&switch1!!!
*/
always@(posedge clk10)
if(!rst)
begin
state1<=IDLE1;
count1<=8'b0;
counter1<=3'b0;
end
else
if(switch[0]==1'b1&&counter1<5)counter1<=counter1+1;
else
case(state1)
IDLE1:
if(switch[0]=='b1)
begin
state1<=state1_pos;
count1<=79;
end
else
begin
state1<=IDLE1;
light[0]<=0;
end
state1_main:
if(count1>0)
begin
count1<=count1-1;
end
else
if(switch[0]==0)
begin
state1<=state1_neg;
end
else
if(switch[0]==1)
begin
state1<=state1_spe_01;
end
state1_spe_01:
if(switch[0]==0)
begin
state1<=state1_spe_02;
count1<=39;
end
else state1<=state1_spe_01;
state1_spe_02:
if(count1>0)
begin
count1<=count1-1;
end
else
state1<=state1_neg;
state1_neg:
begin
light[0]<='b0;
state1<=IDLE1;
counter1<=3'b0;
end
state1_pos:
begin
light[0]<=1;
state1<=state1_main;
end
default:state1<=IDLE1;
endcase
/*
The second always block!!!To deal with light2&switch2!!!
*/
always@(posedge clk10)
if(!rst)
begin
state2<=IDLE2;
count2<=8'b0;
counter2<=3'b0;
end
else
if(switch[1]==1'b1&&counter2<5)counter2<=counter2+1;
else
case(state2)
IDLE2:
if(switch[1]=='b1)
begin
state2<=state2_pos;
count2<=79;
end
else
begin
state2<=IDLE2;
light[1]<='b0;
end
state2_main:
if(count2>0)
begin
count2<=count2-1;
end
else
if(switch[1]==0)
begin
state2<=state2_neg;
end
else
if(switch[1]==1)
begin
state2<=state2_spe_01;
end
state2_spe_01:
if(switch[1]==0)
begin
state2<=state2_spe_02;
count2<=39;
end
else state2<=state2_spe_01;
state2_spe_02:
if(count2>0)
begin
count2<=count2-1;
end
else
state2<=state2_neg;
state2_neg:
begin
light[1]<='b0;
state2<=IDLE2;
counter2<=3'b0;
end
state2_pos:
begin
light[1]<='b1;
state2<=state2_main;
end
default:state2=IDLE2;
endcase
/*
The third always block!!!To deal with light3&switch3!!!
*/
always@(posedge clk10)
if(!rst)
begin
state3<=IDLE3;
count3<=8'b0;
counter3<=3'b0;
end
else
if(switch[2]==1'b1&&counter3<5)counter3<=counter3+1;
else
case(state3)
IDLE3:
if(switch[2]=='b1)
begin
state3<=state3_pos;
count3<=79;
end
else
begin
state3<=IDLE3;
light[2]=0;
end
state3_main:
if(count3>0)
begin
count3<=count3-1;
end
else
if(switch[2]==0)
begin
state2<=state3_neg;
end
else
if(switch[2]==1)
begin
state3<=state3_spe_01;
end
state3_spe_01:
if(switch[2]==0)
begin
state3<=state3_spe_02;
count3<=39;
end
else state3<=state3_spe_01;
state3_spe_02:
if(count3>0)
begin
count3<=count3-1;
end
else
state3<=state3_neg;
state3_neg:
begin
light[1]<='b0;
state3<=IDLE3;
counter3<=3'b0;
end
state3_pos:
begin
light[2]<='b1;
state3<=state3_main;
end
default:state3<=IDLE3;
endcase
endmodule
五.综合仿真结果
实验思考与总结
Verilog是硬件描述语言的一种,用于数字电子系统设计,它允许我们进行各种级别的逻辑设计,进行数字逻辑系统的仿真验证、时序分析、逻辑综合,是目前应用最广泛的一种硬件描述语言。Verilog有许多优点,首先,由于verilog的标准化,可以很容易的把完成的设计移植到不同厂家的不同芯片上去,并在不同规模的应用时可以比较容易的做修改。这不仅是因为用verilog所完成的设计,其信号位数是很容易改变的,可以很容易的对它进行修改,来适应不同规模的应用;在仿真验证时,仿真测试矢量还可以用同一种描述语言来完成,而且还因为采用Verilog HDL综合器生成的数字逻辑是一种标准的电子设计互换格式文件,独立于所采用的实现工艺。有关工艺参数的描述可以通过Verilog HDL提供的属性包括进去,然后利用不同厂家的布局布线工艺,在不同工艺的芯片上实现。采用Verilog输入法最大的优点是其与工艺无关性。这使得我们在功能设计、逻辑验证阶段,可以不必过多考虑门级及工艺实现的具体细节,只需要利用系统设计时对芯片的要求,施加不同的约束条件,即可设计出实际电路。实际上这是利用了计算机的巨大能力在EDA工具的帮助下,把逻辑验证与具体工艺库匹配、布线及延时计算分成不同的阶段来实现,从而减轻了我们的繁琐劳动。
通过Verilog实验,可以让我们理解示范实验中的每一条语句,然后进行功能仿真可以加深我们对Verilog的理解,让我们对老师课堂上所讲的知识点有一个更加深入的了解,解决了很多我们在课堂学习中所不能解决的问题,比如阻塞赋值和非阻塞赋值的实验,就可以让我们更加清楚明白的了解阻塞赋值和非阻塞赋值的区别,避免了课堂讲解的难于理解,同时也加深了我们对这个知识点的记忆。通过做这些实验,可以让我们掌握基本组合逻辑电路的实现方法和生成方法,掌握测试模块的编写方法,掌握各种不同的语句在时序模块设计中的使用,了解Verilog语言中不同实现方法的区别,比如阻塞赋值和非阻塞赋值的区别,比如assign和always两种组合电路实现方法的区别,让我们可以学习测试模块的编写、综合和不同层次的仿真,可以通过综合和布局布线了解不同层次仿真的物理意义,让我们更加完整的了解Verilog,让我们更加深刻的了解我们所学到的知识,并学以所用,能够设计比较简单的程序以实现预期的功能。