FPGA实战-----点灯大师(1)led灯闪烁流水跑马+按键

这篇具有很好参考价值的文章主要介绍了FPGA实战-----点灯大师(1)led灯闪烁流水跑马+按键。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【FPGA工程(1)-------点灯大师(1)led灯闪烁流水跑马+按键】

FPGA实战



前言

用verliog语言点亮FPGA开发板上的led灯是最最最最最基础的操作。
这里用的EP4CE6F17C8开发板,上边一共有四个led灯珠,可以实现简单的例如4个全亮,流水灯,跑马灯以及相比之下难了一点的呼吸灯等等等等效果。
本文最终目的就是实现用按键切换led灯的运动模式。做一个真正的“点灯大师1.0”。


一、认识led灯珠

fpga灯光效果,FPGA实战,fpga开发,硬件工程

四个led灯共阴极接地,所以需要高电平导通led灯。也就是代码中led=1,运用到电路中led才会亮。


二、工程模块设计

1.系统架构图

fpga灯光效果,FPGA实战,fpga开发,硬件工程
图中,时钟、复位、按键为输入信号,led为输出信号,这个图看起来简单没什么难度。


2.led闪烁

在上边已经说过了:

四个led灯共阴极接地,所以需要高电平导通led灯。也就是代码中led=1,运用到电路中led才会亮

所以对于代码中的led:1亮0灭。

*************************<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

复位时亮一个为了之后的流水灯设计方便,后边认真看就看懂了。
这里长按key[1]时四个led灯珠会在计数器每次结束计数后变成与当前亮灭状态相反的状态。从而实现了闪烁。


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

fpga灯光效果,FPGA实战,fpga开发,硬件工程
这里实现一个从左向右流动的流水灯。如图,四个灯珠将从左向右依次亮灭。而实现这一效果的方法需要在代码中用到“计数器”这样的东西。
计数是一种最简单基本的运算,计数器就是实现这种运算的逻辑电路,计数器在数字系统中主要是对脉冲的个数进行计数,以实现测量、计数和计时的功能。
计数器也是在 FPGA 设计中最常用的一种时序逻辑电路,根据计数器的计数值我们可以精确的计算出 FPGA 内部各种信号之间的时间关系,每个信号何时拉高、何时拉低、拉高多久、拉低多久都可以由计数器实现精确的控制。而让计数器计数的是由外部晶振产生的时钟,所以可以比较精准的控制具体需要计数的时间。计数器一般都是从 0 开始计数,计数到我们需要的值或者计数满溢出后清零,并可以进行不断的循环
下边是本篇代码中的计数器模版。

//------------------------<计时器>---------------------------
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;

在这里 add_cnt_300msend_cnt_300ms 分别是这个计数器的开始条件和结束条件。这两个条件相当的重要。决定了这个计数器是否能用。
当长按三个按键时计数器会开始计数,且每经过一个周期就加一;当计数到MAX_300MS - 1时,计数器归零
我们计数的时钟就用系统时钟50MHz,换算成时间为**[1/(50_000_000)Hz]s = 0.000_000_02s**,也就是说50MHz频率的时钟一个周期的时间为20ns。
fpga灯光效果,FPGA实战,fpga开发,硬件工程
所以代码中计数器的最大值是14,999,999(因为从0开始计数,所以0也算一位)。
而最大值的位宽看图中的二进制有24位,所以MAX_300MS=24'd14,999,999(代码块end_cnt_300ms定义中用了“-1”,都一样,个人习惯) 。
以上是计数器的运用,知道了这些,接下来就是形成流水灯了。

*************************<led>**********************************************
 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

上述代码是工程中形成流水灯的代码,不要震惊,对,就是这么短。
代码中四个led在复位的情况下让其亮一个就是为了让流水灯的代码可以不那么繁琐。不亮也可以做出来,就是用case语句,不过下面的跑马灯中用了case代码,这里就不用了。
代码中“{led[0],led[3:1]}”运用了“拼接符{}”,这样写相当于让led[0]移到了led[3]的左边,led[0]变成了新的led[3],led[1]顶替了原来的led[0],而在换位过程中,led[0]一直亮着,所以就呈现出了流水的效果。


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

