• S02_CH13_ AXI_PWM 实验


    S02_CH13_ AXI_PWM 实验

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

    13.1 自定义IP的封装

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

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

    wpsBEBD.tmp

    Step3:单击NEXT

    wpsBEBE.tmp

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

    wpsBECE.tmp

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

    wpsBECF.tmp

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

    wpsBED0.tmp

    Step7:选择Edit IP单击Finish完成

    wpsBEE1.tmp

    13.2 miz702_pwm用户IP的修改

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

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

    wpsBEE2.tmp

    wpsBEE3.tmp

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

    wpsBEF3.tmp

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

    wpsBEF4.tmp

    wpsBEF5.tmp

    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

    wpsBF16.tmp

    Step6:单击NEXT

    wpsBF17.tmp

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

    wpsBF18.tmp

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

    wpsBF28.tmp

    Step9:点击Overwrite

    wpsBF29.tmp

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

    wpsBF2A.tmp

    13.3 搭建硬件工程

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

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

    wpsBF2B.tmp

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

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

    wpsBF3C.tmp

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

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

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

    wpsBF3D.tmp

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

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

    Step10:单击IP icon wpsBF4D.tmp 添加 ila CORE

    wpsBF4E.tmp

    Step11:双击打开ILA CORE

    wpsBF4F.tmp

    Step12:双击打开ILA CORE

    General Options设置如下

    wpsBF50.tmp

    Probe_Ports设置如下,之后单击OK

    wpsBF61.tmp

    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,双击创建一个系统调试。

    wpsBF62.tmp

    Step6:设置系统调试。

    wpsBF73.tmp

    Step7:单击运行程序按钮wpsBF74.tmp运行程序。

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

    wpsBF75.tmp

    Step9:加载完成后的界面

    wpsBF85.tmp

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

    wpsBF86.tmp

    13.5 程序分析

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

    wpsBF87.tmp

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

    wpsBF99.tmp

    wpsBF9A.tmp

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

    13.6 本章小结

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

  • 相关阅读:
    2022省选前集训
    牛客挑战赛57总结
    Atcoder做题总结
    CR775总结
    卡特兰猜想的一个弱化形式
    Jinja2实现模板高度自定义
    Harbor仓库安装使用cfssl工具生成证书
    odoo15 视频聊天打不开摄像头及麦克风问题解决
    整合SSM
    力扣332题(重新安排行程)
  • 原文地址:https://www.cnblogs.com/milinker/p/6474727.html
Copyright © 2020-2023  润新知