基于FPGA的流水灯设计

描述

设计规划

依次点亮4个LED灯,实现流水灯的效果,两灯之间点亮间隔为0.5s,LED灯一次点亮持续时间0.5s。

LED灯低电平点亮,因此流水灯应该是1110-1101-1011-0111-1110-1101-...

流水灯

首先是时钟信号、复位信号,由于需要计时,我们还要产生一个计数器cnt。然后还需要产生一个cnt_flag脉冲标志信号作为流水切换的标志,每当计数器计数到24_999_998时拉高并只产生一个时钟的高电平(高电平出现LED状态就开始切换)。最重要的是,流水灯的实现是通过左移操作,无法直接通过led_out的左移实现,因此需要定义一个led_out_reg(led_out从1110左移一次是1100,会有两个灯点亮,而led_out_reg是LED的位反0001,左移一次是0010,取反后led_out是1101,就能实现流水的需求)。

编写代码

module water_led
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk , 
input wire sys_rst_n , 
output wire [3:0] led_out 
 );


 //reg define
 reg [24:0] cnt ;
 reg cnt_flag ;
 reg [3:0] led_out_reg ;


 //cnt:计数器计数500ms
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt <= 25'b0;
 else if(cnt == CNT_MAX)
 cnt <= 25'b0;
 else
 cnt <= cnt + 1'b1;


 //cnt_flag:计数器计数满500ms标志信号
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_flag <= 1'b0;
 else if(cnt == CNT_MAX - 1)
 cnt_flag <= 1'b1;
 else
 cnt_flag <= 1'b0;


 //led_out_reg:led循环流水
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 led_out_reg <= 4'b0001;
 else if(led_out_reg == 4'b1000 && cnt_flag == 1'b1)
 led_out_reg <= 4'b0001;
 else if(cnt_flag == 1'b1)
 led_out_reg <= led_out_reg < < 1'b1; //左移
 assign led_out = ~led_out_reg;
 endmodule

三个中间信号的定义:cnt,cnt_flag,led_out_reg。

1、cnt:计数器变化的条件是时钟上升和复位有效(复位下降),复位信号有效时cnt变为低电平;计满时清零;其他时刻+1。

2、cnt_flag:计数器计满的脉冲标志信号,变化条件和cnt一样,复位有效时变为低电平;计满前一个时钟拉高;其他时刻都为0,这样就能成为一个脉冲信号,并在计满前拉高,标志led要左移。

3、led_out_reg:暂存led灯状态,可以直接对这个信号进行操作来控制LED灯。复位和初始时是最右边的灯亮,反推出led_out_reg=0001;当最左边的灯亮且计满标志信号拉高时,令最右边的灯亮led_out_reg=0001;当计满标志信号拉高时,led_out_reg左移。而控制LED电平的输出信号led_out是led_out_reg的按位取反。

流水灯

编写testbench

`timescale 1ns/1ns
module tb_water_led();
//wire define
wire [3:0] led_out ;
 //reg define
 reg sys_clk ;
 reg sys_rst_n ;
 //初始化系统时钟、全局复位
 initial begin
 sys_clk = 1'b1;
 sys_rst_n <= 1'b0;
 #20
 sys_rst_n <= 1'b1;
 end


 //sys_clk:模拟系统时钟,每10ns电平翻转一次,周期为20ns,频率为50MHz
 always #10 sys_clk = ~sys_clk;
 //-------------------- water_led_inst --------------------
 water_led
 #(
 .CNT_MAX (25'd24)
 )
 water_led_inst
 (
 .sys_clk (sys_clk ), //input sys_clk
 .sys_rst_n (sys_rst_n ), //input sys_rst_n
 .led_out (led_out ) //output [3:0] led_out
 );
 endmodule

testbench代码是非常熟悉的,信号定义,初始化,实例化。

对比波形

流水灯

流水灯

1110-1101-1011-0111分别对应了十六进制的e,d,b,7

由于在testbench模块,为了节省时间将CNT_MAX设置成24,因此24个时钟脉冲LED的状态就会发生变化,波形和我们预想的一致。

分配管脚

流水灯

流水灯

流水灯

流水灯

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分