利用PWM原理实现调光灯
一、PWM原理
PWM(Pulse Width Modulation)即脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的一种技术。PWM是一种对模拟信号电平进行数字编码的方法。通过使用高分辨率计数器,对方波的占空比进行调制,从而对一个具体模拟信号的电平进行编码。
二、设计思想
本实验利用pynq-z2平台,要求对led灯实现4挡亮度,同时4个led灯要顺序流转起来。led灯只有高低电平2个挡位,如何实现led的4挡亮度呢?可以想到利用pwm技术,对信号周期的占空比进行控制,从而对电平编码,实现4挡亮度控制。
假设周期为1ms,则4挡亮度占空比分别为250us、500us、750us和1000us。定义一个2位计数器cnt1ms对4种状态进行编码。
此时已经实现led灯的4挡亮度。那么下面如何实现led灯的流转呢。定义一个每1s的计数器cnt,每过1秒led灯的状态变化一次,4s是一个周期。4个led灯的状态表如下所示。
根据状态表,对每个led灯的每个cnt时刻亮度挡位状态进行一一对应,即可实现led灯的流转。模块示意图如下所示。
三、代码实现
设计代码如下所示。
modulepwm(inputsclk,inputs_rst,outputreg [ 3:0]led);localparamDELAY_250US='d31249;localparamDELAY_1MS='d3;localparamDELAY_1S='d999;reg[ 14:0]cnt_250us; reg[ 1:0]cnt_1ms;reg [ 9:0] cnt_1s ; //1s的计数器reg[ 1:0]cnt;//每1s的计数器,共4salways@(posedge sclk or posedge s_rst) begin //250us 计数器if(s_rst == 1'b1) cnt_250us <='d0;else if(cnt_250us == DELAY_250US)cnt_250us <='d0;elsecnt_250us <=cnt_250us + 1'b1;endalways@(posedge sclk or posedge s_rst) begin //1ms 计数器if(s_rst == 1'b1) cnt_1ms <='d0;else if(cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt_1ms <='d0;else if(cnt_250us == DELAY_250US)cnt_1ms <=cnt_1ms + 1'b1;endalways @(posedge sclk or posedge s_rst)//1s 计数器beginif(s_rst == 1'b1)cnt_1s <= 10'd0 ;else if(cnt_1s == DELAY_1S && cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt_1s <= 10'd0 ;else if(cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt_1s <= cnt_1s + 1'b1 ;end//计数器cntalways @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)cnt <= 2'd0 ;else if(cnt == 2'd3 && cnt_1s == DELAY_1S && cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt <= 2'd0 ;else if(cnt_1s == DELAY_1S && cnt_1ms == DELAY_1MS && cnt_250us == DELAY_250US)cnt <= cnt + 1'b1 ;end//led0always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[0] <= 1'b0 ;else if(cnt == 0 ) //cnt == 0 时,亮度1挡beginif (cnt_1ms == 2'b00)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelse if(cnt == 1)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelse if(cnt == 2)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelse if(cnt == 3)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[0] <= 1'b1 ;elseled[0] <= 1'b0 ;endelseled[0] <= 1'b0 ;end//led1always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[1] <= 1'b0 ;else if(cnt == 0)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelse if(cnt == 1)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelse if(cnt == 2)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelse if(cnt == 3) beginif (cnt_1ms == 2'b00)led[1] <= 1'b1 ;elseled[1] <= 1'b0 ;endelseled[1] <= 1'b0 ;end//led2always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[2] <= 1'b0 ;else if(cnt == 0)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelse if(cnt == 1)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelse if(cnt == 2) beginif (cnt_1ms == 2'b00)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelse if(cnt == 3)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[2] <= 1'b1 ;elseled[2] <= 1'b0 ;endelseled[2] <= 1'b0 ;end//led3always @(posedge sclk or posedge s_rst)beginif(s_rst == 1'b1)led[3] <= 1'b0 ;else if(cnt == 0)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10 || cnt_1ms == 2'b11)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelse if(cnt == 1) beginif (cnt_1ms == 2'b00)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelse if(cnt == 2)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelse if(cnt == 3)beginif (cnt_1ms == 2'b00 || cnt_1ms == 2'b01 ||cnt_1ms == 2'b10)led[3] <= 1'b1 ;elseled[3] <= 1'b0 ;endelseled[3] <= 1'b0 ;endendmodule
测试代码如下所示。
`timescale1ns/1nsmodule tb_pwm;regsclk;regs_rst;wire [3:0] led;initial beginsclk =1;s_rst <= 1 ;#100s_rst <= 0 ;endalways #4sclk = ~sclk ;pwmpwm_inst(.sclk(sclk),.s_rst (s_rst ),reset, active low.led(led));endmodule
四、实验结果
利用testbench仿真的结果如下所示:
实验结果如下所示: