Verilog学习笔记 Day one 呼吸灯

        该文章是我学习正点原子的达芬奇之FPGA开发指南做的学习笔记,内容并非完全原创,用以记录本人的学习脚步。

实验一、呼吸灯

一、简介:

      呼吸灯采用PWM信号控制的方式,在固定的频率下,通过改变占空比来达到改变LED亮度的效果。PWM(Pulse Width Modulation):脉冲宽度调制,利用微控制器输出PWM信号,实现对模拟电路控制的一种非常有效的技术,在测量、通信、功率控制等领域得到广泛的应用。
 

二、设计思路:
      利用计数计时器产生固定周期的PWM信号,当PWM信号中的占空比为0%时,LED不亮;当PWM信号中的占空比为100%时,LED最亮。在PWM信号的占空比从0%变化到100%再变化到0%LED的由暗慢慢变亮再慢慢变暗,从而实现LED的“呼吸”效果。
 

                                                        PWM占空比示意图

三、本次实验端口与模块示意图


        周期信号计数器用于产生驱动LED的脉冲信号,本次实验的周期信号频率为1KHz,可以通
过调整后级逻辑在每个周期之后进行递增或者递减,最后通过周期计数器与占空比计数器
数值比较,可以实现占空比可调的PWM信号。

四、实验代码:

Design:

module breath_led(

    input sys_clk,
    input rest_clk_n,

    output reg led
);

reg[15:0]  preiod_cnt1;
reg[15:0]  duty_cnt;
reg        flag;



always @(posedge sys_clk or negedge rest_clk_n)begin
    if(!rest_clk_n)
        preiod_cnt1 <= 16'd0;
    else if(preiod_cnt1==16'd50000)
        preiod_cnt1 <= 16'd0;
    else
        preiod_cnt1 <= preiod_cnt1 + 1'b1;
end



always @(posedge sys_clk or negedge rest_clk_n)begin
    if(!rest_clk_n)begin
        duty_cnt <= 16'd0;
        flag <= 1'b0;
        end
    else begin
        if(preiod_cnt1==16'd50000)begin
            if(flag==0)begin
                if(duty_cnt==16'd50000)begin
                    flag<=1'b1;
                end
                else begin
                    duty_cnt <= duty_cnt + 16'd25;
                end
            end
            else begin
                if(duty_cnt==16'd0)begin
                    flag <= 1'b0;
                end
                else begin
                    duty_cnt <= duty_cnt - 16'd25;
                end 
            end        
        end            
    end
end

always @(posedge sys_clk)begin
    if(preiod_cnt1<=duty_cnt)begin
        led <= 1'b1;
    end
    else begin
        led <=1'b0;
    end
end


endmodule

Testbench:

`timescale 1ns/1ps

module tb_breath_led;

parameter  T = 20;

reg sys_clk;
reg rest_clk_n;

wire led;

initial  begin
     sys_clk            = 1'b0;
     rest_clk_n          = 1'b0;    
     #(T+1)  rest_clk_n  = 1'b1;     
end
always #(T/2) sys_clk = ~sys_clk;
 

breath_led u0_breath_led (
     .sys_clk     (sys_clk  ),
     .rest_clk_n   (rest_clk_n),
     .led         (led      )
);
 
endmodule

五、RTL电路以及仿真结果:

六、实验过程中遇到的问题(由于一开始忘记截图了,所以下文不会出现错误提示的截图):

1、在第一次编写代码时,由于将flag以及duty_cnt在多个always语句块中使用,导致编译
时出现了3个critical errors,导致最后behavior仿真时无法进行。最后只能重新编写,将
flag以及duty_cnt放在一个always语句块中赋值。在编写代码时,非常忌讳在多个语句块中
对一个变量赋值。
2、编写testbench时,由于design文件和testbench文件中的信号没有对上,导致无法仿真,
最后经过检查,发现了问题的所在并做修改,终于仿真成功。

七、上板验证:
由于手头没有Xlinx的FPGA开发板,无法进行上板验证。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的Verilog代码实现呼吸灯,呼吸周期可调。 ```verilog module breathing_LED( input clk, //时钟信号 input rst, //复位信号 input adjust_key, //调整周期的按键 output reg LED //LED输出 ); reg [31:0] counter = 0; //计数器,用于控制呼吸周期 reg [31:0] delay = 0; //延时计数器,用于控制灯亮度 parameter MAX_COUNTER = 32'd500000; //呼吸周期上限 parameter MIN_COUNTER = 32'd100000; //呼吸周期下限 always @(posedge clk or posedge rst) begin if (rst) begin //复位 counter <= 0; delay <= 0; LED <= 0; end else begin if (adjust_key) begin //调整周期 if (counter < MAX_COUNTER) begin counter <= counter + 1; end end else begin if (counter > MIN_COUNTER) begin counter <= counter - 1; end end if (delay < counter) begin //控制灯亮度 delay <= delay + 1; end else begin delay <= 0; LED <= ~LED; end end end endmodule ``` 在这个模块中,我们使用了一个计数器`counter`来控制呼吸周期的长度,另一个计数器`delay`用于控制每个呼吸周期内LED的亮度。当`delay`计数到`counter`时,LED会翻转状态,实现呼吸灯的效果。 同时,我们添加了一个调整周期的按键,当按下按键时,`counter`会增加,呼吸周期变长,LED的亮度变化速度变慢;当松开按键时,`counter`会减少,呼吸周期变短,LED的亮度变化速度变快。 请注意,这只是一个简单的实现方式,实际应用中可能需要更复杂的控制逻辑来实现更精细的效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值