本文共 3664 字,大约阅读时间需要 12 分钟。
1. 软件平台
vivado2019.1
2. 硬件平台
PYNQ_Z2
3. 目的
旨在利用PS端来控制PWM波的频率占空比以及启动和关闭。
在这里不做太复杂的功能。
4. 自定义IP核
如果是刚接触vivado,可以参考
如果没有自定义IP核的经验,可以事先查看博客
两路pwm波,这里设置用两个16位数据来控制频率和占空比,一位来做使能,所以只需要3个寄存器,这里最低4个,选择4个寄存器。
由于数据量极低,接口类型选择Lite就可以满足了。
这里AXI接口数量,自行探讨。
这里新建一个源文件,pwm_gen.v
代码如下
`timescale 1ns / 1ps//// Company: // Engineer: // // Create Date: 2019/10/05 15:33:27// Design Name: // Module Name: pwm_gen// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// //`timescale 1ns / 1ps//// Company: // Engineer: // // Create Date: 2019/10/05 10:41:44// Design Name: // Module Name: pwm_gen// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// //`timescale 1ns / 1ps//// Company: // Engineer: // // Create Date: 2019/10/03 18:09:27// Design Name: // Module Name: pwm_gen// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// ///*时钟信号 clk 复位信号 rst 使能信号 en 周期 period = clk/f 占空比 h_time = period * D 输出 pwm */module pwm_gen( input clk, input rst, input en, input [15:0]period, input [15:0]h_time, output reg pwm); reg [31:0]CNT;always @(posedge clk or negedge rst)begin if(!rst) CNT <= 0; else if(CNT >= period-1 || en ==0) CNT <= 0; else CNT <= CNT + 1'b1;endalways @(posedge clk or negedge rst)begin if(!rst) pwm <= 0; else begin if(en == 0) pwm <= 0; else begin if(CNT <= h_time-1) pwm <=1; else pwm <= 0; end endendendmodule
在该文件下添加寄存器输出的数据“端口”
点击保存
转到top level,主要是调用模块
添加输出端口,
“输出寄存器的值”
调用pwm发生器模块
// Add user logic here //pwm0 pwm_gen pwm0( .clk(s00_axi_aclk), .rst(s00_axi_aresetn), .en(en), .period(ctrl_pwm0[15:0]), .h_time(ctrl_pwm0[31:16]), .pwm(pwm_out0) ); //pwm1 pwm_gen pwm1( .clk(s00_axi_aclk), .rst(s00_axi_aresetn), .en(en), .period(ctrl_pwm1[15:0]), .h_time(ctrl_pwm1[31:16]), .pwm(pwm_out1) ); // User logic ends
然后保存,进行综合,这里只需要run synthesis,不需要implementation (作用是防止错漏,但不能完全检查出来)
无误后,re_pakage-IP,,这样一个pwm发生器的IP核就建立好了
下图是block design
然后generate output product
然后选择create HDL wrapper
再添加时序约束
##Raspberry Digital I/O set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { pwm_out0 }]; #IO_L22P_T3_34 Sch=rpio_02_rset_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { pwm_out1 }]; #IO_L22N_T3_34 Sch=rpio_03_r
最后点击generate bitstream
之后的步骤参考
SDK工程代码如下
#include#include "platform.h"#include "xil_printf.h"/* Include Files */#include "xparameters.h"#include "xil_io.h"#include "xstatus.h"/* Definitions */#define printf xil_printf /* smaller, optimised printf *//* * pwm_gen 16λ Ϊperiod 15λΪ ռ¿ձȪperiod 1λΪenable */u32 pwm_gen0= 0x0BB81388; /* h_time & period*/u32 pwm_gen1= 0x094c1388; /* h_time & period*/u32 pwm_en = 0x01; /*enable flag*/#define pwm0 0x43c00000 /* address of pwm0 configure register*/#define pwm1 0x43c00004 /* address of pwm0 configure register*/#define en 0x43c00008 /* address of enable flag configure register*/int main(){ init_platform(); print("Hello World\n\r"); cleanup_platform(); /* Execute the pwm output. */ Xil_Out32(pwm0,pwm_gen0); //configure pwm0 period and D Xil_Out32(pwm1,pwm_gen1); //configure pwm1 period and D Xil_Out32(en,pwm_en); // enable pwm0 pwm1 at the same time return 0;}
注意:寄存器的地址间隔为4
运行结果如下
pwm0输出20khz,占空比为50%
pwm0输出20khz,占空比为47.6%
pwm0和pwm1没有相位偏移(verilog部分没操作好可能会造成一定的相位偏移,这是由于pwm发生器计数不是同时开始而造成的)
转载地址:http://iyjtz.baihongyu.com/