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. jar包中的依赖jar版本冲突

    背景,项目中之前引入了一个 图片上传的jar <groupId>commons-fileupload</groupId> <artifactId>commons-f ...

  2. C语言中内存对齐规则讨论(struct)

    C语言中内存对齐规则讨论(struct) 对齐: 现代计算机中内存空间都是按着byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地 ...

  3. iOS开发系列--地图与定位总结

    现在很多社交.电商.团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的.的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式.例如你到了一个陌生的 ...

  4. LC 986. Interval List Intersections

    Given two lists of closed intervals, each list of intervals is pairwise disjoint and in sorted order ...

  5. Http的请求协议请求行介绍

    请求协议包含的内容 请求行 GET /day04-tomcat/index.jsp HTTP/1.1 HTTP/1.1: 表示的是我们使用的是http协议的1.1版本 请求头 请求空行 请求体: 存储 ...

  6. Qt开发经验小技巧合集

    一.开发经验总结 当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了. 定时器是个好东西,学会好使用它, ...

  7. centos 7设置limit,不生效问题

    1:记录未修改之前的ulimit值 [root@bogon ~]# ulimit -a 2:修改配置文件 vim  /etc/security/limits.conf   在后面添加 *      s ...

  8. Android view的一些认识

    转载:9102年末,我对Android view的13条认识: (顺手留下GitHub链接,需要获取相关面试等内容的可以自己去找)https://github.com/xiangjiana/Andro ...

  9. leetcode 区间合并

    个区间若能合并,则第一个区间的右端点一定不小于第二个区间的左端点.所以先把区间集合按照左端点从小到大进行排序,接着从第一个区间开始遍历,对每个区间执行如下操作: 1.首先保存该区间的左端点start和 ...

  10. SecureCRT 添加Mac Localhost

    1.启动sshd服务: sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist 停止sshd服务的方法: sudo launchc ...