S02_CH13_ AXI_PWM 实验

当学习了上一章的协议介绍内容后,开发基于这些协议的方案已经不是什么难事了,关键的一点就是从零到有的突破了。本章就以AXI-Lite总线实现8路LED自定义IP作为第一验证AXI-Lite总线应用的方案,带领大家快速进入实战状态。

13.1 自定义IP的封装

Step1:新建一个名为Miz_sys空的工程。

Step2:选择Tools Create and Package IP 创建IP

Step3:单击NEXT

Step4:由于我们需要挂在到总线上,因此创建一个带AXI总线的用户IP

Step5:设置IP的名字为PWM_LITE_ML版本号默认,并且记住IP的位置

Step6:设置总线形式为Lite总线,Lite总线是简化的AXI总线消耗的资源少,当然性能也是比完全版的AXI总线差一点,但是由于音频的速度并不高,因此采用Lite总线就够了,设置寄存器数量为16,因为后面我们需要用到16个寄存器。

Step7:选择Edit IP单击Finish完成


13.2 miz702_pwm用户IP的修改

IP创建完成后,并不能立马使用,还需要做一些修改。

Step1:打开PWM_AXI_ML.v文件在以下位置修改:

Step2:修改PWM_AXI_ML_v1_0_S00_AXI.v的端口部分

Step3:slv_reg0-slv_reg5为PS部分写入PL的寄存器。通过这个16个寄存器的值,我们可以控制PWM的占空比。

Step3:下面这段代码就是PS写PL部分的寄存器,一共有16个寄存器

always @( posedge S_AXI_ACLK )

begin

if ( S_AXI_ARESETN == 1'b0 )

begin

slv_reg0 <= 0;

slv_reg1 <= 0;

slv_reg2 <= 0;

slv_reg3 <= 0;

slv_reg4 <= 0;

slv_reg5 <= 0;

slv_reg6 <= 0;

slv_reg7 <= 0;

slv_reg8 <= 0;

slv_reg9 <= 0;

slv_reg10 <= 0;

slv_reg11 <= 0;

slv_reg12 <= 0;

slv_reg13 <= 0;

slv_reg14 <= 0;

slv_reg15 <= 0;

end

else begin

if (slv_reg_wren)

begin

case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )

4'h0:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 0

slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h1:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 1

slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h2:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 2

slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h3:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 3

slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h4:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 4

