[X]关闭

米联客-XILINX-H3_CZ08_7100] FPGA_AXI总线入门连载-11AXI-Lite 自定义 AXI_GPIO

文档创建者:FPGA课程
浏览次数:201
最后更新:2024-10-15
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-FPGA部分 » 2_FPGA实验篇(仅旗舰) » 3-FPGA AXI 总线入门
本帖最后由 FPGA课程 于 2024-10-15 18:40 编辑

​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1概述
在前文中我们学习了AXI总线协议,而且通过VIVADO自定义了AXI-LITE总线协议的IP CORE,并且实现了寄存器的读写。
那么在实际的应用中,如果我们ARM的IO不够用了,除了在前文中使用官方自带的AXI-GPIO,我们自己也可以定义AXI-GPIO IP CORE。
本文后以几篇文章都会展示AXI-LITE 自定义IP的使用,通过加强的训练,让读者掌握这种总线接口的使用。并且后面我们自定的AXI-FDMA可以完成高速的DMA数据传输。
本文实验目的:
1:通过前文的学习,把掌握的自定义AXI-LITE-SLAVE寄存器读写方法,用于引出扩展PL的IO
2:通过VITIS-SDK实现对自定义IP中寄存器的读写访问,以此实现PL IO的控制。
2系统框图
e588dee1833c40c4a1bbd1df011e7c42.jpg
3创建IP
3.1利用模板创建AXI-Lite IP
1:打开VIVADO软件,新建一个工程。
2:单击ToolsàCreate and Package NEW IP。
3:单击Next,选择Create a new AXI4 peripheral,单击Next。
ebc7a80cca104d2b9a5cdd082e48531c.jpg
4:输入要创建的IP名字,此处命名为GPIO_LITE_ML,选择保存路径,单击Next。
39d0344cda454e07a4ccbe21fb2fd160.jpg
5:Name -->S00_AXI;
Interface Type(接口类型)-->Lite;
Data Width(Bits)(数据位宽)-->32位;
Number of Registers(寄存器数量)-->4 ;单击next。
705fe567fc064d629315fd3f7b700f86.jpg
6:选择Edit IP,点击Finish按钮。软件自动打开一个编辑IP的工程,即edit_GPIO_LITE_ML_V1_0.xpr工程。
607af1eb888f425f99ad2cabe4400da6.jpg
3.2修改IP源码
1:打开的edit_GPIO_LITE_ML_V1_0.xpr工程界面如下。
9f0240dec17f4b868150a5438de2421c.jpg
查看生成IP的文件夹
c7e4317c2b724b4ca827591d2a9751f1.jpg
2:现在生成的IP需要进行修改才能满足我们使用需求。选中Project Manager,双击GPIO_LITE_ML_v1_0_S00_AXI_inst,做如下更改。
修改1:
6609329303b746d798709df7a2d0d699.jpg
修改2:
27fd58acf71e47ce884287e135beb903.jpg
将slv_reg0的值赋值给了用户输出逻辑,当我们向slv_reg0写入数据的时候,也就相当于向GPIO_LED赋值。
更改后的文件如下所示。
3:双击GPIO_LITE_ML_v1_0文件,做如下修改。
  1. `timescale 1 ns / 1 ps

  2.         module GPIO_LITE_ML_v1_0_S00_AXI #
  3.         (
  4.                 // Users to add parameters here

  5.                 // User parameters ends
  6.                 // Do not modify the parameters beyond this line

  7.                 // Width of S_AXI data bus
  8.                 parameter integer C_S_AXI_DATA_WIDTH        = 32,
  9.                 // Width of S_AXI address bus
  10.                 parameter integer C_S_AXI_ADDR_WIDTH        = 4
  11.         )
  12.         (
  13.                 // Users to add ports here
  14.         output wire [3:0]GPIO_LED,
  15.                 // User ports ends
  16.                 // Do not modify the ports beyond this line

  17.                 // Global Clock Signal
  18.                 input wire  S_AXI_ACLK,
  19.                 // Global Reset Signal. This Signal is Active LOW
  20.                 input wire  S_AXI_ARESETN,
  21.                 // Write address (issued by master, acceped by Slave)
  22.                 input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
  23.                 // Write channel Protection type. This signal indicates the
  24.                     // privilege and security level of the transaction, and whether
  25.                     // the transaction is a data access or an instruction access.
  26.                 input wire [2 : 0] S_AXI_AWPROT,
  27.                 // Write address valid. This signal indicates that the master signaling
  28.                     // valid write address and control information.
  29.                 input wire  S_AXI_AWVALID,
  30.                 // Write address ready. This signal indicates that the slave is ready
  31.                     // to accept an address and associated control signals.
  32.                 output wire  S_AXI_AWREADY,
  33.                 // Write data (issued by master, acceped by Slave)
  34.                 input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
  35.                 // Write strobes. This signal indicates which byte lanes hold
  36.                     // valid data. There is one write strobe bit for each eight
  37.                     // bits of the write data bus.   
  38.                 input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
  39.                 // Write valid. This signal indicates that valid write
  40.                     // data and strobes are available.
  41.                 input wire  S_AXI_WVALID,
  42.                 // Write ready. This signal indicates that the slave
  43.                     // can accept the write data.
  44.                 output wire  S_AXI_WREADY,
  45.                 // Write response. This signal indicates the status
  46.                     // of the write transaction.
  47.                 output wire [1 : 0] S_AXI_BRESP,
  48.                 // Write response valid. This signal indicates that the channel
  49.                     // is signaling a valid write response.
  50.                 output wire  S_AXI_BVALID,
  51.                 // Response ready. This signal indicates that the master
  52.                     // can accept a write response.
  53.                 input wire  S_AXI_BREADY,
  54.                 // Read address (issued by master, acceped by Slave)
  55.                 input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
  56.                 // Protection type. This signal indicates the privilege
  57.                     // and security level of the transaction, and whether the
  58.                     // transaction is a data access or an instruction access.
  59.                 input wire [2 : 0] S_AXI_ARPROT,
  60.                 // Read address valid. This signal indicates that the channel
  61.                     // is signaling valid read address and control information.
  62.                 input wire  S_AXI_ARVALID,
  63.                 // Read address ready. This signal indicates that the slave is
  64.                     // ready to accept an address and associated control signals.
  65.                 output wire  S_AXI_ARREADY,
  66.                 // Read data (issued by slave)
  67.                 output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
  68.                 // Read response. This signal indicates the status of the
  69.                     // read transfer.
  70.                 output wire [1 : 0] S_AXI_RRESP,
  71.                 // Read valid. This signal indicates that the channel is
  72.                     // signaling the required read data.
  73.                 output wire  S_AXI_RVALID,
  74.                 // Read ready. This signal indicates that the master can
  75.                     // accept the read data and response information.
  76.                 input wire  S_AXI_RREADY
  77.         );

  78.         // AXI4LITE signals
  79.         reg [C_S_AXI_ADDR_WIDTH-1 : 0]         axi_awaddr;
  80.         reg          axi_awready;
  81.         reg          axi_wready;
  82.         reg [1 : 0]         axi_bresp;
  83.         reg          axi_bvalid;
  84.         reg [C_S_AXI_ADDR_WIDTH-1 : 0]         axi_araddr;
  85.         reg          axi_arready;
  86.         reg [C_S_AXI_DATA_WIDTH-1 : 0]         axi_rdata;
  87.         reg [1 : 0]         axi_rresp;
  88.         reg          axi_rvalid;

  89.         // Example-specific design signals
  90.         // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
  91.         // ADDR_LSB is used for addressing 32/64 bit registers/memories
  92.         // ADDR_LSB = 2 for 32 bits (n downto 2)
  93.         // ADDR_LSB = 3 for 64 bits (n downto 3)
  94.         localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
  95.         localparam integer OPT_MEM_ADDR_BITS = 1;
  96.         //----------------------------------------------
  97.         //-- Signals for user logic register space example
  98.         //------------------------------------------------
  99.         //-- Number of Slave Registers 4
  100.         reg [C_S_AXI_DATA_WIDTH-1:0]        slv_reg0;
  101.         reg [C_S_AXI_DATA_WIDTH-1:0]        slv_reg1;
  102.         reg [C_S_AXI_DATA_WIDTH-1:0]        slv_reg2;
  103.         reg [C_S_AXI_DATA_WIDTH-1:0]        slv_reg3;
  104.         wire         slv_reg_rden;
  105.         wire         slv_reg_wren;
  106.         reg [C_S_AXI_DATA_WIDTH-1:0]         reg_data_out;
  107.         integer         byte_index;
  108.         reg         aw_en;

  109.         // I/O Connections assignments

  110.         assign S_AXI_AWREADY        = axi_awready;
  111.         assign S_AXI_WREADY        = axi_wready;
  112.         assign S_AXI_BRESP        = axi_bresp;
  113.         assign S_AXI_BVALID        = axi_bvalid;
  114.         assign S_AXI_ARREADY        = axi_arready;
  115.         assign S_AXI_RDATA        = axi_rdata;
  116.         assign S_AXI_RRESP        = axi_rresp;
  117.         assign S_AXI_RVALID        = axi_rvalid;
  118.         // Implement axi_awready generation
  119.         // axi_awready is asserted for one S_AXI_ACLK clock cycle when both
  120.         // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
  121.         // de-asserted when reset is low.

  122.         always @( posedge S_AXI_ACLK )
  123.         begin
  124.           if ( S_AXI_ARESETN == 1'b0 )
  125.             begin
  126.               axi_awready <= 1'b0;
  127.               aw_en <= 1'b1;
  128.             end
  129.           else
  130.             begin   
  131.               if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
  132.                 begin
  133.                   // slave is ready to accept write address when
  134.                   // there is a valid write address and write data
  135.                   // on the write address and data bus. This design
  136.                   // expects no outstanding transactions.
  137.                   axi_awready <= 1'b1;
  138.                   aw_en <= 1'b0;
  139.                 end
  140.                 else if (S_AXI_BREADY && axi_bvalid)
  141.                     begin
  142.                       aw_en <= 1'b1;
  143.                       axi_awready <= 1'b0;
  144.                     end
  145.               else           
  146.                 begin
  147.                   axi_awready <= 1'b0;
  148.                 end
  149.             end
  150.         end      

  151.         // Implement axi_awaddr latching
  152.         // This process is used to latch the address when both
  153.         // S_AXI_AWVALID and S_AXI_WVALID are valid.

  154.         always @( posedge S_AXI_ACLK )
  155.         begin
  156.           if ( S_AXI_ARESETN == 1'b0 )
  157.             begin
  158.               axi_awaddr <= 0;
  159.             end
  160.           else
  161.             begin   
  162.               if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
  163.                 begin
  164.                   // Write Address latching
  165.                   axi_awaddr <= S_AXI_AWADDR;
  166.                 end
  167.             end
  168.         end      

  169.         // Implement axi_wready generation
  170.         // axi_wready is asserted for one S_AXI_ACLK clock cycle when both
  171.         // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
  172.         // de-asserted when reset is low.

  173.         always @( posedge S_AXI_ACLK )
  174.         begin
  175.           if ( S_AXI_ARESETN == 1'b0 )
  176.             begin
  177.               axi_wready <= 1'b0;
  178.             end
  179.           else
  180.             begin   
  181.               if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
  182.                 begin
  183.                   // slave is ready to accept write data when
  184.                   // there is a valid write address and write data
  185.                   // on the write address and data bus. This design
  186.                   // expects no outstanding transactions.
  187.                   axi_wready <= 1'b1;
  188.                 end
  189.               else
  190.                 begin
  191.                   axi_wready <= 1'b0;
  192.                 end
  193.             end
  194.         end      

  195.         // Implement memory mapped register select and write logic generation
  196.         // The write data is accepted and written to memory mapped registers when
  197.         // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
  198.         // select byte enables of slave registers while writing.
  199.         // These registers are cleared when reset (active low) is applied.
  200.         // Slave register write enable is asserted when valid address and data are available
  201.         // and the slave is ready to accept the write address and write data.
  202.         assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

  203.         always @( posedge S_AXI_ACLK )
  204.         begin
  205.           if ( S_AXI_ARESETN == 1'b0 )
  206.             begin
  207.               slv_reg0 <= 0;
  208.               slv_reg1 <= 0;
  209.               slv_reg2 <= 0;
  210.               slv_reg3 <= 0;
  211.             end
  212.           else begin
  213.             if (slv_reg_wren)
  214.               begin
  215.                 case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
  216.                   2'h0:
  217.                     for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  218.                       if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  219.                         // Respective byte enables are asserted as per write strobes
  220.                         // Slave register 0
  221.                         slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  222.                       end  
  223.                   2'h1:
  224.                     for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  225.                       if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  226.                         // Respective byte enables are asserted as per write strobes
  227.                         // Slave register 1
  228.                         slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  229.                       end  
  230.                   2'h2:
  231.                     for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  232.                       if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  233.                         // Respective byte enables are asserted as per write strobes
  234.                         // Slave register 2
  235.                         slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  236.                       end  
  237.                   2'h3:
  238.                     for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
  239.                       if ( S_AXI_WSTRB[byte_index] == 1 ) begin
  240.                         // Respective byte enables are asserted as per write strobes
  241.                         // Slave register 3
  242.                         slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
  243.                       end  
  244.                   default : begin
  245.                               slv_reg0 <= slv_reg0;
  246.                               slv_reg1 <= slv_reg1;
  247.                               slv_reg2 <= slv_reg2;
  248.                               slv_reg3 <= slv_reg3;
  249.                             end
  250.                 endcase
  251.               end
  252.           end
  253.         end   

  254.         // Implement write response logic generation
  255.         // The write response and response valid signals are asserted by the slave
  256.         // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.  
  257.         // This marks the acceptance of address and indicates the status of
  258.         // write transaction.

  259.         always @( posedge S_AXI_ACLK )
  260.         begin
  261.           if ( S_AXI_ARESETN == 1'b0 )
  262.             begin
  263.               axi_bvalid  <= 0;
  264.               axi_bresp   <= 2'b0;
  265.             end
  266.           else
  267.             begin   
  268.               if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
  269.                 begin
  270.                   // indicates a valid write response is available
  271.                   axi_bvalid <= 1'b1;
  272.                   axi_bresp  <= 2'b0; // 'OKAY' response
  273.                 end                   // work error responses in future
  274.               else
  275.                 begin
  276.                   if (S_AXI_BREADY && axi_bvalid)
  277.                     //check if bready is asserted while bvalid is high)
  278.                     //(there is a possibility that bready is always asserted high)   
  279.                     begin
  280.                       axi_bvalid <= 1'b0;
  281.                     end  
  282.                 end
  283.             end
  284.         end   

  285.         // Implement axi_arready generation
  286.         // axi_arready is asserted for one S_AXI_ACLK clock cycle when
  287.         // S_AXI_ARVALID is asserted. axi_awready is
  288.         // de-asserted when reset (active low) is asserted.
  289.         // The read address is also latched when S_AXI_ARVALID is
  290.         // asserted. axi_araddr is reset to zero on reset assertion.

  291.         always @( posedge S_AXI_ACLK )
  292.         begin
  293.           if ( S_AXI_ARESETN == 1'b0 )
  294.             begin
  295.               axi_arready <= 1'b0;
  296.               axi_araddr  <= 32'b0;
  297.             end
  298.           else
  299.             begin   
  300.               if (~axi_arready && S_AXI_ARVALID)
  301.                 begin
  302.                   // indicates that the slave has acceped the valid read address
  303.                   axi_arready <= 1'b1;
  304.                   // Read address latching
  305.                   axi_araddr  <= S_AXI_ARADDR;
  306.                 end
  307.               else
  308.                 begin
  309.                   axi_arready <= 1'b0;
  310.                 end
  311.             end
  312.         end      

  313.         // Implement axi_arvalid generation
  314.         // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
  315.         // S_AXI_ARVALID and axi_arready are asserted. The slave registers
  316.         // data are available on the axi_rdata bus at this instance. The
  317.         // assertion of axi_rvalid marks the validity of read data on the
  318.         // bus and axi_rresp indicates the status of read transaction.axi_rvalid
  319.         // is deasserted on reset (active low). axi_rresp and axi_rdata are
  320.         // cleared to zero on reset (active low).  
  321.         always @( posedge S_AXI_ACLK )
  322.         begin
  323.           if ( S_AXI_ARESETN == 1'b0 )
  324.             begin
  325.               axi_rvalid <= 0;
  326.               axi_rresp  <= 0;
  327.             end
  328.           else
  329.             begin   
  330.               if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
  331.                 begin
  332.                   // Valid read data is available at the read data bus
  333.                   axi_rvalid <= 1'b1;
  334.                   axi_rresp  <= 2'b0; // 'OKAY' response
  335.                 end   
  336.               else if (axi_rvalid && S_AXI_RREADY)
  337.                 begin
  338.                   // Read data is accepted by the master
  339.                   axi_rvalid <= 1'b0;
  340.                 end               
  341.             end
  342.         end   

  343.         // Implement memory mapped register select and read logic generation
  344.         // Slave register read enable is asserted when valid address is available
  345.         // and the slave is ready to accept the read address.
  346.         assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
  347.         always @(*)
  348.         begin
  349.               // Address decoding for reading registers
  350.               case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
  351.                 2'h0   : reg_data_out <= slv_reg0;
  352.                 2'h1   : reg_data_out <= slv_reg1;
  353.                 2'h2   : reg_data_out <= slv_reg2;
  354.                 2'h3   : reg_data_out <= slv_reg3;
  355.                 default : reg_data_out <= 0;
  356.               endcase
  357.         end

  358.         // Output register or memory read data
  359.         always @( posedge S_AXI_ACLK )
  360.         begin
  361.           if ( S_AXI_ARESETN == 1'b0 )
  362.             begin
  363.               axi_rdata  <= 0;
  364.             end
  365.           else
  366.             begin   
  367.               // When there is a valid read address (S_AXI_ARVALID) with
  368.               // acceptance of read address by the slave (axi_arready),
  369.               // output the read dada
  370.               if (slv_reg_rden)
  371.                 begin
  372.                   axi_rdata <= reg_data_out;     // register read data
  373.                 end   
  374.             end
  375.         end   

  376.         // Add user logic here
  377.     assign GPIO_LED[3:0] = slv_reg0[3:0];
  378.         // User logic ends

  379.         endmodule
复制代码

修改1:
8256817964774e47a39ff75630647281.jpg
修改2:
f02da81513344407a1bd559347b70aa9.jpg
修改后的文件如下。

  1. `timescale 1 ns / 1 ps

  2.         module GPIO_LITE_ML_v1_0 #
  3.         (
  4.                 // Users to add parameters here

  5.                 // User parameters ends
  6.                 // Do not modify the parameters beyond this line


  7.                 // Parameters of Axi Slave Bus Interface S00_AXI
  8.                 parameter integer C_S00_AXI_DATA_WIDTH        = 32,
  9.                 parameter integer C_S00_AXI_ADDR_WIDTH        = 4
  10.         )
  11.         (
  12.                 // Users to add ports here
  13.         output wire [3:0]GPIO_LED,
  14.                 // User ports ends
  15.                 // Do not modify the ports beyond this line


  16.                 // Ports of Axi Slave Bus Interface S00_AXI
  17.                 input wire  s00_axi_aclk,
  18.                 input wire  s00_axi_aresetn,
  19.                 input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,
  20.                 input wire [2 : 0] s00_axi_awprot,
  21.                 input wire  s00_axi_awvalid,
  22.                 output wire  s00_axi_awready,
  23.                 input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata,
  24.                 input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb,
  25.                 input wire  s00_axi_wvalid,
  26.                 output wire  s00_axi_wready,
  27.                 output wire [1 : 0] s00_axi_bresp,
  28.                 output wire  s00_axi_bvalid,
  29.                 input wire  s00_axi_bready,
  30.                 input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,
  31.                 input wire [2 : 0] s00_axi_arprot,
  32.                 input wire  s00_axi_arvalid,
  33.                 output wire  s00_axi_arready,
  34.                 output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata,
  35.                 output wire [1 : 0] s00_axi_rresp,
  36.                 output wire  s00_axi_rvalid,
  37.                 input wire  s00_axi_rready
  38.         );
  39. // Instantiation of Axi Bus Interface S00_AXI
  40.         GPIO_LITE_ML_v1_0_S00_AXI # (
  41.                 .C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),
  42.                 .C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)
  43.         ) GPIO_LITE_ML_v1_0_S00_AXI_inst (
  44.                 .S_AXI_ACLK(s00_axi_aclk),
  45.                 .S_AXI_ARESETN(s00_axi_aresetn),
  46.                 .S_AXI_AWADDR(s00_axi_awaddr),
  47.                 .S_AXI_AWPROT(s00_axi_awprot),
  48.                 .S_AXI_AWVALID(s00_axi_awvalid),
  49.                 .S_AXI_AWREADY(s00_axi_awready),
  50.                 .S_AXI_WDATA(s00_axi_wdata),
  51.                 .S_AXI_WSTRB(s00_axi_wstrb),
  52.                 .S_AXI_WVALID(s00_axi_wvalid),
  53.                 .S_AXI_WREADY(s00_axi_wready),
  54.                 .S_AXI_BRESP(s00_axi_bresp),
  55.                 .S_AXI_BVALID(s00_axi_bvalid),
  56.                 .S_AXI_BREADY(s00_axi_bready),
  57.                 .S_AXI_ARADDR(s00_axi_araddr),
  58.                 .S_AXI_ARPROT(s00_axi_arprot),
  59.                 .S_AXI_ARVALID(s00_axi_arvalid),
  60.                 .S_AXI_ARREADY(s00_axi_arready),
  61.                 .S_AXI_RDATA(s00_axi_rdata),
  62.                 .S_AXI_RRESP(s00_axi_rresp),
  63.                 .S_AXI_RVALID(s00_axi_rvalid),
  64.                 .S_AXI_RREADY(s00_axi_rready),
  65.                 .GPIO_LED(GPIO_LED)
  66.         );

  67.         // Add user logic here

  68.         // User logic ends

  69.         endmodule
