Verilog HDL 实现时钟计数器

文章目录

一、简介

我们在这里是实现一个一秒钟计数一次的计数器,也就是说是一个时钟计数器,计数是从0到59一共有60秒,也就是说时钟计数器的模值为60。

具体的功能是每隔一秒钟会把计数加一,然后加到了59以后,下一个状态是0,相当于是0->59,然后59->0的循环,可以往复进行的哦。

Verilog HDL 实现时钟计数器_Verilog

二、代码的实现

我们使用了两个模块:

1、时钟分频

// Module Function:任意整数时钟分频

// Module Function:任意整数时钟分频

module time_split ( clk,rst_n,clkout);

input clk,rst_n; //输入信号,其中clk连接到FPGA的C1脚,频率为12MHz
output clkout; //输出信号,可以连接到LED观察分频的时钟

//parameter是verilog里常数语句
// parameter WIDTH = 3; //计数器的位数,计数的最大值为 2**WIDTH-1
// parameter N = 5; //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出
//


parameter N=12000000;
parameter WIDTH=24;

reg [WIDTH-1:0] cnt_p,cnt_n; //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器
reg clk_p,clk_n; //clk_p为上升沿触发时分频时钟,clk_n为下降沿触发时分频时钟

//上升沿触发时计数器的控制
always @ (posedge clk or negedge rst_n ) //posedge和negedge是verilog表示信号上升沿和下降沿
//当clk上升沿来临或者rst_n变低的时候执行一次always里的语句
begin
if(!rst_n)
cnt_p<=0;
else if (cnt_p==(N-1))
cnt_p<=0;
else cnt_p<=cnt_p+1; //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器
end

//上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_p<=0;
else if (cnt_p<(N>>1)) //N>>1表示右移一位,相当于除以2去掉余数
clk_p<=0;
else
clk_p<=1; //得到的分频时钟正周期比负周期多一个clk时钟
end

//下降沿触发时计数器的控制
always @ (negedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_n<=0;
else if (cnt_n==(N-1))
cnt_n<=0;
else cnt_n<=cnt_n+1;
end

//下降沿触发的分频时钟输出,和clk_p相差半个时钟
always @ (negedge clk)
begin
if(!rst_n)
clk_n<=0;
else if (cnt_n<(N>>1))
clk_n<=0;
else
clk_n<=1; //得到的分频时钟正周期比负周期多一个clk时钟
end

assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p; //条件判断表达式
//当N=1时,直接输出clk
//当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p
//当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&clk_n。正周期多所以是相与
endmodule

2、时钟计数器

module counter(clk,rst_n,seg_led_1,seg_led_2);
input clk;

input rst_n;

// input [3:0] seg_data_1;
//数码管需要显示0~9十个数字,所以最少需要4位输入做译码
// input [3:0] seg_data_2;
//小脚丫上第二个数码管
output [8:0] seg_led_1;
//在小脚丫上控制一个数码管需要9个信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A
output [8:0] seg_led_2;
//在小脚丫上第二个数码管的控制信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A
reg [8:0] seg [9:0];
//定义了一个reg型的数组变量,相当于一个10*9的存储器,存储器一共有10个数,每个数有9位宽

wire clkout;
reg [5:0] counting = 2'd00;
reg [3:0] seg_data_1= 1'd0;
reg [3:0] seg_data_2= 1'd0;

initial
//在过程块中只能给reg型变量赋值,Verilog中有两种过程块always和initial
begin
seg[0] = 9'h3f;
//对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0
seg[1] = 9'h06;
//7段显示数字 1
seg[2] = 9'h5b;
//7段显示数字 2
seg[3] = 9'h4f;
//7段显示数字 3
seg[4] = 9'h66;
//7段显示数字 4
seg[5] = 9'h6d;
//7段显示数字 5
seg[6] = 9'h7d;
//7段显示数字 6
seg[7] = 9'h07;
//7段显示数字 7
seg[8] = 9'h7f;
//7段显示数字 8
seg[9] = 9'h6f;
//7段显示数字 9
end

time_split u1(
.clk(clk),
.rst_n(rst_n),
.clkout(clkout)
);

always @(posedge clkout)
// 实现一秒钟自动计数一次,然后是从0到60
begin
counting <= (counting + 1) % 60;
seg_data_1 <= counting / 10;
if(counting % 10 == 0)
begin
seg_data_2 <= 0;
end
else
begin
seg_data_2 <= counting - 10 * seg_data_1;
end
end



assign seg_led_1 = seg[seg_data_1];
assign seg_led_2 = seg[seg_data_2];

注意这两个需要写在两个文件里面。

之后,我们编译:

Verilog HDL 实现时钟计数器_时钟计数器_02


成功之后,我们分配引脚:

Verilog HDL 实现时钟计数器_Verilog_03

然后就可以烧录了。

Verilog HDL 实现时钟计数器_时钟计数器_04

三、效果展示

我们通过下面的视频来进行展示:

​https://www.bilibili.com/video/BV1944y1a7gH?spm_id_from=333.999.0.0​

Verilog HDL 实现时钟计数器

以上就是我们实现的时钟计数器了啦,谢谢大家的阅读与支持,要是喜欢的话就点个赞吧,谢谢大家的支持啦啦,(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤,(づ ̄3 ̄)づ╭❤~。

谢谢大家的支持。