fpga学习——实现LED流水灯效果

本文介绍了如何利用FPGA中的计数器和不同方法实现LED流水灯效果,包括移位操作、循环位移以及结合3-8译码器简化代码。通过计数器控制LED的翻转频率,展示了从基础操作到高级应用的步骤。
摘要由CSDN通过智能技术生成

实现LED的流水灯效果是入门的基础操作,所谓流水灯就是要让LED按照固定的频率依次闪烁,说到可能可能之前我们编写的计数器程序(实现LED翻转)能够帮助我们实现LED的流水灯效果。可以参考文章:fpga学习day3 LED灯翻转(计数器)-CSDN博客文章浏览阅读297次,点赞12次,收藏6次。在代码实现上,需要先定义LED用到的输入输出端口(对LED_flash模块进行定义),需要用到系统时钟,低电平复位信号(ResetL=0时,所有操作复位)。我们可以采用计数器的方式,对系统的时钟周期进行计数。一个系统时钟周期为20ns,LED端口的信号周期为1ms(0.5ms进行翻转一次),也就是当系统时钟经过25000个周期后,LED端口的信号需要翻转一次。LED闪烁的本质就是输入电平的翻转,因此想要让LED灯按照我们期待的频率闪烁,需要根据板子的系统时钟和LED电平翻转频率之间的关系来实现。https://blog.csdn.net/crrrd/article/details/135704967?spm=1001.2014.3001.5502

这篇文章中使用计数器来使LED灯按照1khz的频率反转。在此基础上,我们可以让扩展板上的8个LED灯按照1Khz的频率一次点亮。下面将介绍三种方法:

一、使用移位方式实现流水灯效果

首先,能想到的最简单和直观的方式就是使用移位运算符<<来实现流水效果。但此时需要注意:当第八个LED点亮时,如果再进行<<操作,会导致8个LED对应的位全为0,图示如下:

