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。

  • 相关阅读:
    React生命周期, 兄弟组件之间通信
    React组件式编程Demo-用户的增删改查
    React之this.refs, 实现数据双向绑定
    CCF CSP 201812-4 数据中心
    CCF CSP 201812-4 数据中心
    PAT 顶级 1020 Delete At Most Two Characters (35 分)
    PAT 顶级 1020 Delete At Most Two Characters (35 分)
    Codeforces 1245C Constanze's Machine
    Codeforces 1245C Constanze's Machine
    CCF CSP 201712-4 行车路线
  • 原文地址:https://www.cnblogs.com/milinker/p/6474682.html
Copyright © 2011-2022 走看看