21.呼吸灯拓展练习,控制四颗led以不同的频率“呼吸”

(1)Verilog代码:

module ex_breath_led(clk,reset_n,led_out);

    input clk;
    input reset_n;
    
    output [3:0]led_out;
    
    reg [5:0]cnt_1us;
    reg [9:0]cnt_1ms;
    reg [10:0]cnt_2ms;
    reg [11:0]cnt_4ms;
    reg [12:0]cnt_8ms;
    reg [9:0]cnt_1s;
    reg overturn;
    
    parameter MCNT_1us = 6'd49;
    parameter MCNT_1ms = 10'd999;
    parameter MCNT_2ms = 11'd1999;
    parameter MCNT_4ms = 12'd3999;
    parameter MCNT_8ms = 13'd7999;
    parameter MCNT_1s  = 10'd999;  
    
//1us计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_1us <= 6'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_1us <= 6'd0;
        else 
            cnt_1us <= cnt_1us + 6'd1;
            
//1ms计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_1ms <= 10'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_1ms <= 10'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_1ms <= cnt_1ms + 10'd1;
        else 
            cnt_1ms <= cnt_1ms;
            
//2、4、8ms计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_2ms <= 11'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_2ms == MCNT_2ms))
            cnt_2ms <= 11'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_2ms <= cnt_2ms + 11'd1;
        else 
            cnt_2ms <= cnt_2ms;
            
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_4ms <= 12'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_4ms == MCNT_4ms))
            cnt_4ms <= 12'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_4ms <= cnt_4ms + 12'd1;
        else 
            cnt_4ms <= cnt_4ms;
            
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_8ms <= 13'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_8ms == MCNT_8ms))
            cnt_8ms <= 13'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_8ms <= cnt_8ms + 13'd1;
        else 
            cnt_8ms <= cnt_8ms;
            
//1s计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_1s <= 10'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
            cnt_1s <= 10'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_1s <= cnt_1s + 10'd1;
        else 
            cnt_1s <= cnt_1s;
            
//翻转逻辑overturn信号
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            overturn <= 1'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
            overturn <= ~overturn;
        else 
            overturn <= overturn;

//led_out主程序设计
    assign led_out[0] = (((overturn == 1'd0)&&(cnt_1ms <= cnt_1s))||((overturn == 1'd1)&&(cnt_1ms <= MCNT_1s - cnt_1s)));
    assign led_out[1] = (((overturn == 1'd0)&&((cnt_2ms>>1) <= cnt_1s))||((overturn == 1'd1)&&((cnt_2ms>>1) <= MCNT_1s - cnt_1s)));
    assign led_out[2] = (((overturn == 1'd0)&&((cnt_4ms>>2) <= cnt_1s))||((overturn == 1'd1)&&((cnt_4ms>>2) <= MCNT_1s - cnt_1s)));
    assign led_out[3] = (((overturn == 1'd0)&&((cnt_8ms>>3) <= cnt_1s))||((overturn == 1'd1)&&((cnt_8ms>>3) <= MCNT_1s - cnt_1s)));

            
endmodule

(2)仿真文件代码:

