需求:
基于任务(task)的PWM设计仿真验证
需求分析:
1,需求实现可配置PWM输出(频率,占空比)
2,输入,输出端口
input i_clk, //clk = 50Mhz
input i_rst_n,
input i_en,
output reg o_vld,//有效信号
output reg o_pwm
3,定义计数寄存器reg [7:0]cnt;
用于计数,0~ 分频最大值,
o_pwm 在计数到0~正数占空比来临前置高,其他时间置低
4,o_vld 在最高计数来临时,置高,其他时间置低
实现方案1,使用参数传递方式,将最大计数值和高脉冲占空比计数值通过 参数传递出去
vlg_design
/
/*
实现pwm 350kHZ,占空比50%的输出
*/
/
`timescale 1ns/1ps
module vlg_design #(
parameter CNT_MAX = 50_000_000/350_000 - 1 , //350Khz计数值,
parameter CNT_MAX_PERCENT = 50_000_000/350_000*0.5 -1 //50%占空比
)
(
input i_clk, //clk = 50Mhz
input i_rst_n,
input i_en,
output reg o_vld, //有效信号
output reg o_pwm
);
reg [7:0]cnt;
always@(posedge i_clk) begin
if(!i_rst_n) cnt <= 'b0;
else if(!i_en) cnt <= 'b0;
else if(cnt < CNT_MAX) cnt <= cnt+1'b1;
else cnt <= 'b0;
end
always@(posedge i_clk) begin
if(!i_rst_n) o_pwm <= 'b0;
else if(!i_en) o_pwm <= 'b0;
else if(cnt <= CNT_MAX_PERCENT) o_pwm <= 1'b1;
else o_pwm <= 'b0;
end
always@(posedge i_clk) begin
if(!i_rst_n) o_vld <= 'b0;
else if(!i_en) o_vld <= 'b0;
else if(cnt == CNT_MAX) o_vld <= 1'b1;
else o_vld <= 'b0;
end
endmodule
testbench_top
`timescale 1ns/1ps
module testbench_top();
//参数定义
`define CLK_PERIORD 20 //50Mhz
localparam CNT_500KHZ_MAX = 50_000_000/500_000 - 1 ; //350Khz计数值
localparam CNT_500KHZ_MAX_10_PERCENT = 50_000_000/500_000*0.1 -1 ;//50%占空比
//接口申明
reg i_clk;
reg i_rst_n;
reg i_en;
wire o_vld; //有效信号
wire o_pwm;
vlg_design #(
.CNT_MAX (CNT_500KHZ_MAX),
.CNT_MAX_PERCENT(CNT_500KHZ_MAX_10_PERCENT)
)
vlg_design_inst(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.i_en(i_en),
.o_vld(o_vld),
.o_pwm(o_pwm)
);
initial begin
i_en <= 0;
i_clk <= 0;
i_rst_n <= 0;
#200;
i_rst_n <= 1;
end
always #(`CLK_PERIORD/2) i_clk = ~i_clk;
//产生激励
initial begin
@(posedge i_clk);
@(posedge i_rst_n);
i_en <= 1;
@(posedge i_clk);
#5_000;
i_en <= 0;
$stop;
end
endmodule
实现方案2,将配置分频计数的参数和占空比高脉冲计数参数,配置位输入port,在测试文件中,使用task任务的方式对其赋不同的值,实现参数配置生成不同的PWM信号
vlg_design
/
/*
实现pwm 350kHZ,占空比50%的输出
*/
/
`timescale 1ns/1ps
module vlg_design (
input [7:0] i_cnt_max,
input [7:0] i_cnt_max_percent,
input i_clk, //clk = 50Mhz
input i_rst_n,
input i_en,
output reg o_vld, //有效信号
output reg o_pwm
);
reg [7:0]cnt;
always@(posedge i_clk) begin
if(!i_rst_n) cnt <= 'b0;
else if(!i_en) cnt <= 'b0;
else if(cnt < i_cnt_max) cnt <= cnt+1'b1;
else cnt <= 'b0;
end
always@(posedge i_clk) begin
if(!i_rst_n) o_pwm <= 'b0;
else if(!i_en) o_pwm <= 'b0;
else if(cnt <= i_cnt_max_percent) o_pwm <= 1'b1;
else o_pwm <= 'b0;
end
always@(posedge i_clk) begin
if(!i_rst_n) o_vld <= 'b0;
else if(!i_en) o_vld <= 'b0;
else if(cnt == i_cnt_max) o_vld <= 1'b1;
else o_vld <= 'b0;
end
endmodule
testbench_top
`timescale 1ns/1ps
module testbench_top();
//参数定义
`define CLK_PERIORD 20 //50Mhz
localparam CNT_500KHZ_MAX = 50_000_000/500_000 - 1 ; //500Khz计数值
localparam CNT_500KHZ_MAX_10_PERCENT = 50_000_000/500_000*0.5 -1 ;//50%占空比
localparam CNT_350KHZ_MAX = 50_000_000/350_000 - 1 ; //350Khz计数值
localparam CNT_350KHZ_MAX_10_PERCENT = 50_000_000/350_000*0.1 -1 ;//10%章 ?空比
//接口申明
reg [7:0] i_cnt_max;
reg [7:0] i_cnt_max_percent;
reg i_clk;
reg i_rst_n;
reg i_en;
wire o_vld; //有效信号
wire o_pwm;
vlg_design vlg_design_inst(
.i_cnt_max(i_cnt_max),
.i_cnt_max_percent(i_cnt_max_percent),
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.i_en(i_en),
.o_vld(o_vld),
.o_pwm(o_pwm)
);
task setpwmparam;
input [7:0]t_cnt_max;
input [7:0]t_cnt_max_percent;
begin
i_cnt_max <= t_cnt_max;
i_cnt_max_percent <= t_cnt_max_percent;
@(posedge i_clk);
i_en <= 1;
repeat(t_cnt_max*2) @(posedge i_clk);
i_en <= 0;
end
endtask
initial begin
i_en <= 0;
i_clk <= 0;
i_rst_n <= 0;
#200;
i_rst_n <= 1;
end
always #(`CLK_PERIORD/2) i_clk = ~i_clk;
//产生激励
initial begin
@(posedge i_clk);
@(posedge i_rst_n);
setpwmparam(CNT_500KHZ_MAX,CNT_500KHZ_MAX_10_PERCENT);
#200;
setpwmparam(CNT_350KHZ_MAX,CNT_350KHZ_MAX_10_PERCENT);
#20000;
$stop;
end
endmodule
方案3:使用vivado VIO功能传递参数
步骤1,添加设计文件到vivado工程
步骤2,添加vio ip核
步骤2,复制veo文件下的例化模板至设计文件中
去掉模块定义中的这4个输入,改为VIO提供,由软件控件配置参数,通过JTAG 线缆,传递给芯片
步骤3,运行综合
步骤4,管脚分配
步骤5,生成bit文件,并烧录
步骤6,添加vio按钮
将i_en 配置成按钮button ,按下是高电平
其他3个配置位,10进制输入
点击i_en 开始测试