问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

FPGA实战:按键控制LED灯的闪烁、流水和跑马灯效果

创作时间:
作者:
@小白创作中心

FPGA实战:按键控制LED灯的闪烁、流水和跑马灯效果

引用
CSDN
1.
https://blog.csdn.net/2201_75683149/article/details/133417109

本文将介绍如何使用Verilog语言在FPGA开发板上实现LED灯的闪烁、流水和跑马灯效果,并通过按键切换不同的模式。具体将使用EP4CE6F17C8开发板,该开发板上有4个共阴极连接的LED灯珠。

前言

用Verilog语言点亮FPGA开发板上的LED灯是最基础的操作之一。本文将详细介绍如何实现以下功能:

  • LED灯的闪烁
  • 流水灯效果
  • 跑马灯效果
  • 通过按键切换不同的LED灯模式

最终目标是实现一个“点灯大师1.0”,能够通过按键切换不同的LED灯运动模式。

一、认识LED灯珠

四个LED灯珠共阴极接地,因此需要高电平导通LED灯。在代码中,led=1表示LED灯亮,led=0表示LED灯灭。

二、工程模块设计

1.系统架构图

系统架构图如下所示,时钟、复位、按键为输入信号,LED为输出信号。

2. LED闪烁

LED闪烁的实现原理是通过按键控制LED灯的状态反转。具体代码如下:

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        led <= 4'b0001 ;    //复位时亮一个     
    end
    else if(key_in[1]==0 && end_cnt_300ms)begin   //按下key_in[1]
        led <= ~led ;     //led[3:1]和led[0]分开闪烁
    end
end

3. 流水灯实现——计数器

流水灯效果的实现需要使用计数器。计数器是一种基本的时序逻辑电路,可以精确控制信号的时间关系。具体代码如下:

parameter  MAX_300MS = 24'd15_000_000 ;
reg		[23:0]	cnt_300ms	   	;//300ms计数器
wire			add_cnt_300ms	;
wire			end_cnt_300ms	;

always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_300ms <= 'd0 ;
    end 
    else if(add_cnt_300ms)begin 
        if(end_cnt_300ms)begin 
            cnt_300ms <= 'd0 ;
        end
        else begin 
            cnt_300ms <= cnt_300ms + 1'b1 ;
        end 
    end
end 

assign add_cnt_300ms = key_in[1]==0 || key_in[2]==0 || key_in[3]==0 ;//按下三个按键开始计时
assign end_cnt_300ms = add_cnt_300ms && cnt_300ms == MAX_300MS - 1;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        led <= 4'b0001 ;//复位时亮一个     
    end
    else if(key_in[2]==0  && end_cnt_300ms)begin
        led <= {led[0],led[3:1]};//长按key[2]从左到右的流水灯
    end
end

4. 跑马灯实现——case语句

跑马灯效果的实现使用了case语句。具体代码如下:

reg   [2:0] state  ;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        state <= 0 ;
    end
    else if(key_in[3]==0  && end_cnt_300ms)begin
            state <= state + 1 ;
        end
        else begin
            state <= state ;
        end
    end

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        led <= 4'b0001 ;//复位时亮一个     
    end
    else if(key_in[3]==0)begin//长按key[3]跑马灯
        case (state)
            3'd0 : led <= 4'b0001 ;
            3'd1 : led <= 4'b0011 ;
            3'd2 : led <= 4'b0111 ;
            3'd3 : led <= 4'b1111 ;
            3'd4 : led <= 4'b0111 ;
            3'd5 : led <= 4'b0011 ;
            default: led <= 4'b0001 ;
        endcase
    end
end

总体代码

完整的Verilog代码如下:

module led(  
    input             clk       ,
    input             rst_n     ,
    input      [3:1]  key_in    ,   //key_in[0]给到E15引脚复位
    output reg [3:0]  led  
);
parameter  MAX_300MS = 24'd15_000_000 ;
reg		[23:0]	cnt_300ms	   	;//300ms计数器
wire			add_cnt_300ms	;
wire			end_cnt_300ms	;
reg   [2:0] state  ;

always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_300ms <= 'd0 ;
    end 
    else if(add_cnt_300ms)begin 
        if(end_cnt_300ms)begin 
            cnt_300ms <= 'd0 ;
        end
        else begin 
            cnt_300ms <= cnt_300ms + 1'b1 ;
        end 
    end
end 

assign add_cnt_300ms = key_in[1]==0 || key_in[2]==0 || key_in[3]==0 ;//按下三个按键开始计时
assign end_cnt_300ms = add_cnt_300ms && cnt_300ms == MAX_300MS - 1;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        state <= 0 ;
    end
    else if(key_in[3]==0  && end_cnt_300ms)begin
            state <= state + 1 ;
        end
        else begin
            state <= state ;
        end
    end

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        led <= 4'b0001 ;//复位时亮一个     
    end
    else if(key_in[1]==0 && end_cnt_300ms)begin//按下key_in[1]
        led <= ~led ;//led[3:1]和led[0]分开闪烁
    end
    else if(key_in[2]==0  && end_cnt_300ms)begin
        led <= {led[0],led[3:1]};//长按key[2]从左到右的流水灯
    end
    else if(key_in[3]==0)begin//长按key[3]跑马灯
        case (state)
            3'd0 : led <= 4'b0001 ;
            3'd1 : led <= 4'b0011 ;
            3'd2 : led <= 4'b0111 ;
            3'd3 : led <= 4'b1111 ;
            3'd4 : led <= 4'b0111 ;
            3'd5 : led <= 4'b0011 ;
            default: led <= 4'b0001 ;
        endcase
    end
    else if(key_in[1] != 0 && key_in[2] != 0 && key_in[3] != 0)begin//没有按键按下的时候led回初始状态
        led <= 4'b0001 ;
    end
end
endmodule

总结

通过本教程,读者可以掌握如何使用Verilog语言在FPGA开发板上实现基本的LED灯控制功能。后续将进阶到更复杂的呼吸灯效果。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号