数电基础
关于时序逻辑设计的部分依然强烈推荐mooc上华科的数字电路与逻辑设计。
计数器可以分为同步和异步计数器,2进制、10进制和任意进制计数器,加法和减法计数器。同步和异步是指触发器是否都由同一个时钟信号控制。一个触发器能存储1位二进制数,所以由N个触发器构成N位寄存器。例如3个JK触发器可以存储000-111种状态。在数电的原理方面,mooc上讲解的很清晰,可以自行学习同步或异步的二进制寄存器、使用复位清零和反馈置数将M进制构成N进制(N
设计规划
本例将采用一个外部时钟信号,一个复位键和一个LED灯来实现1s内LED闪烁(亮0.5s灭0.5s)。这种计时的功能在FPGA中是通过计数器完成的: 经历一个时钟周期,计数器+1 ,我们只需要计算出计数截止的值,就可以完成计时。由于采用的50MHz时钟频率,也就是1s产生510e7个时钟。那么亮灭0.5s就是需要计2.510e7个数。计数器从0-24999999,2^24<24999999<2^25,因此需要25个触发器,即25位寄存器。这个计数过程是:复位键生效时计数器归零,释放后的第一个时钟上升沿开始计数,从0计到2499999时LED灯改变状态,计数器归零重新开始计数,到2499999时LED灯改变状态...
编写代码
module counter
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk , //系统时钟50MHz
input wire sys_rst_n , //全局复位
output reg led_out
);
reg [24:0] cnt; //经计算得需要25位宽的寄存器才够500ms
//cnt:计数器计数,当计数到CNT_MAX的值时清零
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 25'b0;
else if(cnt == CNT_MAX)
cnt <= 25'b0;
else
cnt <= cnt + 1'b1;
//led_out:输出控制一个LED灯,每当计数满标志信号有效时取反
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led_out <= 1'b0;
else if(cnt == CNT_MAX)
led_out <= ~led_out;
endmodule
代码注释:与#define 标识符 常量类似,这里使用参数的方式定义常量。在RTL代码中实例化该模块时,如果需要两个不同计数值的计数器,只需要修改常数值。使用testbench仿真时也需要实例化,0.5s才能看到led_out的变化,仿真时间过长。如果我们直接修改参数缩短时间就能看到效果。parameter定义的是局部参数,只在本模块中有效,不会影响实际值。
我们观察cnt和led_out的变化条件:计数器发生改变的条件有两个,一个是时钟上升沿,一个是复位有效(复位下降沿)。计数器发生的改变有两个,要么+1要么清零。清零条件有两个:复位和溢出。因此第一个always块中有三个判断条件:复位和溢出时清零,其他的时候+1。
led_out的变化条件:时钟上升沿和复位有效(复位下降沿)。LED灯状态的变化有两个,当复位时LED灯为低电平,溢出时取反。
编写testbench
`timescale 1ns/1ns
module tb_counter();
//reg define
reg sys_clk;
reg sys_rst_n;
//wire define
wire led_out;
//初始化输入信号
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
//sys_clk:每10ns电平翻转一次,产生一个50MHz的时钟信号
always #10 sys_clk = ~sys_clk;
//---------------------flip_flop_inst----------------------
counter
#(
.CNT_MAX (25'd24 )
)
counter_inst(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.led_out (led_out )
);
endmodule
初始化:时钟高电平,复位低电平,20s延迟后复位高电平。
实例化:此处的参数只对该模块有效,想要改变这个模块里的参数数值,只需要在这里改变即可。这里设置成24是为了方便观察,节省时间。
对比波形
24个时钟脉冲输出就会取反,同理trl文件中24999999个脉冲(0.5s)之后LED灯会改变状态,实现1s内闪烁。
分配管脚
全编译后上板验证
LED灯在1s内闪烁,且S1一直按LED灯会一直亮(S1按下去为低电平,复位有效,led_out=0,LED灯亮,和预期一致。
-
FPGA
+关注
关注
1629文章
21729浏览量
603013 -
计数器
+关注
关注
32文章
2256浏览量
94478 -
数字电路
+关注
关注
193文章
1605浏览量
80580 -
触发器
+关注
关注
14文章
2000浏览量
61132 -
时钟信号
+关注
关注
4文章
448浏览量
28542
发布评论请先 登录
相关推荐
评论