自定义AXI_PWM_v1.0——ZYNQ学习笔记15

发布于:2025-09-01 ⋅ 阅读:(14) ⋅ 点赞:(0)

自定义IP

实现从PS段配置输出频率,输出占空比,输出使能配置

配置界面Clk Hz为AXI总线参考时钟

模块底层代码

module breath_pwm
#(
    parameter CLK_HZ = 100_000_000      // 输入时钟频率
)
(
    input  wire        sys_clk,         // 100 MHz
    input  wire        sys_rst_n,       // 低电平复位
    input  wire [13:0] set_freq_duty,   // 0-10000 对应 0%-100%
    input  wire        set_freq_en,     // 使能,为 0 时 PWM 输出 0
    input  wire [24:0] set_freq,        // 目标频率,单位 Hz
    output 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) begin
        period_cnt_max <= 32'hFFFF_FFFF;
    end
    else if (set_freq_en) begin
        period_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) begin
    if (!sys_rst_n) begin
        period_cnt <= 32'd0;
        PWM        <= 1'b0;
    end
    else if (!set_freq_en) begin
        period_cnt <= 32'd0;
        PWM        <= 1'b0;
    end
    else begin
        if (period_cnt >= period_cnt_max - 32'd1) begin
            period_cnt <= 32'd0;
        end
        else begin
            period_cnt <= period_cnt + 32'd1;
            PWM <= (period_cnt < high_cnt) ? 1'b1 : 1'b0;
        end
    end
end

endmodule

顶层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]:NC

int main(){
	xil_printf("AXI_IP_PWM!!\r\n");
	AXI_PWM_mWriteReg(PWM_BASEADDR, AXI_PWM_REG0, 0x04D2);		//50.00%	0x1388->5000		0x04D2->1234
	AXI_PWM_mWriteReg(PWM_BASEADDR, AXI_PWM_REG2, 0x04D2);		//100khz	0x186A0->100_000

	while(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文件)