Advertisement

FPGA呼吸灯

阅读量:

FPGA呼吸灯

  • 关于呼吸灯:
  • 占空比:
  • 代码实现:

关于呼吸灯:

呼吸灯,就是像人们呼吸频率的一种led灯亮灭的一种表现形式。过程是慢慢变亮,然后变亮以后又慢慢变灭的一种过程。

占空比:

占空比是指在一个脉冲循环内,正脉冲序列的持续时间与脉冲总周期的比值。。占空比(Duty Ratio)在电信领域中有如下含义:例如:脉冲宽度1μs,信号周期4μs的脉冲序列占空比为0.25。

假设刚开始时占空比为1%,慢慢的占空比为2%、3%、4%……56%、57%……98%、99%、100%。

这就是LED灯亮的一个过程,我们可以让占空比为1%时,令LED灯亮,其余的部分让LED灭,慢慢的占空比越来越大,亮的部分也越来越多,这就是一个由灭到亮的一个过程。

假设刚开始时占空比为100%,慢慢的占空比为99%、98%、97%……64%、63%……2%、1%、0%。

这就是LED灯灭的一个过程,我们可以让占空比为99%时,令LED灯灭,其余的部分让LED亮,慢慢的占空比越来越小,灭的部分也越来越多,这就是一个由亮到灭的一个过程。

代码实现:

按键消抖模块key_debounce.v:

