【原创】FPGA应用(一)——流水灯
0赞
发表于 7/8/2015 12:33:44 AM
阅读(4796)
一、设计需求
设计一个功能模块使红色飓风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灯像流水一样流动起来。