FPGA:使用PWM波控制LED亮度

本文介绍了一种FPGA实现的PWM控制器,通过检测按键下降沿进行消抖,并能生成可变占空比的PWM波。设计中包含了亮度调节功能,通过4次按键调节亮度,亮度值依次减小。同时,该设计能够生成递增和递减的信号,实现亮度的平滑变化。
摘要由CSDN通过智能技术生成

前言

正文

用到的知识点:

  1. 用检测下降沿的方法进行按键消抖
  2. 通过生成三角波,进而实现可变占空比的PWM波
  3. 生成递增、递减的信号

设计文件

// 4次调节亮度
// 按下第4次后,亮度依次减小
module pwm_led_02(
	input 				    clk,
	input 				    rst_n,
	input 				    key,
	
	output reg 				led
);

parameter CNT_MAX = 12'd1249;
parameter PWM_2   = 12'd249;
parameter PWM_4   = 12'd499;
parameter PWM_6   = 12'd749;
parameter PWM_8   = 12'd999;

reg [11:0]PWM_type;
wire key_nege;//按键下降沿

reg key_reg1;
reg key_reg2;

reg cnt_up;
reg cnt_down;

reg key_up;
reg key_down;

reg [2:0]  cnt_key;
reg [11:0] cnt_1249;
//====================================
//检测按键下降沿
always@(posedge clk or negedge rst_n)begin
	if(!rst_n )begin
		key_reg1 <= 1'd0;
		key_reg2 <= 1'd0;
	end
	else begin
		key_reg1 <= key;
		key_reg2 <= key_reg1;		
	end	
end

assign key_nege = key_reg2 & (~key_reg1);
//====================================


//====================================
// 用50MHZ时钟生成20KHZ的PWM
//生成三角波

always@(posedge clk or negedge rst_n)begin
	if(!rst_n )
		cnt_1249 <= 12'd0;
	else if(key_nege)
		cnt_1249 <= 12'd0;
	else if(cnt_up)
		cnt_1249 <= cnt_1249 + 1;
	else if(cnt_down)
		cnt_1249 <= cnt_1249 - 1;
	else
		cnt_1249 <= cnt_1249;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n )begin
		cnt_up   <= 1'd0;
		cnt_down <= 1'd0;
	end
	else if(cnt_1249 == CNT_MAX-1)begin
		cnt_up   <= 1'd0;
		cnt_down <= 1'd1;
	end
	else if(cnt_1249 == 0)begin
		cnt_up   <= 1'd1;
		cnt_down <= 1'd0;	
	end
	else begin
		cnt_up   <= cnt_up;
		cnt_down <= cnt_down;
	end
end
//====================================
// 按键计数

always@(posedge clk or negedge rst_n)begin
	if(!rst_n )
		cnt_key <= 3'd0;
    else if(key_nege)begin
        if(key_up)
            cnt_key <= cnt_key + 1;
        else if(key_down)//cnt_key[0] && 
            cnt_key <= cnt_key - 1;
    end
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n )begin
		key_up   <= 1'd0;
		key_down <= 1'd0;
	end
	else if(cnt_key == 4)begin
		key_up   <= 1'd0;
		key_down <= 1'd1;
	end
	else if(cnt_key == 0)begin
		key_up   <= 1'd1;
		key_down <= 1'd0;	
	end
	else begin
		key_up   <= key_up;
		key_down <= key_down;
	end
end

always@(*)begin
	case(cnt_key)
		3'd1:begin
            if(key_up)begin
                PWM_type = PWM_2;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
            else if(key_down)begin
                PWM_type = PWM_2;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
        end
		3'd2:begin
            if(key_up)begin
                PWM_type = PWM_4;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
            else if(key_down)begin
                PWM_type = PWM_4;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
			end			
		3'd3:begin
            if(key_up)begin
                PWM_type = PWM_6;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
            else if(key_down)begin
                PWM_type = PWM_6;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
			end		
		3'd4:begin
            if(key_up)begin
                PWM_type = PWM_8;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
            else if(key_down)begin
                PWM_type = PWM_8;
                if(cnt_1249 <= PWM_type)
                    led = 1'd0;
                else if(cnt_1249 > PWM_type )
                    led = 1'd1;
            end
			end		
	default: begin
			PWM_type = CNT_MAX;
			led = 1'd1;
		end
	endcase

end
endmodule 


测试文件

`timescale 1ns/1ns

module tb_pwm (
    
);
reg clk,rst_n,key;
wire led;

initial begin
    clk = 1'd0;
    rst_n = 1'd0;
    key = 1'd1;

    # 100
    rst_n = 1'd1;

    # 30000 
    key = 1'd0;
    #20000
    key = 1'd1;
    # 20000
    key = 1'd0;
    #5000
    key = 1'd1;
    # 10000
    key = 1'd0;
    # 30000
    key = 1'd1;
    # 20000
    key = 1'd0;
    #5000
    key = 1'd1;
    # 10000
    key = 1'd0;
    # 30000
    key = 1'd1;
    # 30000 
    key = 1'd0;
    #20000
    key = 1'd1;
    # 20000
    key = 1'd0;
    #5000
    key = 1'd1;
    # 10000
    key = 1'd0;
    # 30000
    key = 1'd1;
    # 20000
    key = 1'd0;
    #5000
    key = 1'd1;
    # 10000
    key = 1'd0;
    # 30000
    key = 1'd1;
end
always #10 clk = ~ clk;
pwm_led_02 pwm_led_inst(
	.clk(clk),
	.rst_n(rst_n),
	.key(key),
	
	.led(led)
);


endmodule

上板测试

请添加图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值