- 计数器是依托时钟实现的,在时钟沿(一般在上升沿)进行检测,实现计数加1;
- 计数是从0开始计数的,所以计数值为(M-1),其中M为计数的值。比如计数到10,我们实现时到9即可;
- 这里为计数器的第一种实现方法,该方法非最优方法,我们只需要了解即可,后续我们会介绍另一种方法,可以将两种方案作对比学习。
- 实验:
- 依托板子上的LED灯为例进行讲解,RTL代码都是一样的,针对具体的开发板只需要进行引脚的配置,注意时钟晶振的差别。
- 实验要求:LED灯亮0.5s,灭0.5s,循环操作。
- 波形绘制
- RTL代码
//计数器 module counter #( parameter CNT_MAX = 25'd24_999_999//可以作为实例化中参数传递的接口 ) ( input wire Sys_Clk, input wire Sys_Rst_n, output reg Led_out ); //参数定义 //parameter既可以使用在模块内部,还可以写在模块的开始 //parameter CNT_MAX = 25'd24_999_999; //0.5秒的计时需要的时钟周期个数(时钟从0开始计数) //localparam CNT_MAX = 25'd24_999_999;//只能使用在模块内部 reg [24:0] Cnt; always@(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 +25'd1; 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; else Led_out <= Led_out; /* module Counter #( .CNT_MAX(100),//具体这里传进去的为准,原来的和默认参数类似 ) ( .Sys_Clk (Sys_Clk), .Sys_Rst_n (Sys_Rst_n), .Led_out (Led_out) ); */ endmodule
- 仿真代码
`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 #( .CNT_MAX(25'd24)//可以作为实例化中参数传递的接口 ) counter_inst //注意这里的实例化模块名放在parameter参数后面写 ( .Sys_Clk (sys_clk), .Sys_Rst_n (sys_rst_n), .Led_out (led_out) ); endmodule
---------------------------------------------------------------------------------------------------------------------------------文章来源地址https://www.toymoban.com/news/detail-761201.html
- 第二种方法实现计数器(推荐使用)
- 绘制波形
- RTL代码
//计数器 module counter #( parameter CNT_MAX = 25'd24_999_999//可以作为实例化中参数传递的接口 ) ( input wire Sys_Clk, input wire Sys_Rst_n, output reg Led_out ); //参数定义 //parameter既可以使用在模块内部,还可以写在模块的开始 //parameter CNT_MAX = 25'd24_999_999; //0.5秒的计时需要的时钟周期个数(时钟从0开始计数) //localparam CNT_MAX = 25'd24_999_999;//只能使用在模块内部 reg [24:0] Cnt; reg cnt_flag; always@(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 +25'd1; always@(posedge Sys_Clk or negedge Sys_Rst_n) if(!Sys_Rst_n) cnt_flag <= 1'b0; else if(cnt == (CNT_MAX - 25'd1)) cnt_flag <= 1'b1; else cnt_flag < 1'b0; always@(posedge Sys_Clk or negedge Sys_Rst_n) if(Sys_Rst_n == 1'b0) Led_out <= 1'b0; else if(cnt_flag == 1'b1) Led_out <= ~Led_out; else Led_out <= Led_out; /* module Counter #( .CNT_MAX(100),//具体这里传进去的为准,原来的和默认参数类似 ) ( .Sys_Clk (Sys_Clk), .Sys_Rst_n (Sys_Rst_n), .Led_out (Led_out) ); */ endmodule
- RTL仿真代码同第一种方法。
- Modsim仿真波形
- 绘制波形
文章来源:https://www.toymoban.com/news/detail-761201.html
到了这里,关于FPGA-计数器的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!