复制代码

4:进一步修改。去掉“_v1_0”。
1、GPIO_LITE_ML_v1_0_S00_AXI.v中:
module GPIO_LITE_ML_v1_0_S00_AXI #修改为-->module GPIO_LITE_ML_S00_AXI #
e9af675a4f0c4089b77cc14d86d8491a.jpg                   
修改后
40e0593575f04631ae8588915e3f1b57.jpg

2、GPIO_LITE_ML_v1_0.v中:
module GPIO_LITE_ML_v1_0 #     修改为--> module GPIO_LITE_ML #
e00620d8125f494ca25c2293c06b8cae.jpg                      
  修改后
   8da563d8305e4837adfc87caf3e2f532.jpg
GPIO_LITE_ML_v1_0_S00_AXI #  修改为-->GPIO_LITE_ML_S00_AXI #
GPIO_LITE_ML_v1_0_S00_AXI_inst 修改为-->GPIO_LITE_ML_S00_AXI_inst
d3d8bd1950234c33ba30bafb02ef32f4.jpg                      
    修改后
8dbffb16e81c40158c643410dcb9185e.jpg
5:修改后,保存。出现如下界面,选择Automatically pick new top module。
780e6f68c1f6493f82411a3c59d2917a.jpg
更新后界面
64c711b3fe6e40ae96c28a43277b0199.jpg
6:重新封装。选择ToolsàCreat and Pakage New IP,单击Next。
7:选择Package your current project,单击Next。
343afe703aa24193b3ed65717bcf930b.jpg
路径选择原来IP所在的位置,覆盖原来的文件。
9d90accc23c04eed94744651d7a8cf3d.jpg
8:选择Overwrite。
31833dbf58634dcf8e6dc791a4d05c18.jpg
9:选择Package IP --> Rewiew and Package --> Re-Package IP
14a1869dfe614985bc67dd0bba7cd694.jpg
e863947c2df24171bd3182ce24923b7c.jpg
自定义IP生成完毕。