复制代码
    module key_debounce #(parameter KEY_W = 1,DELAY_TIME = 1000_000)(
    input                   clk     ,
    input                   rst_n   ,
    input   [KEY_W-1:0]     key_in  ,
    output  [KEY_W-1:0]     key_out
    
    );
    
    //信号定义
    
    reg     [19:0]      cnt     ;//延时计数器
    wire                add_cnt ;
    wire                end_cnt ;
    reg                 flag    ;
    
    reg     [KEY_W-1:0] key_r0  ;//同步寄存器
    reg     [KEY_W-1:0] key_r1  ;//打拍寄存器
    
    wire    [KEY_W-1:0] nedge   ;//检测下降沿
    
    reg     [KEY_W-1:0] key_flag;//按键按下标志
    
    //计数器
    
    always @(posedge clk or negedge rst_n)begin 
        if(~rst_n)begin
            cnt <= 0;
        end
        else if(add_cnt)begin 
            if(end_cnt) 
                cnt <= 0;
            else 
                cnt <= cnt + 1;
        end
    end 
    
    assign add_cnt = flag;
    assign end_cnt = add_cnt && cnt == DELAY_TIME-1;
    
    always @(posedge clk or negedge rst_n)begin 
        if(~rst_n)begin 
            flag <= 1'b0;
        end 
        else if(nedge != 0)begin 
            flag <= 1'b1;
        end 
        else if(end_cnt)begin 
            flag <= 1'b0;
        end    
        else  begin 
            flag <= flag;
        end 
    end     
    
    //同步 打拍
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            key_r0 <= {KEY_W{1'b1}};
            key_r1 <= {KEY_W{1'b1}};
        end
        else begin
            key_r0 <= key_in;//同步
            key_r1 <= key_r0;//打拍
        end
    end
    
    //assign nedge = key_r1 == 1'b1 && key_r0 == 1'b0;    //一位按键
    
    //assign nedge = {key_r1[0] == 1 && key_r0[0] == 0,key_r1[1] == 1 && key_r0[1] == 0};
    
    //assign nedge = {key_r1[0] && ~key_r0[0],key_r1[1] && ~key_r0[1]};
    
    assign nedge = key_r1 & ~key_r0;
    
    //输出寄存器key_flag
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            key_flag <= 0;
        end
        else begin
            key_flag <= end_cnt ?~key_r1:0; 
        end
    end
    
    assign key_out = key_flag;
    
    
    endmodule 
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

呼吸灯模块led_ctrl.v:

复制代码
    module led_ctrl (
    input           clk     ,
    input           rst_n   ,
    input   [1:0]   mod_sel ,
    output  [3:0]   led     
    );
       
    
    //时间参数定义
    
    parameter   TIME_100MS = 5_000,
                TIME_300MS = 15_000;
    //信号定义
    reg     [13:0]      cnt0        ;//基准定时 T = 100us/300us
    wire                add_cnt0    ;
    wire                end_cnt0    ;
    reg     [13:0]      X           ;
    
    reg     [6:0]       cnt1        ;//100个基准时间  计10ms或30ms
    wire                add_cnt1    ;
    wire                end_cnt1    ;
    
    reg     [6:0]       cnt2        ;//100个10ms、30ms  1S / 3S
    wire                add_cnt2    ;
    wire                end_cnt2    ;
    
    reg                 dir_flag    ;//方向寄存器
    reg                 mode_flag   ;//模式标志
    reg     [1:0]       sel_flag    ;//模式选择寄存
    
    reg     [3:0]       led_r       ;//输出寄存器
    
    //计数器
    always @(posedge clk or negedge rst_n) begin    //计数 T        10ms / 30ms
        if (rst_n==0) begin
            cnt0 <= 0; 
        end
        else if(add_cnt0) begin
            if(end_cnt0)
                cnt0 <= 0; 
            else
                cnt0 <= cnt0+1 ;
       end
    end
    assign add_cnt0 = 1'b1;
    assign end_cnt0 = add_cnt0  && cnt0 == X-1 ;
    
    always  @(*)begin
        if(mode_flag == 0)begin
            X = TIME_100MS;
        end
        else begin
            X = TIME_300MS;
        end
    end
    
    always @(posedge clk or negedge rst_n) begin    //计数 100 个 T  100us / 300us
        if (rst_n==0) begin     
            cnt1 <= 0; 
        end
        else if(add_cnt1) begin
            if(end_cnt1)
                cnt1 <= 0; 
            else
                cnt1 <= cnt1+1 ;
       end
    end
    assign add_cnt1 = end_cnt0;
    assign end_cnt1 = add_cnt1  && cnt1 == 100-1;
    
    always @(posedge clk or negedge rst_n) begin    //计数 100 个 100*T  1s / 3s
        if (rst_n==0) begin
            cnt2 <= 0; 
        end
        else if(add_cnt2) begin
            if(end_cnt2)
                cnt2 <= 0; 
            else
                cnt2 <= cnt2+1 ;
       end
    end
    assign add_cnt2 = end_cnt1;
    assign end_cnt2 = add_cnt2  && cnt2 == 100-1 ;
    
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            dir_flag <= 1'b0;
        end
        else if(end_cnt2)begin
            dir_flag <= ~dir_flag;
        end
    end
    
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            led_r <= 4'b0000;
        end
        else if(dir_flag == 1'b0 && cnt1 <= cnt2)begin
            led_r <= 4'b1111;
        end
        else if(dir_flag && cnt1 <= 99-cnt2)begin
            led_r <= 4'b1111;
        end
        else begin 
            led_r <= 4'b0000;
        end 
    end
    
    //mode_flag     一轮结束后才切换模式
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            mode_flag <= 1'b0;
        end
        else if(dir_flag && end_cnt2 && sel_flag[1])begin   
            mode_flag <= 1'b1;
        end
        else if(dir_flag && end_cnt2 && sel_flag[0])begin
            mode_flag <= 1'b0;
        end
    end
    
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            sel_flag <= 0;
        end
        else if(dir_flag && end_cnt2 && sel_flag != 0)begin
            sel_flag <= 0;
        end
        else if(mod_sel != 0)begin
            sel_flag <= mod_sel;
        end
    end
    
    
    assign led = led_r;
    
    endmodule 
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

顶层代码breath_led:

复制代码
    module breath_led(
    input           clk     ,
    input           rst_n   ,
    input   [1:0]   key_in  ,
    
    output  [3:0]   led_out 
    );
    
    //信号定义
    wire    [1:0]   key_flag    ;
    
    //模块例化
    
    //按键消抖
    
    key_debounce  #(.KEY_W(2))u_key(
    /*input           */.clk     (clk       ),
    /*input           */.rst_n   (rst_n     ),
    /*input   [1:0]   */.key_in  (key_in    ),
    /*output  [1:0]   */.key_out (key_flag  ) 
    );
    
    
    led_ctrl u_led(
    /*input           */.clk     (clk       ),
    /*input           */.rst_n   (rst_n     ),
    /*input   [1:0]   */.mod_sel (key_flag  ),
    /*output  [3:0]   */.led     (led_out   )
    );
    
    
    endmodule 
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

仿真代码breath_led_tb.v:

复制代码
    `timescale 1 ns/1 ns
    
    module breath_led_tb();
    
    reg             clk   ; 
    reg             rst_n ; 
    reg     [1:0]   key_in; 
    
    wire    [3:0]   led_out ;
    
    
    parameter CYCLE    = 20;
    
    parameter RST_TIME = 3 ;
    
     breath_led u_breath_led(
    /*input           */.clk     (clk    ),
    /*input           */.rst_n   (rst_n  ),
    /*input   [1:0]   */.key_in  (key_in ),
    /*output  [3:0]   */.led_out (led_out)
    );
    
    defparam u_breath_led.u_key.DELAY_TIME = 10,
             u_breath_led.u_led.TIME_100MS = 2,
             u_breath_led.u_led.TIME_300MS = 6;
    
    
    initial begin
        clk = 1;
        forever
        #(CYCLE/2)
        clk=~clk;
    end
    
    initial begin
        rst_n = 1;
        #2;
        rst_n = 0;
        #(CYCLE*RST_TIME);
        rst_n = 1;
    end
    
    initial begin
        #1;
        #(10*CYCLE);
        
        key_in = 2'b11;
    
        #(20*CYCLE);        //模式1
        key_in = 2'b01;
        #(20*CYCLE);
        key_in = 2'b11;
    
        #(20000*CYCLE);      //模式0
        key_in = 2'b10;
        #(20*CYCLE);
        key_in = 2'b11;
    
         #(20000*CYCLE);
         $stop;
    
    end
    
    
    
    
    
    endmodule
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI写代码

仿真结果:
在这里插入图片描述

全部评论 (0)

还没有任何评论哟~