【verilog】计数器

理论学习

计数器实现的是计数,计数是一种最简单基本的运算。计数器在数字系统中主要是对脉冲的个数进行计数,以实现测量、计数、控制的功能,同时兼有分频功能。

计数器是FPGA设计中最常用的一种时序逻辑,根据计数器的计数值我们可以精确计算出FPGA内部各种信号之间的时间关系,每个信号何时拉高、何时拉低、拉低需要多久、拉高需要多久,都可以比较精准的控制具体需要计数的时间。计数器一般是从0开始计数,计数到我们需要的值或者计数满溢出后清零,并可以进行不断的循环,3位数的十进制计数器可最大计数到999,4位数的最大可以计数到9999;3位数的二进制计数器最大可以计数到111(7),4位数的最大可以计数到1111(15)。

实验目标

本例让计数器1s时间间隔,来实现led灯每隔1s闪烁一次的效果。

设计

这里设计一个不带标志信号(cnt_flag)的计数器
在这里插入图片描述=============================================================

对于计数器的设计要控制好两个问题:

什么时候开始计数

这个系统除了时钟和复位没有外界的其他输入了,所以只要复位一撤销,时钟沿来到就可以立即进行计数,所以对于计数开始的条件,也可以默认为没有条件。

什么时候清零

计算1s需要计数器计数多少个数。此处计数的时钟就用系统时钟50MHz,换算成时间是0.000_000_02s,计数1s的时间需要50_000_000个。所以计数器要在50MHz的时钟下计50_000_000个数才可以。因为是从0开始计数,所以在50MHz频率下计数1s的最终计数值是49_999_999。
我们实现的是在1s内led灯的闪烁,所以在1s的时间内,亮0.5s,熄0.5s这样的观赏效果最佳。计数到49_999_999需要26位宽的寄存器。为了节省资源,led的电平为高为低交替进行,每隔0.5s取反即可,计数器的值变为0~24_999_999。需要25位寄存器。

counter.v

//counter.v
module counter
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk,
input wire sys_rst_n,
output reg led_out
);
//parameter CNT_MAX = 25'd24_999_999;
reg[24:0] cnt;//计数器变量 位宽25
//计数器的赋值
always@(posedge sys_clk or negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0)begin
		cnt <= 25'd0;
		end else if(cnt == CNT_MAX) begin
		cnt <= 25'd0;
		end else begin
		cnt <= cnt +25'd1;
	end
end
//输出信号的赋值
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(sys_rst_n == 1'b0)begin
		led_out <= 1'b0;
	end else if(cnt == CNT_MAX)begin
		led_out <= ~led_out;
	end else begin //如果复位信号无效 且计数器未达到最大值
		led_out <= led_out;
	end
end
endmodule

counter_tb.v

//counter_tb.v
`timescale 1ns/1ns
module counter_tb();
reg sys_clk;
reg sys_rst_n;
wire led_out;
//赋初值
initial 
begin
	sys_clk = 1'b1;
	sys_rst_n <= 1'b0;
	#20
	sys_rst_n <= 1'b1;
end
//产生时钟信号
always #10 sys_clk = ~sys_clk;
counter //counter_inst
#(
.CNT_MAX(25'd24)
)
counter_inst
(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.led_out(led_out)
);
endmodule

仿真结果

【verilog】计数器_第1张图片
【verilog】计数器_第2张图片
【verilog】计数器_第3张图片

你可能感兴趣的:(verilog,verilog,fpga)