FPGA呼吸灯PS PL

文章详细介绍了如何使用Verilog语言编写两种不同的呼吸灯效果。第一种方法通过切换占空比来模拟呼吸效果,第二种方法通过不同频率的计数器实现快慢闪烁。代码中包含了参数化设置,可以根据需要调整呼吸灯的周期和频率。
摘要由CSDN通过智能技术生成

去年测试分频器写法的玩具,呼吸得比较喘,所以不叫呼吸灯了,调整占空比区域可以转换成正常呼吸灯。

assign r_LED_pwn = (switch)?(LED_pwn_2):(LED_pwn);//控制亮灭

1.assign r_LED_pwn = (switch)?(LED_pwn_2):(LED_pwn);

        LED_pwn是led_cnt == div_cnt时反转的灯,

        led_cnt每个时钟周期增加一次的计数器;

        div_cnt则是每毫秒增加一次的计数器;

        随着时间的增加,反转速度会越来越慢。

2.LED_pwn_2是led_cnt_2 == (div_max - div_cnt)时反转的灯,

随着时间的增加,反转速度会越来越慢。

3.

module breatheled 
#(
    parameter time_period = 20,
    parameter div_max     = 1000_000,
    parameter one_route   = 2_000_000_000,
    parameter cnt_max     = ((one_route/time_period)/div_max),
    parameter div_width   = $clog2(div_max),
    parameter cnt_width   = $clog2(cnt_max)
)
(
    input   wire            Sys_clk,
    input   wire            Rst_n  ,
    output  wire            r_LED_pwn
);
            reg [cnt_width-1:0] Change_cnt ;
            reg                 Change_flag;
            reg [div_width-1:0] div_cnt    ;
            reg [div_width-1:0] led_cnt    ;
            reg [div_width-1:0] led_cnt_2  ;
            reg                 LED_pwn    ;
            reg                 LED_pwn_2  ;
            reg                 switch     ;

    assign r_LED_pwn = (switch)?(LED_pwn_2):(LED_pwn);
