【JokerのZYNQ7020】AXI_PWM。

软件环境:vivado 2017.4        硬件平台:XC7Z020 


 今天主要是通过AXI_LITE总线,做个呼吸灯。老样子,先新建个IP核Tools------------> Create and Package New IP。

然后选择Create a new AXI4 peripheral。

 主要注意名字和存放位置,名字为了后面加载用,切记名字取的不要跟你的block design的名字重名,不然会报一些稀奇古怪的错误,存放位置方便其他工程二次调用。

 接口类型选择Lite,Slave模式。

这里注意寄存器数量,应该是2倍的通道数,也就是说,如果你有4个通道输出PWM,那么就要有8个寄存器,其中一个用于控制频率,另一个用来控制占空比。最后进入编辑模式。

开下层文件, 进入编辑状态,18行增加pwm输出接口。

------------>

445行,增加pwm子模块接口。

 直接在左侧source上点加号,新建PWM文件,同样注意选择保存位置。

PWM添加内容如下。

module PWM(
input clk,
input rst_n,
input [31:0]fre_set,
input [31:0]wav_set,
output  PWM_o
);

reg [31:0]fre_cnt;
always @(posedge clk)begin
	if(rst_n==1'b0)begin
		fre_cnt <=32'd0;
	end
	else begin
		if(fre_cnt<fre_set) begin
			fre_cnt <= fre_cnt+1'b1;
		end
		else begin
			fre_cnt<=32'd0;
		end
	end
end

assign PWM_o = (wav_set>fre_cnt);

endmodule

很好理解,fre_set是频率设置,当计数频率fre_cnt小于设定频率fre_set时,频率计数自加,否则清零。当波形占空比设置值wav_set大于计数频率fre_cnt时,输出高,否则输出低;作为一个灵魂画手,没有visio就能成为不画示意图的理由了吗?当然不能。fre_set=100,fre_cnt是黑线,到100清零,wav_set=50是红线,fre_set和wav_set是input,上级模块给定,所以频率可调。

 别忘了返回最上层,加上output [3:0] pwm_o输出口,两个地方要加,18行和72行,加的时候注意上一行末尾的逗号。

 都搞定了以后先保存,在ports里刷新下添加的PWM输出口。

 然后重新封装一下修改过的IP核。

封装完后它会提示你退出,而后依旧是老套路,create block design ,建好的图如下所示。

注意,ila模块选general options里选择native模式,probe_ports中probe width选择4。然后添加管脚约束文件。

set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]

set_property PACKAGE_PIN J16 [get_ports {PWM_o[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[0]}]

set_property PACKAGE_PIN K16 [get_ports {PWM_o[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[1]}]

set_property PACKAGE_PIN G15 [get_ports {PWM_o[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[2]}]

set_property PACKAGE_PIN H15 [get_ports {PWM_o[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[3]}]

最后进入枯燥的Generate the output products,Create a HDL wrapper,产生Bitstream,最后导入SDK。


SDK中new application然后添加如下测试代码,就能看到四个LED呼吸起来。

#include <stdio.h>
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
#include "xil_types.h"

int main()
{

	int i;
	while(1)
	{
		for(i = 0; i < 299;i++)
		{
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR,299);//pwm0 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+4,i);//pwm0 wav

			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+8,299);//pwm1 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+12,i);//pwm1 wav

			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+16,299);//pwm2 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+20,i);//pwm2 wav

			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+24,299);//pwm3 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+28,i);//pwm3 wav
			usleep(6000);
		}
		for(i = 299; i > 0;i--)
		{
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR,299);//pwm0 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+4,i);//pwm0 wav

			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+8,299);//pwm1 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+12,i);//pwm1 wav

			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+16,299);//pwm2 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+20,i);//pwm2 wav

			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+24,299);//pwm3 fre
			Xil_Out32(XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR+28,i);//pwm3 wav
			usleep(6000);
		}
	}
return 0;
}

可以看到,除了Xil_Out32没用啥其他函数,因为不轮多复杂的函数封装,只要到底层,要操作寄存器,其实还是靠的这一个函数。至于XPAR_AXI_PWM_OUTPUT_0_S00_AXI_BASEADDR哪来的,其实在xparameters.h头文件里,另外在vivado里,也能看到这个寄存器值是多少,就是自建IP核的地址。

 回vivado,在最左下方,open target------------>auto connect通过ila模块看一下时序。

每刷新一次,都能看到寄存器值的变化。也是因为寄存器值先增大,再减小,才能看到LED呼吸。


 这节依旧没啥好总结的。

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值