目录
一、实验目的
二、实验要求
三、实验代码
1.实验源码
2.部分代码设计思路分析
四、实验结果及分析
1、引脚锁定
2、仿真波形及分析
3、下载测试结果及分析
五、实验心得
1.解决实验中遇到的困难及解决
2.完成实验后的心得
一、实验目的
(1)掌握组合逻辑电路和时序电路的 FPGA实现方法;
(2)熟悉EDA开发板和开发软件的使用方法;
(3)学习静态数码管的使用和7段数码显示译码器设计;
(4)掌握时钟在时序电路中的作用;
(5)掌握分频电路的实现方法。
二、实验要求
设计BCD计数器,可任选模的大小(最大模值至少3位),实验要求:
(1)计数结果用3位数码管显示,显示BCD码;
(2)给出此项设计的仿真波形;
(3)选择实验电路验证此计数器的功能。
(4)设计模值可变的输入端口,通过输入模值和设置信号改变计数器模值
(5)设置涉及1个开关和一个按键,开关作为使能控制,按键作为异步清0。
(6)带有进位输出,并进位输出用LED灯显示
三、实验代码
1.实验源码
(1)design source文件(限于篇幅,仅展示部分代码,核心代码均标注有)
-
`timescale 1ns / 1ns module final_counter(input CLK, input SW1, input KEY1, input [6:0] M_SET, input M_EN,output reg [10:0] display_segout,output reg LED_OUT //输出,用于显示进位状态 );reg [6:0] M; // 计数器模数 wire [3:0] bw; wire [3:0] sw; wire [3:0] gw; wire [3:0] qw; reg [7:0] cnt_count;//设置模值 always@(posedge M_EN)beginM[0]<=M_SET[0];M[1]<=M_SET[1];M[2]<=M_SET[2];M[3]<=M_SET[3];M[4]<=M_SET[4];M[5]<=M_SET[5];M[6]<=M_SET[6];end//数码管各位逻辑关系 assign qw =M/10; assign bw =M%10; assign sw =cnt_count%100/10; assign gw =cnt_count%10;reg [19:0]count=0; reg [30:0]count2=0; reg [2:0] sel=0; parameter T1MS=50000; reg [6:0]t;//多位数码管显示 always@(posedge CLK) begin count<=count+1; if(count==T1MS) begin count<=0; sel<=sel+1; if(sel==4) sel<=0; end end //板子计数频率 reg clk1; always @(posedge CLK)begin if(count2 == 9_999_999) // 9_999_999==100msbegin clk1<=1'b1; count2<=0;end elsebegin clk1<=1'b0;count2<=count2+1'b1;endend //板子数码管显示 always@(posedge CLK) begin case(sel) 0:display_segout<={4'b0111,BCD_OUT0};1:display_segout<={4'b1011,BCD_OUT1};2:display_segout<={4'b1101,BCD_OUT2};3:display_segout<={4'b1110,BCD_OUT3};default:display_segout<=11'b1111_1111111; endcase end//计数器逻辑 always @(negedge clk1 or posedge KEY1 ) beginif(KEY1 == 1'b1) // 异步清零begincnt_count <= 0;endelse if(t!=M)begincnt_count <= 0;t=M;endelse if(SW1 == 1'b1) // 使能控制beginif(cnt_count<M-1)begincnt_count<=cnt_count+1;LED_OUT<=1'b0;if(cnt_count == M-2)LED_OUT <=1'b1;endelsebegin cnt_count<=0;LED_OUT<=1'b0;endend endend module
(2)仿真测试文件
-
`timescale 1ns/1ps module sim_CNT(); reg SW1,KEY1; reg [6:0]M_SET; reg M_EN; wire [10:0] display_segout; wire LED_OUT;reg clk1;initialbeginclk1= 1'b0;SW1 = 1'b0;M_EN=1'b0;#2 KEY1 = 1'b1;M_EN<=1'b1;M_SET<=7'b000_1010;M_EN=1'b0;#2 M_EN=1'b0;#2 KEY1 = 1'b1; //清零#2 KEY1 = 1'b0; SW1 = 1'b1; //复位,准备开始#192 M_EN<=1'b1;M_SET<=7'b001_1111;#2 M_EN=1'b0;#20#2 KEY1 = 1'b1; //清零#2 KEY1 = 1'b0; SW1 = 1'b1; //复位,准备开始end alwaysbegin#5 clk1 = ~clk1;end final_counter uu1(clk1,SW1,KEY1,M_SET,M_EN,display_segout,LED_OUT);endmodule
2.部分代码设计思路分析
(1)进行分频操作,输出为 clk1,每两次完整的 clk 跳变等价于一次完整的
clk1 跳变,每次 clk1 上升沿到来时(使能端信号有效且异步清零信号无效时),
计数器的值加一。
(2)计数器进行设计。计数器的跳变以 clk1 时钟信号为准,当使能端有效、
清零信号无效时,在每次 clk1 上升沿跳变之际,若计数器的值小于设定的模值
model,那么其值就继续加 1,若计数器的值等于设定的模值,那么计数器的值回到 0 开始重新计数。其中当计数器处于该模值下最大数时,out 信号会在一个
时钟信号内变为 1,代表本次模值计数即将结束。
四、实验结果及分析
1、引脚锁定
set_property PACKAGE_PIN U16 [get_ports {cnt_count[0]}]
set_property PACKAGE_PIN E19 [get_ports {cnt_count[1]}]
set_property PACKAGE_PIN U19 [get_ports {cnt_count[2]}]
set_property PACKAGE_PIN V19 [get_ports {cnt_count[3]}]
set_property PACKAGE_PIN W18 [get_ports {cnt_count[4]}]
set_property PACKAGE_PIN U15 [get_ports {cnt_count[5]}]
set_property PACKAGE_PIN U14 [get_ports {cnt_count[6]}]
set_property PACKAGE_PIN V14 [get_ports {cnt_count[7]}]
set_property PACKAGE_PIN U7 [get_ports {display_segout[0]}]
set_property PACKAGE_PIN V5 [get_ports {display_segout[1]}]
set_property PACKAGE_PIN U5 [get_ports {display_segout[2]}]
set_property PACKAGE_PIN V8 [get_ports {display_segout[3]}]
set_property PACKAGE_PIN U8 [get_ports {display_segout[4]}]
set_property PACKAGE_PIN W6 [get_ports {display_segout[5]}]
set_property PACKAGE_PIN W7 [get_ports {display_segout[6]}]
set_property PACKAGE_PIN W4 [get_ports {display_segout[7]}]
set_property PACKAGE_PIN V4 [get_ports {display_segout[8]}]
set_property PACKAGE_PIN U4 [get_ports {display_segout[9]}]
set_property PACKAGE_PIN U2 [get_ports {display_segout[10]}]
set_property PACKAGE_PIN V17 [get_ports {M_SET[0]}]
set_property PACKAGE_PIN V16 [get_ports {M_SET[1]}]
set_property PACKAGE_PIN W16 [get_ports {M_SET[2]}]
set_property PACKAGE_PIN W17 [get_ports {M_SET[3]}]
set_property PACKAGE_PIN V15 [get_ports {M_SET[5]}]
set_property PACKAGE_PIN W14 [get_ports {M_SET[6]}]
set_property PACKAGE_PIN W15 [get_ports {M_SET[4]}]
set_property PACKAGE_PIN W5 [get_ports CLK]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets M_EN_IBUF]
set_property PACKAGE_PIN L1 [get_ports LED_OUT]
set_property PACKAGE_PIN R2 [get_ports SW1]
set_property PACKAGE_PIN T1 [get_ports M_EN]
set_property PACKAGE_PIN U18 [get_ports KEY1]
set_property PACKAGE_PIN T1 [get_ports M_EN]
set_property PACKAGE_PIN U18 [get_ports KEY1]
2、仿真波形及分析
SW1为使能端,M_SET为设置的模值,R_SET为清零信号,LED_OUT为计数器输出,cnt_count为计数序列,clk1为时钟信号,SET为模值变化的开关
以上述波形为例进行分析
(1)对使能端的验证:
前10ns,使能端为低电平,无效,计数器不进行计数。使能端为高电平后:当模值为2时,每隔两个时钟信号LED_OUT产生输出信号。
(2)对复位功能的验证
实验要求R_SET作异步清零,如图中蓝线时刻所示,当R_SET信号为 0 时,计数器
的值立刻清零。
(3)对模值变换的验证
观察可知此处实现了模值的变换,在SET键有效后,计数器也以新的模值进行了重新计数。
在异步清零后,模值变为9,当第九个时钟信号到达后,LED_OUT产生输出信号,后面计数器模值继续变化,LED_OUT对应产生输出信号。
波形仿真可观察到复位、使能、模值进位输出和设置模值的功能,故实现了任意模值计数器的功能。
3、下载测试结果及分析
数码管前两位表示模值,后两位表示计数
模值可设置为1~15,由右下角的四个按钮开关设置,L1所指的led灯代表输出信号,每结束一次计数,就会亮一次。
下面是模值为12 和15时开发板的运行照片
(1)模值为12、计数为11时的临界情况 (2)模值为15时
分析:
当模值为12,计数值为11时,led灯亮,表示模值为 12的一次计数结束
当模值为15,计数值为14时,led灯亮,表模值为15的一次计数结束。
综上可知下载测试现象与仿真相吻合。
五、实验心得
1.解决实验中遇到的困难及解决
(1)代表计数到模值最大时刻的输出信号 out 跳变不是在数值最大的时候,而是在计数器数值回到 0 的时候才变为 1,即跳变时刻比计数器晚一个时钟信号。
解决方法:在代码文件的计数器模块程序中更改一个判断条件。原程序的编写是只要计数器的数值等于模值,out 就输出 1,但这个判断条件的结果似乎只会在下一个时钟信号才显示。于是将该部分程序改为,当计数器数值等于模值时,判断一个成立的结果,即刻 out 输出为 1。发现将代码更改后,out 能够成功在数值最大处跳变。
(2)为何要进行分频?
这个要求是在我刚看到实验要求提出的,当时也是满心疑惑,为什么要进行分频,分频有什么好处?查阅资料后得知,分频就是将原有频率除以分频值得到当前频率,简单的来说就是以整数倍降低频率。分频之后可以使输入的速度降低,否则振荡频率太高,信号持续的周期过短,设备无法正常响应。而且有些外设的设备频率要求不同,如果没有分频电路也就控制不了。进行一定的分频还可以缩短仿真时间,提高实验效率。
2.完成实验后的心得
在完成这个实验的过程中,我遇到了一些问题和挑战,但通过不断的尝试和调试,最终成功地完成了整个实验。
我认为充分理解计数器工作原理对于完成此次实验是十分重要的一件事。在进行计数器实验时,需要充分理解计数器的工作原理,以便可以根据需要进行合适的参数设置和设计。最初的时候没有搞懂老师的要求,后面才知道要在数码管上实现左边两位表示模值,右边两位表示计数过程。但经过多次代码的调试后还有完成了实验的验收。
总的来说,模可变计数器设计实验是一项非常有意义和有用的设计实践项目,在这个实验中我们可以学习到许多数字电路设计的基础知识,同时也可以提高我们的问题解决和思维能力。同时,也需要我们具备耐心和毅力,通过不断的调试和优化,最终完成一个稳定可靠的计数器设计!