1、需求
若在FPGA上实现LED灯一秒闪烁一次,先进行计算,1秒闪烁一次,即周期为1秒,开发板XC7A35TFFG-2的基本时钟输入由板载 50MHz 有源晶振提供,即频率为f = 50MHz 。
则一个周期为 T = 1 f = 1 50 M H z = 20 n s T=\frac{1}{f} = \frac{1}{50MHz}=20ns T=f1=50MHz1=20ns
将一秒钟一分为二,即前0.5秒灯灭,后0.5秒灯亮。即亮和灭的周期数为
0.5 × 1 0 9 ÷ 20 = 25000000 T 0.5\times 10^9 \div20=25000000T 0.5×109÷20=25000000T。假设时钟从0开始,设置一个计数器,如果我们想设计 n n n个时钟周期长度的计数器,一般计数到 n − 1 n-1 n−1即可。
例如设置一个计数为 4 4 4个时钟周期的计数器,时钟从 1 1 1开始,则计数器到 3 3 3即可,执行顺序如下 0 − 1 − 2 − 3 − 1 0-1-2-3-1 0−1−2−3−1.
2、设计定义
该实验有两个输入(复位信号和时钟信号),一个输出(led灯亮灭情况),复位信号低电平有效,时钟是上升沿触发。当复位信号来临时,led灯灭,计数器归0,当计数到24999999时,led灯翻转(即状态和原来相反),计数器归0。
3、编写代码
(1)创建工程,命名为led_flash_test,编写设计文件,其对应的verilog代码如下:
// 让led灯每秒闪烁一次 时序电路设计 module led_flash_test( clk,reset_n,led //信号声明 ); input clk; input reset_n; output reg led; // 在always模块赋值的语句,设为reg型 reg [24:0] counter; // 时钟计数单元 always @(posedge clk or negedge reset_n) if (!reset_n) counter<=1'd0; else if(counter == 24999999) counter<=1'd0; else counter<=counter+1'd1; always @(posedge clk or negedge reset_n) if(!reset_n) led <= 0; else if(counter == 24999999) led <= !led; endmodule
编写测试文件,命名为led_flash_test_tb,其对应的verilog代码如下:
`timescale 1ns/1ps module led_flash_test_tb(); reg clk; reg reset_n; wire led; led_flash_test led_flash_test_inst0( .clk(clk), .reset_n(reset_n), .led(led) ); initial clk=1; always #10 clk = !clk; # 每10ns翻转一次 initial begin reset_n=0; #201; # 避免和时钟上升沿重合 reset_n=1; #1000000000; end endmodule
4、仿真&板级调试
点击run simulation,即可查看仿真结果,如下所示
接下来进行引脚分配,根据开发手册提供的引脚分配表,
将Y18分配给clk,M22(led0)分配给led,F15(按键S0)分配给reset_n,按下表示低电平,进行复位。具体设置如下:
生成比特流文件并写入开发板,效果如下:
一秒闪烁一次
按下复位按钮,灯灭。