fpga[1]计数器(附源码)

计数器

  • 介绍
    • 1.创建项目文件夹
    • 2.绘制波形图
    • 3.编写rtl代码
    • 4.编写testbench代码
    • 5.上板验证
    • 6.总结

介绍

计数器电路是在数字电子技术中应用的最多的时序逻辑电路。计数器不仅能用于对时钟脉冲计数,还可以用于分频、定时、产生节拍脉冲和脉冲序列以及进行数字运算等。
在许多大型电路中必然有计数器电路的身影,可以说了解并掌握计数器的设计方法是学习fpga的第一步。
本文使用的软件是Quartus II 13.1modelsimnotepad++,开发板是黑金的AX301

  • 下图是计数器的基本设计流程。

1.创建项目文件夹

首先我们先创建一个存放项目的文件夹:
在这里插入图片描述
再分别在counter内创建用来存放工程文件、rtl代码和波形图的文件夹:
在这里插入图片描述
然后,打开Quartus II软件,新建一个工程文件并存放在我们刚刚建立好的prj文件夹中,命名为counter
在这里插入图片描述
我们使用的开发板是黑金AX301搭载的是Cyclone IV E系列的EP4CE6F17C8,选择对应的型号。
在这里插入图片描述
为了方便后续的仿真,我们先将仿真软件设置为Modelsim语言为Verilog HDL
在这里插入图片描述

2.绘制波形图

对于计数器这个时序逻辑电路来说,需要时钟的驱动,复位方式选择异步复位。
同时,需要定义一个变量cnt来对时钟进行计数(后续需要利用LED来验证代码,此处先将cnt的位宽设置为25),计数值满时将flag进行取反。
最后将文件存放在visio文件夹中
在这里插入图片描述

3.编写rtl代码

我们在rtl文件夹下建立名为counter的.v文件
在这里插入图片描述
notepad++ 是一款小巧且好用的代码编辑软件,我们在language选项中勾选Verilog语言。
可以看到,notepad++Verilog语言有了关键字提示。
在这里插入图片描述
编写代码如下:

module counter
(input			sys_clk	 ,input			sys_rst_n,		//输入端口为时钟和复位信号output		reg flag			//输出端口为计数器计满时的标志信号
);parameter	CNT_MAX = 24_999; 		//定义计数最大值,方便后续修改reg [24:0]	cnt;		//声明一个25位宽的变量cntalways@(posedge sys_clk or negedge sys_rst_n)		//复位方式设为异步复位if(sys_rst_n == 1'b0)cnt <= 25'd0;		//复位信号为低电平时计数变量清零else	if(cnt == CNT_MAX)cnt <= 25'd0;		//计数器计满时清零else cnt <= cnt + 1'b1;	//其他情况对时钟计数always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)flag <= 1'b0;		//复位信号为低电平时标志信号设为低电平else	if(cnt == CNT_MAX)flag <= ~flag;		//计数器计满时将标志信号进行取反else flag <= flag;		//其他情况标志信号保持不变endmodule

Quartus II中我们进行一次全编译,没有报错。
在这里插入图片描述

4.编写testbench代码

为了验证我们的设计,需要编写testbench文件进行仿真验证
我们编写testbench文件,是为了产生满足条件的激励信号,同时对模块的输出进行捕捉,测试输出是否满足要求。
编写代码如下:

`timescale 1ns/1ns		//设置时间参数
module tb_counter();	//模块声明reg	sys_clk;			
reg sys_rst_n;wire flag;				//声明端口(将原文件中wire类型和reg类型对换)initial					//初始化语句beginsys_rst_n = 1'b0;	sys_clk = 1'b0;		//设置初始参数#50		//延迟50个时间单位sys_rst_n = 1'b1;	endalways#10 sys_clk = ~sys_clk;			//每10个时间单位sys_clk取反一次counter	counter_inst		//例化语句
(.sys_clk	(sys_clk),.sys_rst_n	(sys_rst_n),.flag_0		(flag),
);   endmodule

tb_counter文件添加到工程中,并进行编译
在这里插入图片描述
结果没有报错

在这里插入图片描述
然后使用Quartus & Modelsim 联合仿真
我们可以在Quartus中点击Assignments→Settings→Simulation
在Simulation中的NativeLink Settings中添加文件()

在这里插入图片描述
点击Test Benches添加自己写好的tb文件,这里注意文件名一定要与自己编写的tb_counter文件同名
在这里插入图片描述
完成后回到主页面点击仿真按钮,Modelsim就会被启动,开始仿真
在这里插入图片描述

在前面的rtl代码中,我们将CNT_MAX设置为了24_999,方便这部分的仿真
Instance栏目中我们点击counter_inst 使用ctrl+ W 将添加波形(因为默认的设置无法观察到我们设置的cnt变量)
在这里插入图片描述
在波形管理页面我们按住ctrl + A 然后ctrl + G进行分组,方便我们观察
在这里插入图片描述
点击这里可以隐藏变量地址
在这里插入图片描述
然后点continue run
在这里插入图片描述
再查看全局波形
在这里插入图片描述
波形如下:
在这里插入图片描述
我们需要对局部进行放大,可以看出:
当复位信号有效时(为低电平),cnt未开始计数,复位信号为高电平且时钟上升沿到来时计数开始

在这里插入图片描述
每个时钟上升沿到来时cnt增加1(可以右键cnt变量在Radix中选择Unsigned设置为无符号数)
在这里插入图片描述
当计数到24_999时cnt清零,且flag翻转
在这里插入图片描述
在这里插入图片描述
从这里看出来我们的设计是正确的。

为了更好的观察现象,我们把CNT_MAX设置为24_999_999,准备上板验证。

5.上板验证

我们需要绑定管脚,点击File→New→Tcl Script File

在这里插入图片描述
为了更容易观察现象,我们将flag信号引到LED0上,Tcl脚本如下

set_location_assignment PIN_E1 -to sys_clk
set_location_assignment PIN_N13 -to sys_rst_n
set_location_assignment PIN_E10 -to flag

将Tcl脚本保存到工程中,然后点击Tools→TCL Scripts→Tcl_script1.tcl

在这里插入图片描述
点击Run来执行我们编写好的Tcl脚本
在这里插入图片描述
执行成功

在这里插入图片描述
我们可以在这里看到管脚连接(也可以直接在该界面绑定管脚)
在这里插入图片描述
在这里插入图片描述
完成之后,我们进行一次全编译,然后就可以上板验证,点击这个按钮
在这里插入图片描述
连接开发板后我们可以在Hardware Settings中看到USB-0,需要进行选择(需要预先安装驱动)

在这里插入图片描述
先给开发板上电,然后点击Start在这里插入图片描述
在这里看到,操作成功了
在这里插入图片描述
LED0会以亮0.5秒熄灭0.5秒的规律闪烁。
请添加图片描述

6.总结

本次我们设计了一个计数器,产生了占空比为50%的1Hz方波,以此来控制LED灯的闪烁。后续我们可以通过对1Hz方波进行分频来实现多个LED等按照不同频率闪烁,也可以将计数器作为子模块添加到其他的顶层模块来作为时间基准(1秒),以此来进行其他项目的设计。

工程文件点这下载


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部