前言
正文
用到的知识点:
- 用检测下降沿的方法进行按键消抖
- 通过生成三角波,进而实现可变占空比的PWM波
- 生成递增、递减的信号
设计文件
// 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