呼吸灯 fpga实现

目录

  • 原理
  • 实现

原理

呼吸灯:让led灯在固定时间由暗变亮,再由亮变暗,循环往复
原理:假定使led灯在2s内由暗变亮,再由亮变暗,这里采用的办法就是设置占空比,将2s分为100份,每份20ms,在每一个20ms到来,就将占空比加大或缩小1/100,达到呼吸的效果。

实现

代码
这里定义2个计数器
一个2ms计数器,一个2s计数器
2ms计数器周期为100_000次,1/1000就是100次,则每20ms到来,占空比preset_duty加或减100,定义一个flag,每2s翻转一次,由flag控制占空比的加减,在一个2ms内,当2ms计数器小于占空比时则令led灯亮,其余时间不亮,最后实现呼吸灯。

module led2(
    input 			clk		,
    input 			rst_n	,
    output 			led	    
);
//参数定义
parameter TIME_2S = 100_000_000;
parameter TIME_2MS = 100_000;
//信号定义
//2s
reg [25:0] cnt;
wire add_cnt;
wire end_cnt;

//20ms
reg [19:0] cnt0;
wire add_cnt0;
wire end_cnt0;



reg led_r;//寄存
reg [19:0] preset_duty;

reg flag;//2s变化标志
//2s计数
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)begin
            cnt <= 0;
        end
        else begin
            cnt <= cnt + 1;
        end
    end
end
assign add_cnt = end_cnt0;
assign end_cnt = add_cnt && (cnt == 1000 - 1);
//这是我开始写的逻辑 运行没错,上板子就有问题,会渐渐变亮 然后就常亮
//assign add_cnt = 1'b1;
//assign end_cnt = add_cnt && (cnt == TIME_2S - 1);
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt0 <= 0;
    end
    else if(add_cnt0)begin
        if(end_cnt0)begin
            cnt0 <= 0;
        end
        else begin
            cnt0 <= cnt0 + 1;
        end
    end
end
assign add_cnt0 = 1'b1;
assign end_cnt0 = add_cnt0 && (cnt0 == TIME_2MS - 1);

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        flag <= 1'b0;
    end
    else if(end_cnt)begin
        flag <= ~flag;
    end
end

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        led_r <= 1'b0;
    end
    else if(cnt0 <= preset_duty)begin
        led_r <= 1'b1;
    end
    else begin
        led_r <= 1'b0;
    end
end

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        preset_duty <= 0;
    end
    else if(flag)begin
        if(end_cnt0)begin
            preset_duty <= preset_duty - 20'd100;
        end
    end
    else if(!flag)begin
        if(end_cnt0)begin
            preset_duty <= preset_duty + 20'd100;
        end
    end
end

assign led = led_r;

endmodule 

总结:实际上呼吸灯比较简单,第一次遇见的话,思路很难,有了思路就比较容易实现
问题:如代码中,2s计数器以时钟周期数计时时,就会出现预料之外的现象,只有当2s计数器以20ms计数器为基准计时时才能出现正常的呼吸灯,具体原因没有找到,我估计时因为时序问题,可能是时序不满足,最后上板才会出现奇怪的现象。

你可能感兴趣的:(fpga)