我们需要的是当LED7被点亮后,下一次的操作可以让LED0点亮,因此需要使用条件语句来区别不同的情况,当出现上述情况是,下一步让LED变为00000001,其他情况则使用<<进行移位操作,代码如下:

    always@(posedge CLK or negedge Reset_n)
    if(!Reset_n)
        LED <= 8'b00000001;
    else if(counter ==25000000-1)begin
    if((LED==8'b10000000)|LED==8'b00000000)
        LED<= 8'b00000001;
    else
    LED<=LED<<1;
    end

配合之前的计数器部分代码,实现流水灯的整体代码为:

module led_flow(
    CLK,
    Reset_n,
    LED
    );
    
    input CLK;
    input Reset_n;
    output reg[7:0] LED;
    reg [24:0] counter;
    
//计数器部分代码
    always@(posedge CLK or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter ==25000000-1)
        counter <= 0;
    else
        counter <= counter+1'd1;

//移位操作,分情况讨论        
    always@(posedge CLK or negedge Reset_n)
    if(!Reset_n)
        LED <= 8'b00000001;
    else if(counter ==25000000-1)begin
    if((LED==8'b10000000)|LED==8'b00000000)
        LED<= 8'b00000001;
    else
    LED<=LED<<1;
    end
   
endmodule

二、使用循环位移简化方法一的代码

方法一中需要对特殊情况进行讨论,使得代码变得复杂且不直观,在这里我们可以使用拼接方法,直接采用循环位移的方式实现流水灯的效果。

通过图示,我们可以使用{LED[6:0],LED[7]}的拼接语句来替代方法一中的条件分类讨论,使用一行代码解决问题:

/*if((LED==8'b10000000)|LED==8'b00000000)
        LED<= 8'b00000001;
    else
    LED<=LED<<1;*/
LED <= {LED[6:0],LED[7]};

整体实现代码为:

module led_flow_for(
    CLK,
    Reset_n,
    LED
    );

    input CLK;
    input Reset_n;
    output reg[7:0] LED;//8个灯    
    reg [24:0] counter;
    
    always@(posedge CLK or negedge Reset_n)
    if(!Reset_n)//复位端口必须要单独写
        counter <= 0;
    else if(counter == 25000000-1)
        counter <= 0;
    else
        counter <= counter+1'd1;
        
    always@(posedge CLK or negedge Reset_n)
    if(!Reset_n)
        LED <= 8'b0000_0001;
    else if(counter == 25000000-1)
        LED <= {LED[6:0],LED[7]};//位拼接
    else
        LED <= LED;
endmodule

三、参考3-8译码器实现流水灯操作

扩展板上提供了8个LED灯,将这8个LED灯依次点亮,需要的驱动信号与3-8译码器的输出信号相同:

因此可以使用之前编写好的3-8译码器的代码,在工程中进行引用实现对LED的激励,这需要我们对3-8译码器进行模块实例化的操作,具体过程如下:

1.在新建立的工程中导入之前3-8译码器的.v文件,其他操作与先前相同,只是这里需要选择Add

 File而不是Create File。

下面找到实现3-8译码器的代码,后缀为.srcs的文件中包含了我们再vivado中编写的设计、仿真的代码内容,点击进入:

进入文件后,看到如下界面,选择sources_1,这里面存储了design file:

 

 然后我们就可以找到名为decode3_8.v的文件,点击这个文件前面会出现一个蓝色的圆圈,代表我们选中了它,再选择OK,这个文件就成功加入了工程:

接下来,我们再新建立一个design file,稍后将在这个文件中引用译码器的内容,此时工程中会出现两个文件:

 

2.引用3-8译码器的实例:

3-8译码器的代码如下:

module decode3_8(
input a,
input b,
input c,
output reg[7:0] out
    );
//    reg [7:0] out;
    always@(*) begin //always@(a,b,c)
        case({a,b,c})//{a,b,c}实现位拼接
            3'b000:out = 8'b0000_0001;
            3'b001:out = 8'b0000_0010;
            3'b010:out = 8'b0000_0100;
            3'b011:out = 8'b0000_1000;
            3'b100:out = 8'b0001_0000;
            3'b101:out = 8'b0010_0000;
            3'b110:out = 8'b0100_0000;
            3'b111:out = 8'b1000_0000;
        endcase
    end

endmodule

 因此在引用时我们需要确定a,b,c和[7:0]out分别对应什么信号,根据之前的分析,LED[7:0]接收out[7:0]输出的8个信号,又因为要求LED灯以1Khz闪烁,因此译码器的输入信号a,b,c需要根据计数器counter的数值进行变化,也就是说当计数器counter为24999时,编码器的计数器decoder_cnt对输入信号进行+1操作,代码实现:

    reg [2:0]decoder_cnt;
    always@(posedge CLK or negedge Reset_n)
     if(!Reset_n)
     decoder_cnt<=0;
     else if(counter == 25000000-1)
     decoder_cnt<=decoder_cnt+1'd1;

此时,a对用计数器decoder_cnt的高位,c对应计数器decoder_cnt的低位。因此在实现流水灯的操作中,3-8译码器的输入信号为计数器的输出信号,输出信号与LED相连接,实例化代码为:

//例化
   decode3_8 decoder0(
   .a(decoder_cnt[2]),
   .b(decoder_cnt[1]),
   .c(decoder_cnt[0]),
   .out(LED)
   );     

此时需要注意将LED的数据形式由reg更改为wire类型,因为在这个方法下LED信号是由译码器的输出决定的,是由其他激励控制的信号,因此需要更改为wire数据类型。

整体代码为:

module led_flow_decoder(
    CLK,
    Reset_n,
    LED
    );
    
    input CLK;
    input Reset_n;
    output wire[7:0]LED;
    //因为此时的led被3-8译码器驱动,因此在代码中应为wire型数据
    //因为led_flow_decoder中的LED模块是被译码器驱动的
    //可以理解为定义的7个管脚作为引线起到传递译码器结果的作用
    reg [24:0] counter;

    //使用3-8译码器 LED视为3-8译码器的输出端
    //input:a b c, OUTPUT:LED0-LED7
    
    always@(posedge CLK or negedge Reset_n)
     if(!Reset_n)
        counter <= 0;
    else if(counter ==25000000-1)
        counter <= 0;
    else
        counter <= counter+1'd1;
              
//编码器输入信号每0.5ms变化一次  
    reg [2:0]decoder_cnt;
    always@(posedge CLK or negedge Reset_n)
     if(!Reset_n)
     decoder_cnt <= 0;
     else if(counter == 25000000-1)
     decoder_cnt <= decoder_cnt+1'd1;
     
//例化
   decode3_8 decoder0(
   .a(decoder_cnt[2]),
   .b(decoder_cnt[1]),
   .c(decoder_cnt[0]),
   .out(LED)
   );     
endmodule

  • 18
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: FPGA(现场可编程门阵列)是一种可使用户定制硬件功能的集成电路芯片。UART(通用异步收发传输器)是一种在计算机和外部设备之间传输数据的串行通信协议。 串口控制LED流水灯是一种利用FPGA来控制LED的方式。流水灯是一种 LED 条,其上的 LED 依次亮起或熄灭,给人一种流动的效果。 使用FPGA实现UART串口控制LED流水灯,首先需要通过FPGA的引脚连接到UART串口模块。然后,根据串口通信协议,通过FPGA的逻辑电路将串口数据传输到LED流水灯控制部分。 在流水灯控制部分,通过设置FPGA的逻辑电路,可以实现LED的闪烁、亮度调节、流动速度调节等功能。对于串口数据,FPGA可以解析其中的指令,根据指令来控制LED的状态和效果。 例如,当收到特定的指令时,FPGA可以使得LED流水灯按照设定的亮度和速度流动。当收到其他指令时,FPGA可以使得LED流水灯停止流动或改变流动方向。 通过FPGA UART串口控制LED流水灯,可以实现灵活、可定制的LED效果。用户可以通过发送不同的指令,改变LED的亮度、流动速度,与外设进行交互,实现更丰富的应用场景。这种方式充分利用了FPGA的可编程性和UART串口的通信能力,为LED控制提供了一种高效、可定制的解决方案。 ### 回答2: FPGA是一种可编程逻辑器件,可以根据设计人员的需求进行灵活的编程控制。UART是一种通用异步收发传输接口,用于串行数据的传输。而LED流水灯是一种LED串联连接的电路,可以实现光的流水效果。 要使用FPGA来控制LED流水灯,首先需要设计一个适当的电路。可以使用FPGA的数字逻辑单元和可编程的I/O引脚,将UART接口与LED的串口控制连接起来。 在FPGA中,通过编程的方式,配置UART的工作模式和传输参数,例如波特率、数据位数、校验等。接收到来自外部设备的串行数据后,通过逻辑单元进行解析和处理,将数据转换为相应的控制信号。 在LED流水灯方面,可以通过FPGA的I/O引脚输出控制信号,控制LED流水灯的亮灭。根据UART接收到的控制数据,FPGA可以实现不同的流水灯模式,例如顺序流水、倒序流水、闪烁等。 通过编程控制UART接收数据和LED流水灯的控制信号的传输和处理,就可以实现FPGA对UART串口控制LED流水灯的功能。 总之,FPGA是一种具有灵活性的电路设备,可以通过编程对UART串口进行控制,实现LED流水灯的控制效果。这种方法可以根据需求自定义串口传输和LED控制的参数和模式,具有很大的灵活性和可扩展性。 ### 回答3: FPGA是可重新配置的硬件,它可以实现各种数字电路设计的功能。UART是串行通信接口的一种标准,可用于在电路板之间进行数据传输。LED流水灯是一种LED效果LED在不同的时间间隔内依次点亮。 要实现FPGA UART串口控制LED流水灯,需要进行以下步骤: 1. 首先,在FPGA上创建或导入所需的UART通信模块。该模块应支持常用的串口通信协议,如UART通信协议的发送和接收功能。 2. 在FPGA上创建或导入LED控制模块。该模块应支持控制LED的亮灭,以及按照一定的顺序和时间间隔点亮LED的功能。 3. 在FPGA实现UART和LED控制模块之间的数据传输。通过UART通信模块,FPGA可以接收来自其他设备(如电脑或微控制器)发送的指令,以控制LED流水灯效果。 4. 设计指令协议,以使来自UART的指令能够正确地被LED控制模块识别和执行。指令可以设定光的点亮顺序、时间间隔以及其他特效。 5. 配置和连接FPGA的输入和输出引脚。UART模块应与外部设备(如电脑或其他微控制器)的串口通信引脚连接,而LED控制模块应与LED的控制引脚连接。 最终,当FPGA通过UART接收到来自外部设备的指令时,LED控制模块会根据指令的要求,按照预设的顺序和时间间隔点亮LED。这样就实现FPGA UART串口控制LED流水灯的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值