其实我也不知道跑马灯是啥,大体也就下面那么个跑法,俺也不知道为啥叫跑马灯,只是都这么叫(-_-')(图画得不好,献丑了)。
fpga灯光效果,FPGA实战,fpga开发,硬件工程
要实现跑马灯,在这里使用了一个“case语句”
case语句检查给定的表达式是否与列表中的其他表达式之一相匹配,并据此进行分支。它通常用于实现一个多路复用器。
简单来说,就是定义一个数据,有一些不一样的数值,让led(需要改变的数)在这个数据相应的数值去改变灯珠的亮灭。也可以说随着这个数据的变化,去改变led,这个数据是什么值的时候,led必须是一个相对应的亮灭。

case(控制表达式/值)

分支表达式:执行语句

default:执行语句

endcase
以case关键字开始,以endcase关键字结束。在括弧内的表达式将被精确地评估一次,并按其编写顺序与备选方案列表进行比较,与给定表达式匹配的备选方案的语句将被执行。

//------------------------<state>---------------------------
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

***********************<led跑马>**********************************
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

在代码中,state就是case中的“控制表达式/值”,将led亮灭情况(执行语句)与state的编写顺序一一对应并执行。
依靠这些代码,实现led跑马灯。


总体代码

/*
 * @Projcet: led
 * @Author: Yang.
 * @Date: 2023-08-22 18:59:46
 * @LastEditors: Yang.
 * @LastEditTime: 2023-09-29 21:58:06
 */
//---------<模块及端口声名>------------------------------------------------------
module led(  
    input             clk       ,
    input             rst_n     ,
    input      [3:1]  key_in    ,   //key_in[0]给到E15引脚复位
    output reg [3:0]  led  
);
//------------------------<参数定义>---------------------------
reg   [2:0] state  ;
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;//计满数

//------------------------<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[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

总结

这就是上板效果,仿真懒得写了,有空再填。

点灯大师(1)------按键控制led

博客上传的工程都在百度网盘,有压缩包也有整个文件,可以自行下载。

链接:https://pan.baidu.com/s/1boY0JLOdO53gO1Mu1kg1Yg?pwd=aysz
提取码:aysz

点灯虽然简单也有意思,下一章进阶到点灯大师2.0,各位,来做呼吸灯。文章来源地址https://www.toymoban.com/news/detail-764430.html

到了这里,关于FPGA实战-----点灯大师(1)led灯闪烁流水跑马+按键的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【51单片机】按键操作(单个灯闪烁&&流水灯)

    🎊专栏【51单片机】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【如愿】 大一同学小吉,欢迎并且感谢大家指出我的问题🥰 目录 ⭐注意 🍔同一个灯  🏳️‍🌈效果 🏳️‍🌈代码 🏳️‍🌈问题分析 ⭐注意 ⭐P3_1=0,表示按下按键  ⭐为什么while(

    2024年02月01日
    浏览(60)
  • 3、stm32:GPIO输出——LED闪烁、LED流水灯、蜂鸣器

    目录 一、GPIO简介 二、GPIO基本结构 三、GPIO模式 四、GPIO常用寄存器 (1)端口配置低高寄存器(GPIOx_CRL/GPIOx_CRH)(x=A…E) (2)端口输入数据寄存器(GPIOx_IDR)(x=A…E) (3)端口输出数据寄存器(GPIOx_ODR)(x=A…E) (4)端口位设置/清除寄存器(GPIOx_BERR)(x=A…E) (5)端口位清除寄存器(GP

    2024年02月09日
    浏览(34)
  • stm32按键实现LED的闪烁

    首先,需要准备如下硬件设备: STM32F103C8T6单片机开发板 4个LED灯 4个220欧姆电阻 4个按键 接下来,我将讲解如何连接硬件设备。 将4个LED灯连接到STM32单片机的PB0、PB1、PB2、PB3引脚上。 将4个220欧姆电阻连接到PB0、PB1、PB2、PB3引脚上,防止电流过大损坏LED灯。 将4个按键连接到

    2024年02月08日
    浏览(34)
  • (STM32基础)STM32实现LED闪烁&LED流水灯&蜂鸣器

    1、按照新建工程步骤创建工程,新建start、library、user三个文件夹,从固件库添加相应文件 2、keilkil小程序用来清理listings和objects文件夹中编译产生的中间文件,以后需要打包工程的话可以先用keilkill先清理,这样文件夹会大大缩小所占内存。 在library中可以查看外设函数库,

    2024年02月07日
    浏览(41)
  • STM32——led灯的点亮+闪烁+流水灯的实现

    1.原理 其方式有两种一种是寄存器方式一种是库函数方式,但其原理都是一样的。如原理图所示,与LED相连接的IO口置低电平即可点亮led灯 2.寄存器方式–代码 3.库函数–代码 (1)led.c:函数led_config() (2)main.c调用led_config 4.结果展示 原理:让连接的IO口先置零再置1可以使其先亮

    2024年02月08日
    浏览(42)
  • 用STM32单击按键实现LED闪烁和双击按键实现LED呼吸灯效果

    在嵌入式系统中,按键和LED是最常见的外设之一。本文将介绍如何使用STM32微控制器实现按键的单击和双击检测,并通过控制LED的闪烁和呼吸灯效果来呈现按键的触发效果。 第一部分:硬件准备 准备一块STM32开发板,如STM32F103C8T6。 连接一个按键到开发板上的GPIO引脚,并通过

    2024年02月05日
    浏览(66)
  • 【STM32】STM32学习笔记-LED闪烁 LED流水灯 蜂鸣器(06-2)

    电路图示例1 电路图示例2 main.c 接线图如下图所示: 点击下载,现象为LED闪烁。 main.c main.c stm32F103工程模板 01-LED闪烁.rar 02-LED流水灯.rar 03-蜂鸣器示例程序.rar 参考: 【STM32】江科大STM32学习笔记汇总

    2024年03月19日
    浏览(43)
  • 从零开始学习vivado——day4 跑马灯(让8个LED灯以每个0.5s的速率循环闪烁)

    研一从零开始学习verilog!!!此时不学何时学! 第一次写博客,以此激励自己努力学习! 我跟的视频教程是b站的一个up主,小梅哥爱漂流。 ①编写端口代码: ②计数器 其中,一定是=,如果直接用=,则波形图会出现错误,从00000010到00000100的时间会非常短,导致整个图像看

    2024年02月02日
    浏览(38)
  • 51单片机——一个独立按键控制LED的闪烁和熄灭

    目录 一、要求 二、实现 三、总结 消除按键的机械抖动         当按下按键,LED灯闪烁,再按下,LED熄灭。。。。循环操作。         编译环境:keil4         单片机:STC89c516RD 消除按键的机械抖动         按键的机械抖动会影响单片机对按键按下次数的判断。消除抖动的

    2024年02月07日
    浏览(34)
  • [esp32 + LVGL]物理按键控制屏幕上开关和LED闪烁

    IO0 对应按键 控制 IO2LED闪烁,同时当LED亮的时候开关闭合,当LED灭的时候LED闪烁。 为什么这么做,因为手里没有触摸屏。 首先我们要明白开关闭合的原理,对于触摸屏来说,当你触摸开关的时候会触发点击事件,同时给开关控件添加点击事件。 添加点击事件,也就是开关闭

    2024年02月13日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包