4搭建SOC系统工程
详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。
4.1SOC系统工程
0f1f026117b94831a4d634eac6cbb702.jpg

1:PS 复位设置
e5478c357efd42049e3ccadfccb1ddc4.jpg
2:PS LPD 设置
44ea7e800ed744b8aac40394e91bc762.jpg
3:PL 输出时钟设置
55cebc77b325436489c2218b9a568a62.jpg
4.2 添加自定义 AXI-Lite IP
1:设置 IP 路径
本文中是我们第一次在 BD 图形化设计中添加自定义的 IP , 自定义的 IP 需要设置 IP 路径才能被识别到。默认情况 下,我们自定的 IP 在配套工程的 uisrc/ip 路径下:

04d3907114134fa189cdcd9ffe818ccb.jpg
2:添加 IP
43d8219fb7904ad8952dff751b458625.jpg
4.3PL 图像化编程
d1be6a473c974e5bbe1bd68bc5baedd9.jpg
4.4 设置地址分配
138d664f9f2e40f29dd73da3c39e81b2.jpg
4.5 编译并导出平台文件
1:单击 Block 文件 --> 右键 --> Generate the Output Product --> Globa --> Generate。
2: 单 击 Block  文 件 --> 右 键 --> Create  a HDL wrapper( 生 成 HDL  顶 层 文 件 ) --> Let vivado manager wrapper and auto-update(自动更新)。
3:生成 Bit 文件。
4:导出到硬件: File --> Export Hardware --> Include bitstream
5:导出完成后,对应工程路径的 zu_hw 路径下有硬件平台文件:system_wrapper.xsa 的文件。根据硬件平台文件 system_wrapper.xsa 来创建需要 Platform 平台。