slv_reg4[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h5:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 5

slv_reg5[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h6:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 6

slv_reg6[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h7:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 7

slv_reg7[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h8:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 8

slv_reg8[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'h9:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 9

slv_reg9[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'hA:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 10

slv_reg10[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'hB:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 11

slv_reg11[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'hC:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 12

slv_reg12[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'hD:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 13

slv_reg13[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'hE:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 14

slv_reg14[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

4'hF:

for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )

if ( S_AXI_WSTRB[byte_index] == 1 ) begin

// Respective byte enables are asserted as per write strobes

// Slave register 15

slv_reg15[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];

end  

default : begin

slv_reg0 <= slv_reg0;

slv_reg1 <= slv_reg1;

slv_reg2 <= slv_reg2;

slv_reg3 <= slv_reg3;

slv_reg4 <= slv_reg4;

slv_reg5 <= slv_reg5;

slv_reg6 <= slv_reg6;

slv_reg7 <= slv_reg7;

slv_reg8 <= slv_reg8;

slv_reg9 <= slv_reg9;

slv_reg10 <= slv_reg10;

slv_reg11 <= slv_reg11;

slv_reg12 <= slv_reg12;

slv_reg13 <= slv_reg13;

slv_reg14 <= slv_reg14;

slv_reg15 <= slv_reg15;

end

endcase

end

end

end

Step4:新建一个PWM.v 文件实现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

Step5:修改完成后重新封装一次自定义IP

Step6:单击NEXT

Step7:和第一次不同,这次选择第一个单选框然后单击NEXT

Step8:选择第一个单选框,然后单击NEXT

Step9:点击Overwrite

Step10:点击Finish 到此自定义IP结束


13.3 搭建硬件工程

Step1:另外新建一个VIVADO工程,根据自己的开发板正确配置芯片型号。

Step2:在Project manager区中单击Project settings。

Step3:选择IP设置区中的repository manager,将上一节我们封装好的IP的路劲添加进去。

Step:4:单击+号图标,将上一节封装的IP的路劲存放进去,单击OK。

Step5:新建一个BD文件,输入文件名,完成创建。

Step6:向BD文件中添加一个ZYNQ Processing system,根据自身硬件完成IP的配置。

Step7:单击添加IP图标,输入上一节我们自定义IP的模块名,将其添加入BD文件中。

Step8:直接点击Run connection automation,然后单击OK。

Step9:选中PWM_o,按Ctrl+T组合键引出端口。

Step10:单击IP icon 添加 ila CORE

Step11:双击打开ILA CORE

Step12:双击打开ILA CORE

General Options设置如下

Probe_Ports设置如下,之后单击OK

Step13:连接Probe0到PWM_o。

Step14:连接CLK接口到FCLK_CLK0接口。

Step15:右键单击Block文件,文件选择Generate the Output Products。

Step16:右键单击Block文件,选择Create a HDL wrapper,根据Block文件内容产生一个HDL 的顶层文件,并选择让vivado自动完成。

Step17:添加一个约束文件,打开对应自己硬件的原理图,查看LED部分引脚连接情况,此次我们只用4个LED完成实验。Miz702约束文件如下所示:

set_property SEVERITY {Warning} [get_drc_checks NSTD-1]

set_property SEVERITY {Warning} [get_drc_checks UCIO-1]

set_property PACKAGE_PIN T22 [get_ports {PWM_o[0]}]

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

set_property PACKAGE_PIN T21 [get_ports {PWM_o[1]}]

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

set_property PACKAGE_PIN U22 [get_ports {PWM_o[2]}]

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

set_property PACKAGE_PIN U21 [get_ports {PWM_o[3]}]

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

其他型号开发板参照对应型号的原理图的LED部分,修改成对应的引脚即可。

Step11:生成bit文件。

13.4 加载到SDK

Step1:导出硬件。

Step2:新建一个空SDK工程,并添加一个main.c的文件。

Step3:在main.c文件中添加以下程序,按Ctrl+S保存后自动开始编译。

#include <stdio.h>

#include "xparameters.h"

#include "xil_io.h"

#include "sleep.h"

#include "xil_types.h"

int main()

{

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR,99);//pwm0 fre

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+4,10);//pwm0 wav

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+8,99);//pwm1 fre

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+12,20);//pwm1 wav

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+16,99);//pwm2 fre

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+20,40);//pwm2 wav

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+24,99);//pwm3 fre

Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+28,80);//pwm3 wav

return 0;

}

Step4:右击工程,选择Debug as ->Debug configuration。

Step5:选中system Debugger,双击创建一个系统调试。

Step6:设置系统调试。

Step7:单击运行程序按钮运行程序。

Step8:回到VIVADO单击Open Target->Auto Connect

Step9:加载完成后的界面

Step10:单击箭头所指向启动触发,窗口显示采集到的信号波形。


13.5 程序分析

Main函数中,根据之前章节的讲解我们可知,此处是分别向AXI总线的寄存器中写入数据。在13.2小节里,我们观察到,pwm_o[0]的频率设置和波形设置是通过slv_reg0和slv_reg1控制的。

由程序可知,程序中设置的pwm_o[0]的频率和波形频率分别为99和10,我们在ila中实际测量一下看看波形是否正确(将黄色测量线拖放到某一点,然后点击,可设立一个参考点)。

由上图可知,我们写入的数据和实际的输出是完全一致的,验证了我们的想法。

13.6 本章小结

本章实现了第一个实现具体功能的8路PWM,通过点亮LED可以看到效果。这个简单的工程充分体现了SOC的优势。CPU无需参与就可以让8路PWM持续输出,这个输出是有PL控制的

S02_CH13_ AXI_PWM 实验的更多相关文章

  1. [原] 利用 OVS 建立 VxLAN 虚拟网络实验

    OVS 配置 VxLAN HOST A ------------------------------------------ | zh-veth0(10.1.1.1) VM A | | ---|--- ...

  2. Android中Activity的四大启动模式实验简述

    作为Android四大组件之一,Activity可以说是最基本也是最常见的组件,它提供了一个显示界面,从而实现与用户的交互,作为初学者,必须熟练掌握.今天我们就来通过实验演示,来帮助大家理解Activ ...

  3. SEED实验系列文章目录

    美国雪城大学SEEDLabs实验列表 SEEDLabs是一套完整的信息安全实验,涵盖本科信息安全教学中的大部分基本原理.项目组2002年由杜文亮教授创建,目前开发了30个实验,几百所大学已采用.实验楼 ...

  4. 物联网实验4 alljoyn物联网实验之手机局域网控制设备

    AllJoyn开源物联网协议框架,官方描述是一个能够使连接设备之间进行互操作的通用软件框架和系统服务核心集,也是一个跨制造商来创建动态近端网络的软件应用.高通已经将该项目捐赠给了一个名为“AllSee ...

  5. (转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)

    一.  HTTP请求的数据流总结#上传数据, yeelink的数据流如下POST /v1.0/device/4420/sensor/9089/datapoints HTTP/1.1Host: api. ...

  6. (原创) alljoyn物联网实验之手机局域网控制设备

    AllJoyn开源物联网协议框架,官方描述是一个能够使连接设备之间进行互操作的通用软件框架和系统服务核心集,也是一个跨制造商来创建动态近端网络的软件应用.高通已经将该项目捐赠给了一个名为“AllSee ...

  7. 实验:Oracle直接拷贝物理存储文件迁移

    实验目的:Oracle直接拷贝物理文件迁移,生产库有类似施工需求,故在实验环境简单验证一下. 实验环境: A主机:192.168.1.200 Solaris10 + Oracle 11.2.0.1 B ...

  8. Oracle RAC 更换存储实验

    实验环境准备: RHEL 6.5 + Oracle 11.2.0.4 RAC (2nodes) OCR和Voting Disk使用的是OCR1磁盘组,底层对应3个1G大小的共享LUN,一般冗余: DA ...

  9. Vertica集群扩容实验过程记录

    需求: 将3个节点的Vertica集群扩容,额外增加3个节点,即扩展到6个节点的Vertica集群. 实验环境: RHEL 6.5 + Vertica 7.2.2-2 步骤: 1.三节点Vertica ...

随机推荐

  1. CDH 更换 HDFS 数据目录

    先停止 HDFS 角色. 数据文件位置默认在 /dfs/ 中,这里配置 NameNode.SecondaryNameNode.DataNode 数据目录. 先在所有 HDFS 的主机上把数据拷贝过去, ...

  2. Python JSON dump ,load,dumps,loads

    JSON是一种轻量级的数据交换格式. json.dump() 将Python数据格式序列化为json数据格式(字符串)并储存在json文件之中. json.load()将Jons数据(字符串)反序列化 ...

  3. mysql 给用户设置权限

    grant   all   on   wordpress.*   to  wordpress@'10.0.0.%'  identified  by  'wordpress'; all    全部权限 ...

  4. 获取当前运行的exe路径

    void GetAppPath(CString& path) { TCHAR str[] = {}; GetModuleFileName(NULL,str,); wchar_t *pszPos ...

  5. python 内置数据结构 切片

    切片 通过索引区间访问线性结构的一段数据 sequence[start:stop] 表示返回[start,stop]区间的子序列 支持负索引 start为0,可以省略 stop为末尾,可以省略 超过上 ...

  6. 在线word转html

    http://www.docpe.com/word/word-to-html.aspx

  7. Spring Aop(二)——基于Aspectj注解的Spring Aop简单实现

    转发地址:https://www.iteye.com/blog/elim-2394762 2 基于Aspectj注解的Spring Aop简单实现 Spring Aop是基于Aop框架Aspectj实 ...

  8. bash小结

    context:CentOS 什么是shell? shell就是与计算机交互的接口. linux支持的shell [root@node1 ~]# cat /etc/shells /bin/sh #被 ...

  9. BFS算法模板(python实现)

    BFS算法整理(python实现) 广度优先算法(Breadth-First-Search),简称BFS,是一种图形搜索演算算法. 1. 算法的应用场景 2. 算法的模板 2.1 针对树的BFS模板 ...

  10. Go语言中使用切片(slice)实现一个Vector容器

    Go语言中的切片(slice)和一些内置函数能实现其他语言容器类Array.Vector的功能,但是Go内置语言包container里只提供了list.heap.ring三种容器,缺少vector容器 ...