数字式秒表verilog语言实现.docx
《数字式秒表verilog语言实现.docx》由会员分享,可在线阅读,更多相关《数字式秒表verilog语言实现.docx(23页珍藏版)》请在冰豆网上搜索。
数字式秒表verilog语言实现
一、实验目的
(1)熟练把握分频器、各类进制的同步计数器的设计。
(2)熟练把握同步计数器的级联方式。
(3)把握数码管的动态显示驱动方式。
(4)把握计数器的功能和应用。
(5)明白得开关防哆嗦的必要性。
(6)把握简单操纵器的设计方式。
二、实验内容和原理
一、实验设计要求:
(1)计时范围0’0’.0’’~59’59’.9’’,分辨率为,用数码管显示计时值。
(2)秒表有一个按键开关:
当电路处于“初始”状态时,第一次按键,计时开始(“计时”状态);再次按键。
计时停止(“停止”状态);第三次按键,计时器复位为0’0’.0’’,且电路恢复到“初始”状态。
二、依照设计要求,可画出秒表电路的原理框图,如图1-2所示,秒表电路由时钟治理模块(DCM)、分频器模块、按键处置模块、操纵器、计时模块和显示模块组成。
显示模块
DCM
clksys_clk
分频器模块
en
计时模块
pulse10Hz
pulse400Hz
clearcountstop
按键处理模块
控制器
ButtonInButtonOut
图1-2秒表电路的原理框图
(1)DCM模块
由于数字钟为低速电路,而XUPVirtex-IIPro开发系统只提供100MHz主时钟,因此需插入DCM分频模块以降低系统的工作时钟,从而提高系统的靠得住性。
DCM可采纳16分频,输出的sys_clk信号作为系统的主时钟。
ISE生成DCM内核的VerilogHDL代码:
VgaDCMDCMInst(
.CLKIN_IN(clk),
.CLKDV_OUT(sys_clk),
.CLKIN_IBUFG_OUT(),
.CLK0_OUT(),
.LOCKED_OUT());
(2)分频器模块
产生用于计时的1/10秒脉冲信号pulse10,频率为10Hz;
产生用于显示模块的扫描脉冲信号pulse400,频率为400Hz。
1/10秒脉冲信号pulse10和扫描脉冲信号pulse400的脉冲宽度为一个系统主时钟信号sys_clk的周期。
分频器模块原理框图如图1-3所示,先设计一个15625分频器,产生400Hz的扫描信号pulse400,再由pulse400操纵40分频器产生1/10秒脉冲信号pulse10。
分频器设计:
分频器事实上确实是计数器:
分频比n确实是计数器的模。
pulse400
enout
40进制
计数器
enout
15625进制
计数器
装订线
“1”pulse10
sys_clk
图1-3分频器原理框图
分频器模块的VerilogHDL代码:
modulediv(sys_clk,sec,scan);out(scan),.cin(1'b1),.clk(sys_clk));out(sec),.cin(scan),.clk(sys_clk));
endmodule
modulediv_n1(cout,cin,clk);
(asynch_in),.reset(reset),.clk(clk),.q(a));
d_ffu2(.d(a),.reset(reset),.clk(clk),.q(synch_out));
endmodule
moduled_ff(d,reset,clk,q);
10ms定时器
图1-8所示为防颤动电路的原理框图。
控制器
en
sys_clk
reset
timer_clr
timer_done
Vo
分频器
(÷)
pulse400
Vi
clk
cin
timer_done
en
定时器
qout
timer_clr
图1-9定时器框图
图2-1控制器的算法流程图
图1-7防颤动电路的工作流程图
图2-2防颤动电路控制器的ASM图
ys_clk(clk),.sec(),.scan(pulse400));
time_nu2(.cin(pulse400),.clk(clk),.time_clr(b),.time_done(c));
controlu3(.clk(clk),.vi(vi),.time_done(c),.reset(reset),.time_clr(b),.vo(vo));
endmodule
moduletime_n(cin,clk,time_clr,time_done);out(scan),.cin(1'b1),.clk(sys_clk));
div_n2u2(.cout(sec),.cin(scan),.clk(sys_clk));
endmodule
modulecontrol(clk,vi,time_done,reset,time_clr,vo);
clk
in
out
&
D
Q
图2-3脉宽变换电路
(in),.reset(reset),.clk(clk),.q(b));
enco
六十进制
BCD码
计数器
enco
六十进制
BCD码
计数器
enco
十进制
BCD码
计数器
qss
qm
qs
图2-4计时模块的原理框图
out(qss),.cout(second),.cin(sec&&count&~stop),
.reset(clear),.clk(sys_clk));out(qs),.cout(min),.cin(second),.reset(clear),.clk(sys_clk));
bcd1_60u3(.qout(qm),.cout(),.cin(min),.reset(clear),.clk(sys_clk));
endmodule
modulebcd1_60(qout,cout,cin,reset,clk);
控制器模块的VerilogHDL代码:
图2-6控制器的ASM图
Reset
clear=1,count=0,stop=0
Start
N
Timing
End
Y
N
N
Y
Y
ButtonOut?
ButtonOut?
clear=0,count=0,stop=1
ButtonOut?
clear=0,count=1,stop=0
modulecontrol_16(sys_clk,buttonout,clear,count,stop,start);//控制器
inputsys_clk,buttonout,start;
outputclear,count,stop;
regclear,count,stop;
reg[1:
0]state;
parameterreset=2'b00,timing=2'b01,End=2'b11;//格雷码编码;
always@(posedgesys_clk)
beginif(start)state<=reset;//进入状态reset;
else
case(state)//状态转换;
reset:
beginif(buttonout)state<=timing;
elsestate<=reset;end
timing:
beginif(buttonout)state<=End;
elsestate<=timing;end
default:
beginif(buttonout)state<=reset;
elsestate<=End;end
endcase
end
always@(*)
begincase(state)
reset:
beginclear=1'b1;count=1'b0;stop=1'b0;end
timing:
beginclear=1'b0;count=1'b1;stop=1'b0;end
default:
beginclear=1'b0;count=1'b0;stop=1'b1;end
endcase
end
endmodule
4mux
3
2
1
0
sel
qm[7:
4]
显示译码器
a~g
data
qm[3:
0]
qs[7:
4]
qs[3:
0]
qss[3:
0]
显示模块的VerilogHDL代码:
moduledisplay(scan,sys_clk,qss,qs,qm,position,a,b,c,d,e,f,g,dp);(q),.reset(1'b0),.clk(sys_clk),.cin(scan));(q),.position(position));
mux_5u3(.data(data),.sel(q),.qm(qm),.qs(qs),.qss(qss));
decode4_7u4(.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.data(data));
assigndp=~position[1];//第二位显示小数点;
endmodule
图2-7动态显示电路的原理框图
position[4:
0]
q
sys_clk
pulse400Hz
en
五进制
计数器
二进制译码器
LKIN_IN(clk),
.CLKDV_OUT(sys_clk),
.CLKIN_IBUFG_OUT(),
.CLK0_OUT(),
.LOCKED_OUT());
divu1(.sys_clk(sys_clk),.sec(pulse10),.scan(pulse400));p(buttonin),.clk(sys_clk),.out(buttonout));ys_clk(sys_clk),.buttonout(buttonout),lear(clear),.count(count),.stop(stop),.start(1'b0));
counteru4(.clear(clear),.count(count),.stop(stop),.sys_clk(sys_clk),ec(pulse10),.qss(qss),.qs(qs),.qm(qm));
displayu5(.scan(pulse400),.sys_clk(sys_clk),.qss(qss),.qs(qs),.qm(qm),osition(position),.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.dp(dp));
endmodule
三、要紧仪器设备
(1)装有ISE、ModelSimSE和ChipScopePro软件的运算机。
(2)XUPVirtex-IIPro开发系统一套。
(3)DigitIO扩展板一块。
四、操作方式和实验步骤
(1)编写按键处置模块、分频器模块、操纵器模块、计时模块和显示模块的VerilogHDL代码及其测试
(2)代码,并用ModelSim仿真。
(3)生成系统所需的DCM内核。
(4)编写秒表系统的top文件,成立秒表系统的ISE工程文件。
(5)对工程进行综合、约束、实现并下载至实验开发板中。
FPGA引脚约束内容如表1-1所示。
(6)接通扩展版电源,进行秒表的功能测试,验证设计是不是符合要求。
引脚名称
I/O
引脚编号
说明
clk
Input
AJ15
系统主100MHz时钟
ButtonIn
Input
AG5
Enter按键
a
Output
P7
七段码
b
Output
P3
c
Output
P2
d
Output
R7
e
Output
P4
f
Output
T2
g
Output
R5
position[0]
Output
N6
5个数码管的点亮控制端
position[1]
Output
L5
position[2]
Output
M2
position[3]
Output
P9
position[4]
Output
M4
dp
Output
R3
小数点
表2-8FPGA引脚约束内容
五、实验数据记录和分析
(1)分频器测试代码:
`timescale1ns/100ps
modulediv_tb;
regsys_clk;
wiresec,scan;
divdut(.sys_clk(sys_clk),.sec(sec),.scan(scan));
initialbegin
sys_clk=0;
#(1*00)
$stop;
end
always#80sys_clk=~sys_clk;
endmodule
图2-9分频器测试仿真波形
(1)
图3-0分频器测试仿真波形
(2)
图2-9、3-0、3-1都是分频器测试仿真波形,
在波形
(2)中可以看出信号scan的周期为2×ps,即,转换为频率为400Hz,与分频的设计要求一致。
波形(3)为波形的进一步放大,可以清晰的看到信号sec的周期为1×ps,即为,频率为10Hz,与设计要求一致。
图3-1分频器测试仿真波形(3)
(2)按键处置模块测试代码
`timescale1us/1ns
moduledebouncer1_tb;
regclk,up;
wireout;parameterdelay=1000;p(up),.clk(clk),.out(out));
endmodule
图3-2防抖动电路仿真波形
(1)
约为12ms
图3-3局部放大波形
从图3-2、3-3的防抖动电路仿真波形能够看出,在输入高低电平不断转变的情形下,输出老是维持在一个稳固的“高电平”状态,达到了电路消抖的目的。
操纵器模块测试代码:
`timescale1ns/100ps
modulecontrol_16_tb;
regsys_clk,buttonout,start;
wireclear,count,stop;
parameterdely=160;
control_16test(.sys_clk(sys_clk),.buttonout(buttonout),
.clear(clear),.count(count),.stop(stop),.start(start));
initialsys_clk=0;
always#(dely/2)sys_clk=~sys_clk;
initial
begin
start=1;buttonout=0;
#delystart=0;buttonout=1;
#(dely*10)buttonout=0;
#(dely*5)buttonout=1;
#(dely*8)buttonout=0;
#(dely*5)buttonout=1;
#(dely*5)$stop;
end
endmodule
图3-4操纵器模块仿真波形
从图3-4中能够看出,只要buttonout处于高电平,输出信号clear、count、stop按时钟周期依次输出,在一个时钟周期内三个信号总只有一个是高电平,为互斥信号。
对照图2-6操纵器的流程图,仿真波形与操纵设计要求一致。
计时模块测试代码
`timescale1ns/100ps
modulecount_tb;
regclear,count,stop,sec,sys_clk;
wire[3:
0]qss;
wire[7:
0]qs,qm;
parameterdely=100;
countertest(.clear(clear),.count(count),.stop(stop),.sys_clk(sys_clk),.sec(sec),.qss(qss),.qs(qs),.qm(qm));
initialsys_clk=0;
always#(dely/2)sys_clk=~sys_clk;
initial
begin
clear=1;count=0;stop=0;sec=0;
#delyclear=0;count=0;stop=1;sec=1;
#(dely*100)clear=0;count=1;stop=0;sec=1;
#(dely*130)clear=0;count=1;stop=0;sec=0;
#(dely*300)clear=1;count=1;stop=0;sec=1;
#(dely*500)clear=0;count=1;stop=0;sec=1;
#(dely*200)clear=0;count=1;stop=0;sec=0;
#(dely*250)clear=0;count=1;stop=0;sec=1;
#(dely*200)sec=0;
#(dely*300)clear=0;count=0;stop=1;sec=1;
#(dely*100)clear=0;count=1;stop=0;sec=1;
#(dely*500)clear=0;count=0;stop=1;sec=0;
#(dely*200)$stop;
end
endmodule
图3-5计时器模块仿真波形
(1)
图3-6计时器模块仿真波形
(2)
图3-五、3-6为计时器模块的仿真波形,从放大的波形
(2)能够看到十进制BCD码计数器、六十进制BCD码计数器
(1)、六十进制BCD码计数器
(2)知足相互级联的关系。
当十进制BCD码计数器进位时,六十进制BCD码计数器
(1)计数;当六十进制BCD码计数器
(1)进位时,六十进制BCD码计数器
(2)计数。
六、实验心得、体会
通过这次数电实验,大体把握了VerilogHDL代码的语法,会编写一些大体模块的VerilogHDL代码,及其测试代码的,比如任意进制计数器、分频器、计时器、操纵器、还有一些大体的组合电路。
以下是我对VerilogHDL代码的一些熟悉总结,和在软件仿真、综合实现进程中碰到的一些问题和解决方法。
一、VerilogHDL代码的一些熟悉总结:
在VerilogHDL代码中的变量有两种数据类型:
net类型和variable类型。
用的平常的数据类型有net型中的wire和variable类中reg。
reg型必需放在进程块语句中。
在编写VerilogHDL代码是,模块的输入变量默以为wire类型,不需要从头声明。
在模块级联时,中间变量的数据类型为wire型,因为级联是线性的。
一样的进程块语句有:
initial和always语句。
initial进程块中的语句只执行一次,一样用于仿真中的变量初始化。
always进程块中的语句那么是不断重复执行的。
赋值语句也分为两种:
assign为持续赋值语句,要紧用于对wire型变量的赋值;进程赋值语句多用于对reg型变量进行赋值。
过称赋值有阻塞赋值和非阻塞赋值两种方式。
在ise综合中,一个进程块语句中只能利用一种赋值语句,及阻塞赋值和非阻塞赋值不能混用,不然ise的综合通只是。
模块与模块之间的级联时,在顶层文件中各模块的模块声明必需与挪用的模块声明一致。
为避免写错,建议利用复制粘贴的方式,幸免显现一些细小有事关重大的语法错误。
关于级联中的一些中间变量数据长度,默以为一名。
通过编写操纵器的代码,对状态图及状态转换有了深刻的熟悉,能够依照状态图或状态机图编写VerilogHDL代码。
一样有单进程描述和双进程描述方式。
在数据选择器模块中,用case语句能简练的实现预想的功能。
二、实验进程中碰到的问题及解决方法
(1)BCD计数器代码编写问题
十进制BCD码编写没有问题,而六十进制BCD码计数器的编写进程中没有注意到运算机运行的事二进制代码。
因此六十进制的模60转换为BCD码为0110’0000,在运算机“看来”是二进制代码。
转换为十进制数是90,故在模块的变量模n的概念中,n应取为90。
(2)ise综合问题
在ise综合进程中,会显现错误提示。
认真检查以后发觉是,在同一个进程块语句中阻塞赋值和非阻塞赋值混用。
ise综合时有很多的waring,这是我在编写VerilogHDL代码时,对一些细节方面没有注意,比如一些对自己不需要的输出,应当用()代替。
问题细小,但也可能显现一些大问题。
因此尽管综合编译通过了,并非意味着模块的功能就如自己预先设计的一样。
(3)功能实现问题
(i)第一次ise工程综合、约束、实现并下载只后,数码显示器上只有第一名点亮。
按下操纵按钮,无任何作用。
分析:
(1)数字显示正常,说明显示模块中7段数码管显示代码编写正确。
(2)有可能是分频器有问题,扫描频率太低,在人眼看来只有一个数字显示。
(3)按键防抖动有问题。
检查:
通过认真检查,分频器modelsim仿真正确,扫描频率符合要求。
要紧问题出在显示器模块的顶层文件中,由于我对所有大体模块都设定了复位端,且都是高电平有效。
而在级联进程中,把5进制计数器中复位键始终置于复位状态,因此每过来一个时钟信号,计数器都会清零,因此无法实现计数的功能,数据q始终是3’b000,因此始终只有第一名点亮。
解决方式:
对所有模块的复位端都置0,幸免复位清零的干扰。
悔改来以后,数码显示器5个数字都显示0,按下按钮,仍旧没有计时。
(ii)由上面的现象推出按键模块存在问题。
由于按键防抖动电路在实验11中已经成功实现功能,其代码都是沿用上次实验的代码,应该可不能显现错误。
对其子模块:
同步器、分频器、计时器、操纵器、频宽变换电路测试后发觉,操纵器与预期不一样。
认真检查后发觉,其中一个状态的逻辑输出写错了。
为避免ise综合显现问题,将按键模块和操纵器模块中的操纵器中的最后一个状态命名defaul,目的是让状态机在任何情形下都能进入正确的状态。
(iii)将操纵器修更正确后,再次下载实现后,发觉按下按钮后,第一名计数只有0,1的转变,且转变频率专门快,其余高位也有进位计数,可是也是有0,1的转变,转换时刻不确信。
分析:
可能是计数器模块显现问题。
检查:
对计数器模块进行modelsim仿真后,发觉该模块的功能正常。
再次对所有代码检查后发觉,问题出在顶层文件的模块级联中。
在模块级联中,中间变量默以为一名长度,而在顶层文件中,我对所有中间变量均没有概念,故所有中间变量的数据长度就默以为一名。
而在计时器模块中,秒计时模块、秒计时模块、分计时模块输出数据的长度别离为4位BCD码、8位BCD码、8位BCD码。
一名数据只有0,1的转变,故输出显示也只有0,1的转变。
解决方式:
在顶层模块中,概念wire[3:
0]qss;wire[7:
0]qs,qm;在级联时,要注意中间变量的数据长度,假设只有一名,可省略不写,假设两位及以上那么必需概念中间变量的数据长度。
将顶层文件更正后,再次下载实现,按下按键后,开始计时,再次按键那么计时停止,再按键时,计数清零,实现设计要求。
3感想:
咱们对数字式钟表并非陌生,可是要咱们通过自己的学习来实现这一简单的秒表功能,却是问题百出。
第一是VerilogHDL代码的编写,随着数电理论课进度的深切