zoukankan      html  css  js  c++  java
  • S02_CH10_ User GPIO实验

    S02_CH10_ User GPIO实验

    在之前的第四章课程中,我们详细的讲解了如何在VIVADO软件下封装一个简单的流水灯程序。在ZYNQ开发过程中,有时候我们可能会需要与ARM硬核进行通信,在这种情况之下,可能就需要用到更高速的接口与ARM通信。本章就将讲解如何创建一个基于高速的AXI总线的IP。本章将带领大家创建一个带AXI总线接口的自定义GPIO模拟的流水灯实验。通过这种方法,我们可以在GPIO资源缺乏的情况下,利用PL的资源来扩充GPIO资源。

    10.1 创建IP

    Step1:打开VIVADO软件,新建一个工程。

    Step2:单击Tools菜单下的Create and package IP。

    Step3:单击Next,选择Create a new AXI4 peripheral,单击Next。

    wps15D2.tmp

    Step4:输入要创建的IP名字,此处我们命名为GPIO_LITE_ML,选择好保存路劲,单击Next。

    wps15D3.tmp

    Step5:选择接口类型为lite,数据位宽为32位,寄存器数量为4,然后单击next。

    wps15D4.tmp

    Step6:选择Edit IP,然后选择Finish按钮将打开一个新的编辑IP的工程。

    wps15E4.tmp

    Step7:选中Project Manager,双击GPIO_LITE_ML_v1_0_S00_inst,用以下程序替换原来的程序。

    `timescale 1 ns / 1 ps

    module GPIO_LITE_ML_v1_0_S00_AXI #

    (

    // Users to add parameters here

    // User parameters ends

    // Do not modify the parameters beyond this line

    // Width of S_AXI data bus

    parameter integer C_S_AXI_DATA_WIDTH = 32,

    // Width of S_AXI address bus

    parameter integer C_S_AXI_ADDR_WIDTH = 4

    )

    (

    // Users to add ports here

           output wire [7:0]GPIO_LED,

    // User ports ends

    // Do not modify the ports beyond this line

    // Global Clock Signal

    input wire  S_AXI_ACLK,

    // Global Reset Signal. This Signal is Active LOW

    input wire  S_AXI_ARESETN,

    // Write address (issued by master, acceped by Slave)

    input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,

    // Write channel Protection type. This signal indicates the

    // privilege and security level of the transaction, and whether

    // the transaction is a data access or an instruction access.

    input wire [2 : 0] S_AXI_AWPROT,

    // Write address valid. This signal indicates that the master signaling

    // valid write address and control information.

    input wire  S_AXI_AWVALID,

    // Write address ready. This signal indicates that the slave is ready

    // to accept an address and associated control signals.

    output wire  S_AXI_AWREADY,

    // Write data (issued by master, acceped by Slave)

    input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,

    // Write strobes. This signal indicates which byte lanes hold

    // valid data. There is one write strobe bit for each eight

    // bits of the write data bus.    

    input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,

    // Write valid. This signal indicates that valid write

    // data and strobes are available.

    input wire  S_AXI_WVALID,

    // Write ready. This signal indicates that the slave

    // can accept the write data.

    output wire  S_AXI_WREADY,

    // Write response. This signal indicates the status

    // of the write transaction.

    output wire [1 : 0] S_AXI_BRESP,

    // Write response valid. This signal indicates that the channel

    // is signaling a valid write response.

    output wire  S_AXI_BVALID,

    // Response ready. This signal indicates that the master

    // can accept a write response.

    input wire  S_AXI_BREADY,

    // Read address (issued by master, acceped by Slave)

    input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,

    // Protection type. This signal indicates the privilege

    // and security level of the transaction, and whether the

    // transaction is a data access or an instruction access.

    input wire [2 : 0] S_AXI_ARPROT,

    // Read address valid. This signal indicates that the channel

    // is signaling valid read address and control information.

    input wire  S_AXI_ARVALID,

    // Read address ready. This signal indicates that the slave is

    // ready to accept an address and associated control signals.

    output wire  S_AXI_ARREADY,

    // Read data (issued by slave)

    output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,

    // Read response. This signal indicates the status of the

    // read transfer.

    output wire [1 : 0] S_AXI_RRESP,

    // Read valid. This signal indicates that the channel is

    // signaling the required read data.

    output wire  S_AXI_RVALID,

    // Read ready. This signal indicates that the master can

    // accept the read data and response information.

    input wire  S_AXI_RREADY

    );

    // AXI4LITE signals

    reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;

    reg   axi_awready;

    reg   axi_wready;

    reg [1 : 0] axi_bresp;

    reg   axi_bvalid;

    reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;

    reg   axi_arready;

    reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;

    reg [1 : 0] axi_rresp;

    reg   axi_rvalid;

    // Example-specific design signals

    // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH

    // ADDR_LSB is used for addressing 32/64 bit registers/memories

    // ADDR_LSB = 2 for 32 bits (n downto 2)

    // ADDR_LSB = 3 for 64 bits (n downto 3)

    localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;

    localparam integer OPT_MEM_ADDR_BITS = 1;

    //----------------------------------------------

    //-- Signals for user logic register space example

    //------------------------------------------------

    //-- Number of Slave Registers 4

    reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;

    reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1;

    reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2;

    reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3;

    wire  slv_reg_rden;

    wire  slv_reg_wren;

    reg [C_S_AXI_DATA_WIDTH-1:0]  reg_data_out;

    integer  byte_index;

    // I/O Connections assignments

    assign S_AXI_AWREADY = axi_awready;

    assign S_AXI_WREADY = axi_wready;

    assign S_AXI_BRESP = axi_bresp;

    assign S_AXI_BVALID = axi_bvalid;

    assign S_AXI_ARREADY = axi_arready;

    assign S_AXI_RDATA = axi_rdata;

    assign S_AXI_RRESP = axi_rresp;

    assign S_AXI_RVALID = axi_rvalid;

    // Implement axi_awready generation

    // axi_awready is asserted for one S_AXI_ACLK clock cycle when both

    // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is

    // de-asserted when reset is low.

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_awready <= 1'b0;

        end

      else

        begin    

          if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID)

            begin

              // slave is ready to accept write address when

              // there is a valid write address and write data

              // on the write address and data bus. This design

              // expects no outstanding transactions.

              axi_awready <= 1'b1;

            end

          else           

            begin

              axi_awready <= 1'b0;

            end

        end

    end       

    // Implement axi_awaddr latching

    // This process is used to latch the address when both

    // S_AXI_AWVALID and S_AXI_WVALID are valid.

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_awaddr <= 0;

        end

      else

        begin    

          if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID)

            begin

              // Write Address latching

              axi_awaddr <= S_AXI_AWADDR;

            end

        end

    end       

    // Implement axi_wready generation

    // axi_wready is asserted for one S_AXI_ACLK clock cycle when both

    // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is

    // de-asserted when reset is low.

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_wready <= 1'b0;

        end

      else

        begin    

          if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID)

            begin

              // slave is ready to accept write data when

              // there is a valid write address and write data

              // on the write address and data bus. This design

              // expects no outstanding transactions.

              axi_wready <= 1'b1;

            end

          else

            begin

              axi_wready <= 1'b0;

            end

        end

    end       

    // Implement memory mapped register select and write logic generation

    // The write data is accepted and written to memory mapped registers when

    // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to

    // select byte enables of slave registers while writing.

    // These registers are cleared when reset (active low) is applied.

    // Slave register write enable is asserted when valid address and data are available

    // and the slave is ready to accept the write address and write data.

    assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

    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;

        end

      else begin

        if (slv_reg_wren)

          begin

            case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )

              2'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  

              2'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  

              2'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  

              2'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  

              default : begin

                          slv_reg0 <= slv_reg0;

                          slv_reg1 <= slv_reg1;

                          slv_reg2 <= slv_reg2;

                          slv_reg3 <= slv_reg3;

                        end

            endcase

          end

      end

    end    

    // Implement write response logic generation

    // The write response and response valid signals are asserted by the slave

    // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.  

    // This marks the acceptance of address and indicates the status of

    // write transaction.

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_bvalid  <= 0;

          axi_bresp   <= 2'b0;

        end

      else

        begin    

          if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)

            begin

              // indicates a valid write response is available

              axi_bvalid <= 1'b1;

              axi_bresp  <= 2'b0; // 'OKAY' response

            end                   // work error responses in future

          else

            begin

              if (S_AXI_BREADY && axi_bvalid)

                //check if bready is asserted while bvalid is high)

                //(there is a possibility that bready is always asserted high)   

                begin

                  axi_bvalid <= 1'b0;

                end  

            end

        end

    end   

    // Implement axi_arready generation

    // axi_arready is asserted for one S_AXI_ACLK clock cycle when

    // S_AXI_ARVALID is asserted. axi_awready is

    // de-asserted when reset (active low) is asserted.

    // The read address is also latched when S_AXI_ARVALID is

    // asserted. axi_araddr is reset to zero on reset assertion.

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_arready <= 1'b0;

          axi_araddr  <= 32'b0;

        end

      else

        begin    

          if (~axi_arready && S_AXI_ARVALID)

            begin

              // indicates that the slave has acceped the valid read address

              axi_arready <= 1'b1;

              // Read address latching

              axi_araddr  <= S_AXI_ARADDR;

            end

          else

            begin

              axi_arready <= 1'b0;

            end

        end

    end       

    // Implement axi_arvalid generation

    // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both

    // S_AXI_ARVALID and axi_arready are asserted. The slave registers

    // data are available on the axi_rdata bus at this instance. The

    // assertion of axi_rvalid marks the validity of read data on the

    // bus and axi_rresp indicates the status of read transaction.axi_rvalid

    // is deasserted on reset (active low). axi_rresp and axi_rdata are

    // cleared to zero on reset (active low).  

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_rvalid <= 0;

          axi_rresp  <= 0;

        end

      else

        begin    

          if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)

            begin

              // Valid read data is available at the read data bus

              axi_rvalid <= 1'b1;

              axi_rresp  <= 2'b0; // 'OKAY' response

            end   

          else if (axi_rvalid && S_AXI_RREADY)

            begin

              // Read data is accepted by the master

              axi_rvalid <= 1'b0;

            end                

        end

    end    

    // Implement memory mapped register select and read logic generation

    // Slave register read enable is asserted when valid address is available

    // and the slave is ready to accept the read address.

    assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;

    always @(*)

    begin

          // Address decoding for reading registers

          case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )

            2'h0   : reg_data_out <= slv_reg0;

            2'h1   : reg_data_out <= slv_reg1;

            2'h2   : reg_data_out <= slv_reg2;

            2'h3   : reg_data_out <= slv_reg3;

            default : reg_data_out <= 0;

          endcase

    end

    // Output register or memory read data

    always @( posedge S_AXI_ACLK )

    begin

      if ( S_AXI_ARESETN == 1'b0 )

        begin

          axi_rdata  <= 0;

        end

      else

        begin    

          // When there is a valid read address (S_AXI_ARVALID) with

          // acceptance of read address by the slave (axi_arready),

          // output the read dada

          if (slv_reg_rden)

            begin

              axi_rdata <= reg_data_out;     // register read data

            end   

        end

    end    

    // Add user logic here

      assign  GPIO_LED[7:0] = slv_reg0[7:0];

    // User logic ends

    endmodule

    以上程序与生成的程序基本一致,只是添加了一个用户输出端口和用户逻辑。修改部分如下图所示:

    wps1614.tmp

    wps1615.tmp

    最后的用户逻辑将slv_reg0的值赋值给了用户输出逻辑,当我们向slv_reg0写入数据的时候,也就相当于向GPIO_LED赋值。

    Step8:双击GPIO_LITE_ML文件,用以下程序替换原来的程序。

    `timescale 1 ns / 1 ps

    module GPIO_LITE_ML #

    (

    // Users to add parameters here

    // User parameters ends

    // Do not modify the parameters beyond this line

    // Parameters of Axi Slave Bus Interface S00_AXI

    parameter integer C_S00_AXI_DATA_WIDTH = 32,

    parameter integer C_S00_AXI_ADDR_WIDTH = 4

    )

    (

    // Users to add ports here

            output wire [7:0]GPIO_LED,

    // User ports ends

    // Do not modify the ports beyond this line

    // Ports of Axi Slave Bus Interface S00_AXI

    input wire  s00_axi_aclk,

    input wire  s00_axi_aresetn,

    input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,

    input wire [2 : 0] s00_axi_awprot,

    input wire  s00_axi_awvalid,

    output wire  s00_axi_awready,

    input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata,

    input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb,

    input wire  s00_axi_wvalid,

    output wire  s00_axi_wready,

    output wire [1 : 0] s00_axi_bresp,

    output wire  s00_axi_bvalid,

    input wire  s00_axi_bready,

    input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,

    input wire [2 : 0] s00_axi_arprot,

    input wire  s00_axi_arvalid,

    output wire  s00_axi_arready,

    output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata,

    output wire [1 : 0] s00_axi_rresp,

    output wire  s00_axi_rvalid,

    input wire  s00_axi_rready

    );

    // Instantiation of Axi Bus Interface S00_AXI

    GPIO_LITE_ML_v1_0_S00_AXI # (

    .C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),

    .C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)

    ) GPIO_LITE_ML_v1_0_S00_AXI_inst (

    .S_AXI_ACLK(s00_axi_aclk),

    .S_AXI_ARESETN(s00_axi_aresetn),

    .S_AXI_AWADDR(s00_axi_awaddr),

    .S_AXI_AWPROT(s00_axi_awprot),

    .S_AXI_AWVALID(s00_axi_awvalid),

    .S_AXI_AWREADY(s00_axi_awready),

    .S_AXI_WDATA(s00_axi_wdata),

    .S_AXI_WSTRB(s00_axi_wstrb),

    .S_AXI_WVALID(s00_axi_wvalid),

    .S_AXI_WREADY(s00_axi_wready),

    .S_AXI_BRESP(s00_axi_bresp),

    .S_AXI_BVALID(s00_axi_bvalid),

    .S_AXI_BREADY(s00_axi_bready),

    .S_AXI_ARADDR(s00_axi_araddr),

    .S_AXI_ARPROT(s00_axi_arprot),

    .S_AXI_ARVALID(s00_axi_arvalid),

    .S_AXI_ARREADY(s00_axi_arready),

    .S_AXI_RDATA(s00_axi_rdata),

    .S_AXI_RRESP(s00_axi_rresp),

    .S_AXI_RVALID(s00_axi_rvalid),

    .S_AXI_RREADY(s00_axi_rready),

    //user port

    .GPIO_LED(GPIO_LED)

    );

    // Add user logic here

    // User logic ends

    endmodule

    以上的程序也只是在原来的程序的基础上增加了一个用户端口而已,并无什么大的改变。

    Step9:单击Tools菜单下的Create and package IP命令,重新封装IP。

    Step10:单击Next,选择第一项,单击Next。

    wps1616.tmp

    Step11:选择保存的路劲,单击Next。

    wps1627.tmp

    Step12:选择Overwrite,然后单击Finish。

    Step13:在新弹出的窗口中,我们注意到有一个警告,直接忽略它,选择Review and package IP选项,单击底部的package IP按钮完成IP的创建。

    wps1628.tmp

    10.2 搭建硬件工程

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

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

    wps1629.tmp

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

    wps1639.tmp

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

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

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

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

    wps163A.tmp

    Step8:直接点击Run connection automation。

    Step9:选中GPIO_LED端口,按Ctrl+T引出端口,整体硬件电路如下。

    wps164B.tmp

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

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

    Step10:添加一个约束文件,打开对应自己硬件的原理图,查看按键部分引脚连接情况,此次我们只用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 {GPIO_LED[0]}]

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

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

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

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

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

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

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

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

    Step11:生成bit文件。

    10.3 加载到SDK

    Step1:导出硬件。

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

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

    /*

    * main.c

    *

    *  Created on: 2016年11月8日

    *      Author: Administrator

    */

    #include <stdio.h>

    #include "xparameters.h"

    #include "xil_io.h"

    #include "sleep.h"

    #include "xil_types.h"

    #define XGpio_axi_WriteReg(BaseAddr, RegOffset, Data)

    Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))

    #define XPAR_GPIO_LITE_ML_0 XPAR_GPIO_LITE_ML_0_BASEADDR

    #define GPIO_LITE_ML_REG0 0

    int main()

    {

    u8 i=0;

    XGpio_axi_WriteReg(XPAR_GPIO_LITE_ML_0,GPIO_LITE_ML_REG0,0X00);

    while(1)

    {

    for(i=0;i<=3;i++)

    {

    XGpio_axi_WriteReg(XPAR_GPIO_LITE_ML_0,GPIO_LITE_ML_REG0,1<<i);

    usleep(500000);

    }

    i=0;

    }

    }

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

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

    wps164C.tmp

    Step6:设置系统调试。

    wps164D.tmp

    点击运行按钮开始运行程序,在开发板上四个LED循环流水操作。

    wps165D.tmp

    10.4 程序分析

    XGpio_axi_WriteReg()函数实现的是向AXI的寄存器中写入数据,它的三个参数分别为基地址,偏移量和数据。需要注意的是此处的偏移量,AXI的相邻寄存器偏移量相差4个字节,默认slv_reg0的偏移量是0,因此,可以推导出slv_reg1,slv_reg2的偏移量分别为4和8,本章中,我们只用到了slv_reg0,所以偏移量为0。

    10.4 本章小结

    本章介绍了一种创建AXI总线高速接口的方法,在实际开发中,有非常重要的意义,大家可以根据这种方法,自行设计其他带AXI总线的IP。

  • 相关阅读:
    微服务-分解应用程序从而实现更好的部署特性及可伸缩性
    <HTML5和CSS3响应式WEB设计指南>译者序
    使用亚马逊的Route53服务
    Java中测试异常的多种方式
    跑在路上的程序员随想
    使用ruby过程中遇到安装gem失败的一些通用解决方案
    Spring-Context之九:在bean定义中使用继承
    Spring-Context之八:一些依赖注入的小技巧
    配置ngnix
    PHP程序员进阶学习书籍参考指南
  • 原文地址:https://www.cnblogs.com/milinker/p/6474682.html
Copyright © 2011-2022 走看看