FPGA学习记录(2):计数器编写
注:使用的是野火的征途mini FPGA开发板(参考野火系列视频)
1.定时点亮led灯
-
目标
- 利用计数器定时1s,实现0.5s灯亮,0.5s灯灭
-
模拟框图
开发板使用的是50MHz的晶振也就是
频率f = 50MHz = 5*10^7KHz
所以t=1/f= 2*10^7
所以计数1s所需要的计数为
M=1/t=25000000
因为是从0开始计数所以计数的最大值为
M=24_999_999
通过计算器可以知道M为25位宽的
定义两个寄存器变量,cnt与cnt_flag
cnt用于计数
cnt_flag用来控制led亮灭的变化
起始让cnt_flag为低电平,每当cnt计数到最大值的的一半时即达到0.5s时
改变cnt_flag的状态,这样就可以实现0.5s灯亮,0.5灯灭
- 波形图绘制
-
代码编写
-
rtl代码
/*------------------------- Function:定时1s,点亮led Date:2020/2/12 Reference:"野火" Author:Troke ---------------------------*/ module counter #( parameter CNT_MAX = 25d'24_999_999 //定义参数变量 ) ( input wire sys_clk, //定义时钟线 input wire sys_rst_n, //定义复位信号 output reg led_out ); /*定义两个寄存器变量,一个用于计数,一个用于控制led*/ reg [24:0] cnt; reg cnt_flag; /*对cnt的编写*/ always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt <= 25'd0; //起始给cnt赋值为0 else if (cnt == (CNT_MAX)) cnt <= 25'd0; //当cnt计数到最大值时,重新赋值为0 else cnt <= cnt + 25'd1; //其他情况让cnt自加 /*对cnt_flag的编写*/ always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) cnt_flag <= 1'b0; //起始给cnt_flag赋值低电平 else if (cnt ==(CNT_MAX-25'd1)) cnt_flag <= ~cnt_flag; //当计数到最大值减1时,改变cnt_flag的状态 else cnt_flag <= cnt_flag; //其他情况cnt_flag保持原来的状态 /*对led_out的编写*/ always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) led_out <= 1'b0; //起始给led_out赋值低电平 else if (cnt_flag == 1'b1) led_out <= ~led_out; //当cnt_flag改变状态时,改变led的状态 else led_out <= led_out; //其他情况保持led状态 endmodule
-
testbench代码
`timescale 1ns/1ns module tb_counter(); reg sys_clk; reg sys_rst_n; wire led_out; initial begin sys_clk = 1'b0; sys_rst_n <= 1'b0; #20 sys_rst_n <= 1'b1; end always #10 sys_clk = ~sys_clk; counter #( .CNT_MAX(25'd 24) //设置参数变量的值 ) counter_inst ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .led_out (led_out) ); endmodule
-
-
仿真结果