FPGA Verilog简单的LED呼吸灯,作为新板子的亮灯程序。
这个LED在输出高电平时点亮。
主要的想法:
- CMP_MAX限制最大占空比,因为发现在占空比较大时,改变占空比时,亮度变化不大,效果不明显。
- PWM_CNT_MAX设置PWM频率
- DUTY_CNT_MAX设置占空比变化的频率
- CMP_STEP设置每次占空比变化的步长,通过改变CMP_STEP来改变呼吸灯的频率
- flag_duty_increase指示占空比变化的方向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| module pwm_led
(
input clk,
input reset_n,
output led
);
parameter PWM_CNT_MAX = 32'd50_000; //PWM frequency 50M/5e4=1kHz
parameter CMP_MAX = 32'd25_000; //max duty ratio CMP_MAX/PWM_CNT_MAX=0.5
parameter DUTY_CNT_MAX = 32'd500_000;
//duty step change frequency 50M/DUTY_CNT_MAX=100Hz, every 0.01s
parameter CMP_STEP = 32'd500; //duty step length
//estimated cycle:
//=(DUTY_CNT_MAX/50M)*(CMP_MAX/DUTY_STEP)*2
//=0.01s*50*2=1s
reg [31:0] pwm_cnt;
reg [31:0] duty_cnt;
reg [31:0] cmp;
reg flag_duty_increase;
always @(posedge clk)
begin
if(!reset_n)
pwm_cnt <= 0;
else if(pwm_cnt >= PWM_CNT_MAX-1)
pwm_cnt <= 32'd0;
else
pwm_cnt <= pwm_cnt + 1;
end
always @(posedge clk)
begin
if(!reset_n)
duty_cnt <= 0;
else if(duty_cnt >= DUTY_CNT_MAX-1)
duty_cnt <= 32'd0;
else
duty_cnt <= duty_cnt + 1;
end
always @(posedge clk)
begin
if(!reset_n) begin
flag_duty_increase <= 0;
cmp <= 0;
end
else if(duty_cnt == DUTY_CNT_MAX-1)
if(flag_duty_increase) //increase cmp
if(cmp >= CMP_MAX)
flag_duty_increase <= 0;
else
cmp <= cmp + CMP_STEP;
else //flag_duty_increase == 0, decrease cmp
if(cmp < CMP_STEP)
flag_duty_increase <= 1;
else
cmp <= cmp - CMP_STEP;
end
assign led = (cmp > pwm_cnt); //duty ratio = cmp/PWM_CNT_MAX
endmodule
|
仿真不做了(亮灯程序,能用就行),上板实测效果:
