脉冲宽度调制(pulse width modelation)简称PWM,利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
在本章的应用中可以认为PWM就是一种方波。如图2-7所示。
图2-7 PWM波形图
一个周期为10ms,高电平为6ms,低电平时间为4ms的PWM,其占空比(高电平时间占整个周期的比例)为60%。
明德扬的FPGA开发板共有8个LED灯。产生8个管脚的PWM图,如图2-8所示。每个管脚对应的占空比分别为:80%、70%、60%、50%、40%、30%、20%和10%。系统工作时钟100MHz。
图2-8 各个LED等对应的PWM波形
FPGA通过8个管脚来分别控制8个LED灯,管脚值为0,对应的LED灯亮,管脚值为1,对应的LED灯灭(低亮高灭)。如果管脚不停地变化,则LED灯会闪烁;如果这种高低变化非常快,由于人的视觉暂留现象,LED就会出现不同的亮度。
基于这个原则,我们也可以通过产生PWM波形,来控制LED灯的亮度。
1. 明确功能
首先确定模块信号列表,如表2.2。
表2.2信号列表
信号名 |
I/O |
位宽 |
说明 |
clk |
I |
1 |
系统工作时钟100MHz。 |
rst_n |
I |
1 |
系统复位信号,低电平有效。 |
led |
O |
8 |
LED输出信号 |
产生8个脉冲,每个脉冲周期为10s对应的占空比分别为:80%、70%、60%、50%、40%、30%、20%和10%。
2. 功能波形
led所有信号的变化都是相似的,这里以led[0]为例。见图2-9。
图2-9 led[0]信号变化图
3. 计数结构
因为每个脉冲的高低电平持续时间都是以1s为单位的,所以引入两个计数器,计数器cnt_1s计数1s,计数器cnt_10s计数每个脉冲高低电平分别持续的时间。具体计数情况如图2-10所示:
图2-10 计数结构图
4. 加一结束条件
cnt_1s的加1条件:计数器一直在计数,即:assign add_cnt_1s=1;
cnt_1s的结束条件:加一条件下计数到100_000_000-1;
cnt_10s的加1条件:cnt_1s的结束时刻;
cnt_10s的结束条件:加一条件下计数到10-1;
5. 定义特殊点
图2-11有几个特殊点,需要我们记住。
图2-11 特殊定义点图
cnt1s的结束条件:cnt_1s==100_000_000-1,定为end_cnt_1s。
cnt10s的结束条件:cnt_10s==10-1,定为end_cnt_10s。
led所有位的新号变化都是相似的,所以我们以led[0]为例定义特殊点,
led[0]变高的条件:cnt_10s==1-1,定为led0_off。
led[0]变低的条件:cnt_10s==10-1,定为led_on。
6. 完整性检查
(1)计数器cnt_1s cnt_1s的初值:0; cnt_1s的加1条件:assign add_cnt_1s=1; cnt_1s的结束条件: assign end_cnt_1s=add_cnt1s&&cnt_1s ==100_000_000 - 1 |
(6)led[3] led[3]由0变1:led3_off led[3]由1变0:led_on |
(2)计数器cnt_10s cnt_10s初值:0; cnt_10s的加1条件: assign add_cnt_10s=end_cnt1s; cnt_10s的结束条件: assign end_cnt_10s=add_cnt10s && cnt_10s==10 - 1 |
(7)led[4] led[4]由0变1:led4_off led[4]由1变0:led_on |
(3)led[0] led[0]由0变1:led0_off led[0]由1变0:led_on |
(8)led[5] led[5]由0变1:led5_off led[5]由1变0:led_on |
(4)led[1] led[1]由0变1:led1_off led[1]由1变0:led_on |
(9)led[6] led[6]由0变1:led6_off led[6]由1变0:led_on |
(5)led[2] led[2]由0变1:led2_off led[2]由1变0:led_on |
(10)led[7] led[7]由0变1:led7_off led[7]由1变0:led_on |
7. 计数器代码
2
3 always @(posedgeclk or negedgerst_n)begin
4 if(rst_n==1'b0)begin
5 cnt_1s <= 0;
6 end
7 else if(add_cnt_1s)begin
8 if(end_cnt_1s)
9 cnt_1s <= 0;
10 else
11 cnt_1s <= cnt_1s + 1;
12 end
13 end
14 assign add_cnt_1s = 1'b1;
15 assign end_cnt_1s = add_cnt_1s && cnt_1s==TIME_1S-1;
16
17 always @(posedgeclk or negedgerst_n)begin
18 if(rst_n==1'b0)begin
19 cnt_10s <= 0;
20 end
21 else if(add_cnt_10s)begin
22 if(end_cnt_10s)
23 cnt_10s <= 0;
24 else
25 cnt_10s <= cnt_10s + 1;
26 end
27 end
28 assign add_cnt_10s = end_cnt_1s;
29 assign end_cnt_10s = add_cnt_10s && cnt_10s==10-1;
30
8.完整代码
2 always @(posedgeclk or negedgerst_n)begin
3 if(rst_n==1'b0)begin
4 led[0] <= 0;
5 end
6 else if(led_on)begin
7 led[0] <= 0;
8 end
9 else if(led0_off)begin
10 led[0] <= 1;
11 end
12 end
13 assign led0_off = add_cnt_10s && cnt_10s==1-1;
14 assign led_on = add_cnt_10s && cnt_10s==10-1;
15
16 //按照第六步第4点,写出len[1]的代码
17 always @(posedgeclk or negedgerst_n)begin
18 if(rst_n==1'b0)begin
19 led[1] <= 0;
20 end
21 else if(led_on)begin
22 led[1] <= 0;
23 end
24 else if(led1_off)begin
25 led[1] <= 1;
26 end
27 end
28 assign led1_off = add_cnt_10s && cnt_10s==2-1;
29
30 //按照第六步第5点,写出len[2]的代码
31 always @(posedgeclk or negedgerst_n)begin
32 if(rst_n==1'b0)begin
33 led[2] <= 0;
34 end
35 else if(led_on)begin
36 led[2] <= 0;
37 end
38 else if(led2_off)begin
39 led[2] <= 1;
40 end
41 end
42 assign led2_off = add_cnt_10s && cnt_10s==3-1;
43
44 //按照第六步第6点,写出len[3]的代码
45 always @(posedgeclk or negedgerst_n)begin
46 if(rst_n==1'b0)begin
47 led[3] <= 0;
48 end
49 else if(led_on)begin
50 led[3] <= 0;
51 end
52 else if(led3_off)begin
53 led[3] <= 1;
54 end
55 end
56 assign led3_off = add_cnt_10s && cnt_10s==4-1;
57
58 //按照第六步第7点,写出len[4]的代码
59 always @(posedgeclk or negedgerst_n)begin
60 if(rst_n==1'b0)begin
61 led[4] <= 0;
62 end
63 else if(led_on)begin
64 led[4] <= 0;
65 end
66 else if(led4_off)begin
67 led[4] <= 1;
68 end
69 end
70 assign led4_off = add_cnt_10s && cnt_10s==5-1;
71
72 //按照第六步第8点,写出len[5]的代码
73 always @(posedgeclk or negedgerst_n)begin
74 if(rst_n==1'b0)begin
75 led[5] <= 0;
76 end
77 else if(led_on)begin
78 led[5] <= 0;
79 end
80 else if(led5_off)begin
81 led[5] <= 1;
82 end
83 end
84 assign led5_off = add_cnt_10s && cnt_10s==6-1;
85
86 //按照第六步第9点,写出len[6]的代码
87 always @(posedgeclk or negedgerst_n)begin
88 if(rst_n==1'b0)begin
89 led[6] <= 0;
90 end
91 else if(led_on)begin
92 led[6] <= 0;
93 end
94 else if(led6_off)begin
95 led[6] <= 1;
96 end
97 end
98 assign led6_off = add_cnt_10s && cnt_10s==7-1;
99
100 //按照第六步第10点,写出len[7]的代码
101 always @(posedgeclk or negedgerst_n)begin
102 if(rst_n==1'b0)begin
103 led[7] <= 0;
104 end
105 else if(led_on)begin
106 led[7] <= 0;
107 end
108 else if(led7_off)begin
109 led[7] <= 1;
110 end
111 end
112 assign led7_off = add_cnt_10s && cnt_10s==8-1;
113
技术交流QQ群:544453837
更多FPGA技术资讯:明德扬科教
了解>>至简设计法