PWM全程为Pulse width Modulation(脉冲宽度调制)。本文将利用FPGA产生PWM,用来驱动LED电路。
1. 设计需求
定义一个定义脉冲宽度计数器cnt1/cnt2,分别用于产生三角波及调制波;
定义一个标志位flag_pwm,用于pwm增减方向,0加1减;
2. PWM代码编程
module LEDPWM(clk, rst_n, LED_PWM);
input clk; //clock
input rst_n; // rest
output LED_PWM; //led output
reg [2:0] cnt1; //triangle conter
reg [2:0] cnt2; //
reg flag_pwm;
parameter T = 4;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt1<=3'd0;
end
else
begin
if(cnt1== T-1)
cnt1<=1'b0;
else
cnt1<=cnt1+1'b1;
end
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt2<=3'd0;
flag_pwm<=1'b0;
end
else
begin
if(cnt1==T-1)
begin
if(!flag_pwm)
begin
if(cnt2==T-1)
flag_pwm<=1'b1;
else
cnt2<=cnt2+1'b1;
end
else
begin
if(cnt2==0)
flag_pwm<=1'b0;
else
cnt2<=cnt2-1'b1;
end
end
else
cnt2<=cnt2;
end
end
assign LED_PWM = (cnt1<cnt2)?1'b0:1'b1;
endmodule
3. 仿真例程
准备好一份正确的PWM代码后,我们开始testbench文件编写。
新建激励文件,点击"Sources"窗口顶部的"+"按钮, 打开添加源文件对话框. 选中"Add or create simulation sources", 点击"Next"继续。
点击"Create File"按钮, 在创建源文件对话框中, 输入文件名. 点击"OK", 点击"Finish"。
双击打开" LEDPWM.v "文件, 复制" LEDPWM.v "文件中的如下内容到"sim_LEDPWM.v"的模块中。
修改sim_ LEDPWM.v"文件中,输入信号修改为"reg"类型, 编写"initial"块对输入信号进行初始化, 为时钟信号编写激励, 将"timescale" 设置为"1ns / 1ps". 最终生成的代码如下所示:
`timescale 1ns / 1ps
module SIM_LEDPWM(
);
reg clk;
reg rst_n;
wire LED_PWM;
LEDPWM SIMTEST_LEDPWM(
.clk(clk),
.rst_n(rst_n),
.LED_PWM(LED_PWM)
);
initial begin
clk = 0;
rst_n = 0;
#100;
@(posedge clk);
rst_n = 1;
repeat(10) #1_000_000_000;
$finish;
end
always #10 clk = ~clk;
endmodule
从"Source"窗口中,选中激励文件"sim_LEDPWM.v", 右键选择菜单"Set as Top", 将激励文件设置为顶层。
点击左侧"Flow Navigator"工具窗口中的"Simulation" | "Run Simulation", 点击"Run Behavioral Simulation", 运行行为仿真。