0ab62d392d784e4389974b892aa9741b.jpg
5搭建Vitis-sdk工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
5.1创建SDK Platform工程
1f7282503623498b8115ed8103ae57d8.jpg
右击soc_base编译,编译的时间可能会有点长
5.2创建APP工程
d8f1087acb84409cbd489997e9700c96.jpg
6程序分析
XGpio_axi_WriteReg()函数实现的是向AXI的寄存器中写入数据,它的三个参数分别为基地址,偏移量和数据。需要注意的是此处的偏移量,AXI的相邻寄存器偏移量相差4个字节,默认slv_reg0的偏移量是0,因此,可以推导出slv_reg1,slv_reg2的偏移量分别为4和8,本课中,我们只用到了slv_reg0,所以偏移量为0。
7方案演示
a71b33678b5547ee992fd2554f2449b1.jpg

ea399958935a4455be6405dbfd87620b.jpg
c251619254ed4767a6b9ff7fa9d74701.jpg
a7f94e8095f444d9ba425e2b9539b469.jpg
c950151ae176439787e9425be3f3f29a.jpg
5084eb78d0714a30a6364259d122f31b.jpg
5084eb78d0714a30a6364259d122f31b.jpg
5084eb78d0714a30a6364259d122f31b.jpg
5084eb78d0714a30a6364259d122f31b.jpg
5084eb78d0714a30a6364259d122f31b.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
920550be026c4facbcaa68a1562d3f54.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则