自定义AXI_PWM_v1.0——ZYNQ学习笔记15
自定义IP
实现从PS段配置输出频率,输出占空比,输出使能配置
配置界面Clk Hz为AXI总线参考时钟
模块底层代码
module breath_pwm
#(parameter CLK_HZ = 100_000_000 // 输入时钟频率
)
(input wire sys_clk, // 100 MHzinput wire sys_rst_n, // 低电平复位input wire [13:0] set_freq_duty, // 0-10000 对应 0%-100%input wire set_freq_en, // 使能,为 0 时 PWM 输出 0input wire [24:0] set_freq, // 目标频率,单位 Hzoutput reg PWM
);//------------------------------------------------------------------
// 1. 计算一个 PWM 周期所需的时钟周期数
//------------------------------------------------------------------
reg [31:0] period_cnt_max; // = CLK_HZ / set_freq
wire [31:0] next_period_cnt_max =(set_freq == 0) ? 32'hFFFF_FFFF : (CLK_HZ / set_freq);
always @(posedge sys_clk or negedge sys_rst_n)if (!sys_rst_n) beginperiod_cnt_max <= 32'hFFFF_FFFF;endelse if (set_freq_en) beginperiod_cnt_max <= next_period_cnt_max;end
//------------------------------------------------------------------
// 2. 计算高电平持续时间(高电平时钟周期数)
//------------------------------------------------------------------
wire [31:0] high_cnt =((period_cnt_max * set_freq_duty) + 15'd5000) / 16'd10000; // 四舍五入
//------------------------------------------------------------------
// 3. PWM 周期计数器 & 输出逻辑
//------------------------------------------------------------------
reg [31:0] period_cnt;
always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n) beginperiod_cnt <= 32'd0;PWM <= 1'b0;endelse if (!set_freq_en) beginperiod_cnt <= 32'd0;PWM <= 1'b0;endelse beginif (period_cnt >= period_cnt_max - 32'd1) beginperiod_cnt <= 32'd0;endelse beginperiod_cnt <= period_cnt + 32'd1;PWM <= (period_cnt < high_cnt) ? 1'b1 : 1'b0;endend
endendmodule
顶层AXI接口封装
测试工程
#include "AXI_PWM.h"
#include "xparameters.h"
#include "stdio.h"
#include "xil_io.h"
#include "sleep.h"
#include "xil_printf.h"#define PWM_BASEADDR XPAR_AXI_PWM_0_S0_AXI_BASEADDR //AXI_PWM IP 基地址//AXI_PWM IP 寄存器偏移地址
#define AXI_PWM_REG0 AXI_PWM_S0_AXI_SLV_REG0_OFFSET //[13:0]:PWM输出占空比,10000映射到100.00
#define AXI_PWM_REG1 AXI_PWM_S0_AXI_SLV_REG1_OFFSET //[0 :0]:PWM输出使能位
#define AXI_PWM_REG2 AXI_PWM_S0_AXI_SLV_REG2_OFFSET //[25:0]:PWM输出频率(Hz)
#define AXI_PWM_REG3 AXI_PWM_S0_AXI_SLV_REG3_OFFSET //[x :x]:NCint main(){xil_printf("AXI_IP_PWM!!\r\n");AXI_PWM_mWriteReg(PWM_BASEADDR, AXI_PWM_REG0, 0x04D2); //50.00% 0x1388->5000 0x04D2->1234AXI_PWM_mWriteReg(PWM_BASEADDR, AXI_PWM_REG2, 0x04D2); //100khz 0x186A0->100_000while(1){//打开输出使能AXI_PWM_mWriteReg(PWM_BASEADDR, AXI_PWM_REG1, 1);xil_printf("PWM ON\r\n");sleep(1);//关闭 输出使能
// AXI_PWM_mWriteReg(PWM_BASEADDR, AXI_PWM_REG1, 0);
// xil_printf("PWM OFF\r\n");
// sleep(1);}}
IP获取链接
通过网盘分享的文件:AXI_PWM_v1.0.zip
链接: https://pan.baidu.com/s/1ENpRrl0rJ-y4QVsz3ky9JA?pwd=5875 提取码: 5875
(PS:需要替换makefile文件)