`timescale 1ns / 1ps

module ex_breath_led_tb;

    reg clk;
    reg reset_n;
    
    wire [3:0]led_out;

    ex_breath_led ex_breath_led_inst(
        .clk(clk),
        .reset_n(reset_n),
        .led_out(led_out)
    );
    
    defparam ex_breath_led_inst.MCNT_1us = 4;
    defparam ex_breath_led_inst.MCNT_1ms = 99;
    defparam ex_breath_led_inst.MCNT_2ms = 199;
    defparam ex_breath_led_inst.MCNT_4ms = 399;
    defparam ex_breath_led_inst.MCNT_8ms = 799;
    defparam ex_breath_led_inst.MCNT_1s  = 99;

    initial clk = 1'd1;
    always #10 clk = ~clk;
    
    initial begin
        reset_n <= 1'd0;
        #15;
        reset_n <= 1'd1;
        #5_000_000;
        $stop;
    end

endmodule

(3)仿真波形:

(4)引脚绑定:

(5)上版验证后,发现该Verilog代码是错的,在肉眼看来,四个灯是在同频呼吸,因此修改代码为:

module ex_breath_led(clk,reset_n,led_out);

    input clk;
    input reset_n;
    
    output [3:0]led_out;
    
    reg [5:0]cnt_1us;
    reg [9:0]cnt_1ms;
    reg [9:0]cnt_1s;
    reg [10:0]cnt_2s;
    reg [11:0]cnt_4s;
    reg [12:0]cnt_8s;
    reg [3:0]overturn;
    
    parameter MCNT_1us = 6'd49;
    parameter MCNT_1ms = 10'd999;
    parameter MCNT_1s  = 10'd999;  
    parameter MCNT_2s  = 11'd1999; 
    parameter MCNT_4s  = 12'd3999; 
    parameter MCNT_8s  = 13'd7999; 
    
//1us计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_1us <= 6'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_1us <= 6'd0;
        else 
            cnt_1us <= cnt_1us + 6'd1;
            
//1ms计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_1ms <= 10'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_1ms <= 10'd0;
        else if(cnt_1us == MCNT_1us)
            cnt_1ms <= cnt_1ms + 10'd1;
        else 
            cnt_1ms <= cnt_1ms;
    
//1s计数器模块
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_1s <= 10'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
            cnt_1s <= 10'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_1s <= cnt_1s + 10'd1;
        else 
            cnt_1s <= cnt_1s;
            
//2、4、8秒计数器模块设计
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_2s <= 11'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_2s == MCNT_2s))
            cnt_2s <= 11'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_2s <= cnt_2s + 11'd1;
        else 
            cnt_2s <= cnt_2s; 
            
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_4s <= 12'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_4s == MCNT_4s))
            cnt_4s <= 12'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_4s <= cnt_4s + 12'd1;
        else 
            cnt_4s <= cnt_4s;

    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            cnt_8s <= 13'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_8s == MCNT_8s))
            cnt_8s <= 13'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
            cnt_8s <= cnt_8s + 13'd1;
        else 
            cnt_8s <= cnt_8s;          
            
//翻转逻辑overturn信号
    always@(posedge clk or negedge reset_n)
        if(!reset_n)
            overturn <= 4'd0;
        else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
            overturn <= overturn + 4'd1;
        else 
            overturn <= overturn;

//led_out主程序设计
    assign led_out[0] = (((overturn[0] == 1'd0)&&(cnt_1ms <= cnt_1s))||((overturn[0] == 1'd1)&&(cnt_1ms <= MCNT_1s - cnt_1s)));
    assign led_out[1] = (((overturn[1] == 1'd0)&&(cnt_1ms <= (cnt_2s >> 1)))||((overturn[1] == 1'd1)&&(cnt_1ms <= MCNT_1s - (cnt_2s >> 1))));
    assign led_out[2] = (((overturn[2] == 1'd0)&&(cnt_1ms <= (cnt_4s >> 2)))||((overturn[2] == 1'd1)&&(cnt_1ms <= MCNT_1s - (cnt_4s >> 2))));
    assign led_out[3] = (((overturn[3] == 1'd0)&&(cnt_1ms <= (cnt_8s >> 3)))||((overturn[3] == 1'd1)&&(cnt_1ms <= MCNT_1s - (cnt_8s >> 3))));

            
endmodule
`timescale 1ns / 1ps

module ex_breath_led_tb;

    reg clk;
    reg reset_n;
    
    wire [3:0]led_out;

    ex_breath_led ex_breath_led_inst(
        .clk(clk),
        .reset_n(reset_n),
        .led_out(led_out)
    );
    
    defparam ex_breath_led_inst.MCNT_1us = 4;
    defparam ex_breath_led_inst.MCNT_1ms = 9;
    defparam ex_breath_led_inst.MCNT_1s  = 9;
    defparam ex_breath_led_inst.MCNT_2s  = 19;
    defparam ex_breath_led_inst.MCNT_4s  = 39;
    defparam ex_breath_led_inst.MCNT_8s  = 79;

    initial clk = 1'd1;
    always #10 clk = ~clk;
    
    initial begin
        reset_n <= 1'd0;
        #15;
        reset_n <= 1'd1;
        #500_000;
        $stop;
    end

endmodule

仿真波形:

PS:实验现象正确,实现了预定目标,但我觉得可以以0.25s、0.5s、1s、2s的频率去呼吸,8s太长了,效果不佳。

相关推荐

  1. 02.3 基于Verilog控制多个LED不同频率闪烁

    2024-07-12 18:18:04       34 阅读
  2. 02.2 基于Verilog控制LED不同频率闪烁

    2024-07-12 18:18:04       31 阅读
  3. STM32自学☞PWM驱动LED呼吸

    2024-07-12 18:18:04       42 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 18:18:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 18:18:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 18:18:04       57 阅读
  4. Python语言-面向对象

    2024-07-12 18:18:04       68 阅读

热门阅读

  1. AI学习指南机器学习篇-聚类树的剪枝

    2024-07-12 18:18:04       17 阅读
  2. 华为的服务器创新之路

    2024-07-12 18:18:04       20 阅读
  3. 新版k8s拉取镜像失败问题

    2024-07-12 18:18:04       20 阅读
  4. 每日一题~p4447(贪心)

    2024-07-12 18:18:04       16 阅读
  5. windows server安装mino

    2024-07-12 18:18:04       21 阅读
  6. matlab实现pid控制液压系统

    2024-07-12 18:18:04       22 阅读