【原创】FPGA应用(一)——流水灯
0赞
发表于 7/8/2015 12:33:44 AM
阅读(6318)
一、设计需求
设计一个功能模块使红色飓风E45板上的8盏led灯流动起来,像流水一样。
二、设计思路
首先,有一点要明确的是led灯的每一次流动都是需要时间间隔的。也就是说,8盏led灯所对应的状态只有经过一段时间延迟后才能发生改变。根据这种思路,在开始设计之前提出两个问题:第一,led灯的状态需要多久发生一次改变;第二,led灯的状态根据什么发生改变。对于第一个问题,可以通过设计计时器来控制时间,如每0.5秒(即2Hz)就产生一个周期的时钟或时钟使能信号;对于第二个问题,led灯的状态可以在生成的2Hz时钟上升沿发生改变,也可以在时钟使能信号下发生改变。但在FPGA设计技巧中推荐同步设计,于是本设计放弃采用产生时钟信号的方案,而是选择时钟使能信号。其对应的时序如图1所示。
图1 流水灯时序图
三、设计实现
在计时器的作用下,每隔0.5秒就产生一个高电平的时钟使能信号cnt_flag,而当检测到时钟使能信号为高电平时,led灯状态led_data发生改变,这样就实现了流水灯的效果。其对应Verilog HDL实现如下所示:
`timescale 1ns/1ps
module water_led(
rst_n,
clk,
led_data
);
// 参数定义
parameter DATA_WIDTH = 8; // 通过修改该参数可应用于led盏数不同的场合
// 端口定义
input rst_n; // 全局异步复位
input clk; // 50MHz
output reg [DATA_WIDTH-1:0] led_data;
// 实现每0.5秒就产生一个时钟使能信号
parameter DELAY_CNT = 25'd25_000_000; // 0.5s
reg [24:0] cnt; // 计数器变量
wire cnt_flag = (cnt==DELAY_CNT-1'b1); // 时钟使能信号
always @(posedge clk or negedge rst_n)
begin
if(rst_n==1'b0)
cnt <= 0;
else if(cnt_flag==1'b1)
cnt <= 0;
else
cnt <= cnt + 1'b1;
end
// led灯状态的控制
always @(posedge clk or negedge rst_n)
begin
if(rst_n==1'b0)
led_data <= {{(DATA_WIDTH-1){1'b0}},1'b1}; // 复位初始化
else if(cnt_flag==1'b1)
led_data <= {led_data[DATA_WIDTH-2:0],led_data[DATA_WIDTH-1]}; // 左移
else
led_data <= led_data;
end
endmodule其modelsim功能仿真如图2所示(为了使仿真节省大量时间,将参数DELAY_CNT改小,如本设计改为DELAY_CNT=25'd250):
图2 流水灯modelsim功能仿真
功能仿真正确之后,便可进行综合(综合之前记得把DELAY_CNT改为25'd25_000_000)、管脚约束、实现、生成bit流、下载到板子,最后可在板子上看到8盏led灯像流水一样流动起来。


