verilogHDL实现pwm控制

用verilog实现PWM控制呼吸灯。呼吸周期2秒:1秒逐渐变亮,1秒逐渐变暗。系统时钟24MHz,pwm周期1ms,精度1us。

系统时钟为24MHZ,精度为1us,则对24MHZ时钟进行分频为1MHZ,1MHZ对应周期为1us。采用计数器计数,如果计数器从0到23产生一个脉冲表示为1us。

PWM周期为1ms。首先需要完成1ms控制信号,对1us所产生的脉冲信号计数,从0到9时为1ms,产生1ms脉冲信号

1s逐渐变亮 1s逐渐变暗。led周期为1s需要产生1s的周期信号,同上述方式一样,对1ms的信号计数。

基本原理

PWM的全称是脉冲宽度调制(Pulse-width modulation),是通过将有效的电信号分散成离散形式从而来降低电信号所传递的平均功率的一种方式;

所以根据面积等效法则,可以通过对改变脉冲的时间宽度,来等效的获得所需要合成的相应幅值和频率的波形;
具体如下图所示;
在这里插入图片描述
由上图可知,脉冲宽度调制使用一个脉冲宽度会被调制的方波,并且波型的平均值会有所变化。

在这里插入图片描述

具体实现方式

在本题目中要求PWM载波周期为1ms。而且led灯随着时间再逐渐亮和灭。因此需要PWM在1ms 占空比不断发生变化。1s为周期led发生亮和灭。因此灯的周期为1s。在1s内灯发生亮灭。

//state change   1s为周期控制灯亮和灭,
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		display_state <= 1'b0;
	else if(delay_1s)
		display_state <= ~display_state;
	else
		display_state <= display_state;
end

//pwm信号产生
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		pwm <= 1'b0;
	else 
		case(display_state)   //在1s周期内,控制PWM占空比变换
			1'b0: pwm <= (cnt2 < cnt3)?1'b1:1'b0;
			1'b1: pwm <= (cnt2 < cnt3)?1'b0:1'b1;
		endcase
end

verilog实现
`timescale 1ns / 1ps

module pwm(
	input clk,
	input rst_n,
	output led_out
    );
	 
parameter DELAY24 = 24;
parameter DELAY1000 = 10;

wire delay_1us;
wire delay_1ms;
wire delay_1s;

reg pwm;
reg [7:0] cnt1;
reg [10:0] cnt2;
reg [10:0] cnt3;

reg display_state;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		cnt1 <= 6'd0;
	else if(cnt1 == DELAY24 - 1'b1)
		cnt1 <= 6'd0;
	else
		cnt1 <= cnt1 + 1'b1;
end
assign delay_1us = (cnt1 == DELAY24 - 1'b1)?1'b1:1'b0;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		cnt2 <= 10'd0;
	else 
		if(delay_1us) begin
			if(cnt2 == DELAY1000 - 1'b1)
				cnt2 <= 10'd0;
			else
				cnt2 <= cnt2 + 1'b1;
		end
		else
			cnt2 <= cnt2;
		
end
assign delay_1ms = ((delay_1us == 1'b1)&&(cnt2 == DELAY1000 - 1'b1))?1'b1:1'b0;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		cnt3 <= 10'd0;
	else
		if(delay_1ms) begin
			if(cnt3 == DELAY1000 - 1'b1)
				cnt3 <= 10'd0;
			else
				cnt3 <= cnt3 + 1'b1;
		end
		else
			cnt3 <= cnt3;
end
assign delay_1s = ((delay_1ms == 1'b1)&&(cnt3 == DELAY1000 - 1'b1))?1'b1:1'b0;

//state change
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		display_state <= 1'b0;
	else if(delay_1s)
		display_state <= ~display_state;
	else
		display_state <= display_state;
end

//pwm信号产生
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) 
		pwm <= 1'b0;
	else 
		case(display_state)
			1'b0: pwm <= (cnt2 < cnt3)?1'b1:1'b0;
			1'b1: pwm <= (cnt2 < cnt3)?1'b0:1'b1;
		endcase
end

//位拼接使得输出8位led呼吸灯
assign led_out = pwm;
endmodule

  • 1
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值