博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
S02_CH13_ AXI_PWM 实验
阅读量:5291 次
发布时间:2019-06-14

本文共 9243 字,大约阅读时间需要 30 分钟。

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控制的

转载于:https://www.cnblogs.com/milinker/p/6474727.html

你可能感兴趣的文章
#587. 天天和不可描述
查看>>
P3111 [USACO14DEC]牛慢跑Cow Jog_Sliver
查看>>
#10. 三角形的个数
查看>>
P1007 独木桥
查看>>
#592. 投放点的选择
查看>>
#532. 排名
查看>>
P1372 又是毕业季I
查看>>
P1403 [AHOI2005]约数研究
查看>>
#594. 连线交叉
查看>>
P1495 曹冲养猪
查看>>
P1104 生日
查看>>
P2735 电网 Electric Fences
查看>>
重置select2下拉框方法
查看>>
redis面试题
查看>>
composer 执行内存超出问题解决
查看>>
Ubuntu 下安装phantomjs
查看>>
Windows环境下npm install 报错: operation not permitted, rename的解决方法
查看>>
docker保存对容器的修改
查看>>
安装composer后报错proc_open(): fork failed - Cannot allocate memory
查看>>
HTTP状态码
查看>>