//switch
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                switch <= 1'b0;
            else if(div_cnt == div_max -1'b1)
                switch <= ~switch;
            else
                switch <= switch;
        end    
//change
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                Change_cnt <= 0;
            else if(Change_cnt == cnt_max -1'b1)
                Change_cnt <= 0;
            else
                Change_cnt <= Change_cnt + 1'b1;
        end
//flag
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                Change_flag <= 1'b0;
            else if(Change_cnt == cnt_max -1'b1)
                Change_flag <= 1'b1;
            else
                Change_flag <= 1'b0;
        end
//div_cnt
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                div_cnt <= 1'b0;
            else if(div_cnt == div_max -1'b1)
                div_cnt <= 1'b0;
            else if(Change_flag)
                div_cnt <= div_cnt + 1'b1;
        end
//led_cnt
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                led_cnt <= 1'b0;
            else if(led_cnt == div_cnt)
                led_cnt <= 1'b0;
            else
                led_cnt <= led_cnt + 1'b1;
        end
//led
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                LED_pwn <= 1'b0;
            else if(led_cnt == div_cnt)
                LED_pwn <= ~LED_pwn;
            else
                LED_pwn <=  LED_pwn ;
        end
//led_cnt_2
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                led_cnt_2 <= 1'b0;
            else if(led_cnt_2 == (div_max - div_cnt))
                led_cnt_2 <= 1'b0;
            else
                led_cnt_2 <= led_cnt_2 + 1'b1;
        end
//led_2
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                LED_pwn_2 <= 1'b0;
            else if(led_cnt_2 == (div_max - div_cnt))
                LED_pwn_2 <= ~LED_pwn_2;
            else
                LED_pwn_2 <=  LED_pwn_2 ;
        end
endmodule

 真呼吸灯

    assign r_LED_pwn = (pwn_flag == 0)?

                        ((pwn_cnt > div_1000_cnt)?1'b0:1'b1):

                        ((pwn_cnt > div_1000_cnt)?1'b1:1'b0);

div_1000_cnt 100ns计数器,100周期增加一次。

pwn_cnt 1000*100即100000周期增加一次

pwn_flag 1000*1000*100 100周期反转一次

pwn_flag = 0 随着时间增加,闪烁越来越快。

pwn_flag = 1随着时间增加,闪烁越来越慢。

module pwm_breathe_led 
#(
    parameter time_period = 20,
    parameter div_1000    = 1000, 
    parameter div_1000_100= 100 ,
    parameter div_width   = $clog2(div_1000),
    parameter cnt_width   = $clog2(div_1000_100)
)
(
    input   wire            Sys_clk,
    input   wire            Rst_n  ,
    output  wire            r_LED_pwn
);
            reg [div_width-1:0] div_1000_cnt;
            reg [div_width-1:0] pwn_cnt     ;
            reg [cnt_width-1:0] div_1000_100_cnt;
            reg                 pwn_flag;
    assign r_LED_pwn = (pwn_flag == 0)?
                        ((pwn_cnt > div_1000_cnt)?1'b0:1'b1):
                        ((pwn_cnt > div_1000_cnt)?1'b1:1'b0);
//cnt
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                div_1000_100_cnt <= 0;
            else if(div_1000_100_cnt == div_1000_100 - 1'b1)
                div_1000_100_cnt <= 0;
            else
                div_1000_100_cnt <= div_1000_100_cnt + 1'b1;
        end

    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                div_1000_cnt <= 0;
            else if((div_1000_cnt == div_1000 - 1'b1)
                  &&(div_1000_100_cnt == div_1000_100 - 1'b1))
                div_1000_cnt <= 0;
            else if(div_1000_100_cnt == div_1000_100 - 1'b1)
                div_1000_cnt <= div_1000_cnt + 1'b1;
            else
                div_1000_cnt <= div_1000_cnt;
        end

    always @(posedge Sys_clk or negedge Rst_n) 
    begin
        if(!Rst_n)
            pwn_cnt <= 0;
        else if((pwn_cnt == div_1000 - 1'b1)
              &&(div_1000_cnt == div_1000 - 1'b1)
              &&(div_1000_100_cnt == div_1000_100 - 1'b1))
            pwn_cnt <= 0;
        else if((div_1000_cnt == div_1000 - 1'b1)
              &&(div_1000_100_cnt == div_1000_100 - 1'b1))
            pwn_cnt <= pwn_cnt + 1'b1;
        else
            pwn_cnt <= pwn_cnt;
    end
//flag
    always @(posedge Sys_clk or negedge Rst_n) 
        begin
            if(!Rst_n)
                pwn_flag <= 1'b0;
            else if((pwn_cnt == div_1000 - 1'b1)
              &&(div_1000_cnt == div_1000 - 1'b1)
              &&(div_1000_100_cnt == div_1000_100 - 1'b1))
                pwn_flag <= ~pwn_flag;
            else
                pwn_flag <=  pwn_flag; 
        end
endmodule

PS呼吸灯 

/******************************************************************************
*
* Copyright (C) 2009 - 2014 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/

/*
 * helloworld.c: simple test application
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpiops.h"

#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
u32 LED0 = 54;
u32 LED1 = 55;
u32 Bottom = 56;

static XGpioPs GPIO_Decive;
static XGpioPs_Config *GPIO_Device_ConFig;

int GPIO_init_TEST(void);

int main()
{
    int LED = 0;
    int i;
    int j;
    int k = 0;
    init_platform();
    GPIO_init_TEST();
    while (1)
    {
    	switch(k)
    	{
    	case 0:
            for(i=0;i<500;i++){
            	for(j=0;j<500;j++){
            		usleep(1);
            		if(j>i){
            			XGpioPs_WritePin(&GPIO_Decive,LED0,0x00);}
            		else{
            			XGpioPs_WritePin(&GPIO_Decive,LED0,0x01);}}}
            		k = 1;
            		break;
    	case 1:
        for(i=0;i<500;i++){
        	for(j=0;j<500;j++){
        		usleep(1);
        		if(j>i){
        			XGpioPs_WritePin(&GPIO_Decive,LED0,0x01);}
        		else{
        			XGpioPs_WritePin(&GPIO_Decive,LED0,0x00);}}}
        			k = 0;
        			break;
    	}
      }
    cleanup_platform();
    return 0;
}

int GPIO_init_TEST(void)
{
    int Status;
    GPIO_Device_ConFig = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    if (GPIO_Device_ConFig == NULL) {
		return XST_FAILURE;
	}
    Status = XGpioPs_CfgInitialize(&GPIO_Decive,
                                    GPIO_Device_ConFig,
                                    GPIO_Device_ConFig->BaseAddr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
    //LED0
    XGpioPs_SetDirectionPin(&GPIO_Decive,
                            LED0,
                            0x01);
    XGpioPs_SetOutputEnablePin(&GPIO_Decive,
                            LED0,
                            0x01);
    //LED1
    XGpioPs_SetDirectionPin(&GPIO_Decive,
                            LED1,
                            0x01);   
    XGpioPs_SetOutputEnablePin(&GPIO_Decive,
                            LED1,
                            0x01); 
    //Bottom
    XGpioPs_SetDirectionPin(&GPIO_Decive,
                            Bottom,
                            0x0);      
    XGpioPs_SetOutputEnablePin(&GPIO_Decive,
                            Bottom,
                            0x01);    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA(Field-Programmable Gate Array)是一种可编程逻辑器件,用于设计和实现各种硬件系统,包括简单的LED灯控制。对于FPGA呼吸灯设计,其基本思路如下: 1. **硬件接口**: 首先,你需要确定使用哪个FPGA的输入/输出引脚来连接LED灯。通常,GPIO(通用输入输出)或类似的模块会被用来作为LED的驱动信号。 2. **时序设计**: 呼吸灯效果依赖于灯的闪烁频率和亮度变化。确定一个基础的周期,比如几个微妙或毫秒,然后通过计数器或者状态机来控制LED的开关。 3. **状态机或计数器**: 使用状态机的设计方法,定义LED的不同工作状态,如关闭、亮起、慢慢亮、慢慢暗等。计数器可以用来控制灯的闪烁速度,比如每增加一定次数就改变亮度或切换到下一个阶段。 4. **编程逻辑**: 在FPGA中,编写Verilog或VHDL代码来描述这个逻辑。这部分代码会定义如何根据状态机的状态来控制LED的驱动信号。 5. **配置和下载**: 使用FPGA开发工具(如Xilinx ISE或Vivado, Intel Quartus II等),将编写的逻辑配置到目标FPGA芯片上。 6. **测试**: 通过硬件调试器或JTAG接口验证设计是否按照预期工作,调整参数以达到理想的效果。 相关问题: 1. FPGA呼吸灯设计中,如何控制LED的亮度变化? 2. 在状态机设计中,有哪些常见的状态用于呼吸灯效果? 3. 如何通过编程逻辑实现灯的闪烁频率变化?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值