• ZYNQ之路--制作AXI4 接口IP的思路


            这篇ZYNQ之路给大家带来使用AXI总线读写DDR的介绍,此篇博客的意义在于:

    1. AXI总线基础学习
    2. PL-PS交互学习
    3. 创建带有AXI总线接口的IP核
    4. 理解AXI总线IP的移植

    PL与PS交互方式

            

             上面的图片展示了PS与PL通过接口进行交互的方式,当然除此之外PS和PL还可以通过中断等方式进行一个交互。

    AXI总线

            概述

           AXI的全称叫做“ Advanced eXtensible Interface”即高级可扩展接口,该协议是ARM公司提出的AMBA(Advanced Microcontroller Bus Architecture)3.0协议中最重要的部分,是一种面向高性能、高带宽、低延迟的片内总线

            很容易理解这个总线的重要作用:Soc上各个子模块之间要进行通信,既然是通信那么总得有一个规范和标准,AMBA就是为了这样一个目的而提出的(不要问为啥是由ARM公司提出的,问就是因为ZYNQ使用的是ARM的内核)

            最新的AMBA(AXI4)标准

            AMBA属于不断在发展的一个架构,从前常用的诸如APB,AHB之类的总线标准,但是近些年来都统一称为AXI标准了,目前最新的AMBA标准应该是AXI4,具体包含的总线/接口请看下面的图片:

            总结,AXI协议支持以下三种接口:

    1. AXI-Full:即高性能存储映射接口。
    2. AXI-Lite:简化版的 AXI4 接口,用于较少数据量的存储映射通信,例如对模块进行配置。
    3. AXI-Stream:用于高速数据流传输,非存储映射接口,例如视频音频流传输(不能直接与PS端通信)。

            存储映射(Meamory Map):如果一个协议是存储映射的,那么主机 所发出的会话(无论读或写)就会标明一个地址。这个地址对应于系统存储空间中的一个地址,表明是针对 该存储空间的读写操作。 

             协议细节

            首先我们来看一下AXI4总线的组成:

    AXI4总线共有五个通道:

    1. 读地址
    2. 读数据
    3. 写地址
    4. 写数据
    5. 写应答

            每个通道的基本拓扑如下:

             包含了:时钟信号(上升沿有效)、数据信号,握手信号(VALID和READY)

            AXI协议的特色或者说核心就在于:握手信号

    • VALID信号由数据发送方发出,指示数据有效,因此一旦VALID为高电平,那么数据线上的数据就不能再改变。
    • READY信号由数据接收方发出,指示可以进行数据接收,因此READY信号只能在VALID有效之后拉高;当VALID和READY信号都有效时数据传输完成。

            之后我们再来看看五条通道的功能分配:

             

            五条通道互相独立,并且各自都遵循握手信号协议

          有关突发传输

            所谓的突发传输就是只要给定一个起始地址,一次性写入多组数据。在ZYNQ的AXI协议当中,AXI-Full协议支持最高256组数据的突发传输,而AXI-Lite一次只能传输一组数据,AXI-Stream则可以无限制地进行突发传输。

            关于突发传输的控制问题,例如突发写时主要使用WLAST信号线进行指示突发传输是否完成,最后一组数据写入完成后WLAST信号拉高(最下面三组是应答信号,由从机发出)。

    创建AXI接口的IP核

             Vivado可以使用向导创建带有AXI接口的IP模块,点击Tool里的Create and Package New IP即可打开向导。

             向导上说:这个导航将被用来完成下面的任务:

    • 打包一个新的IP(该导航将会指引你使用源文件或者你当前工程的文件等创建一个新的Vivado IP)
    • 创建一个新的AXI4外设(该导航将会指引你创建一个新的带有AXI4接口的外设,包括HDL,驱动,软件应用等等设计)

            我们选择创建一个AXI4的外设:

             下面是简单地配置AXI接口的相关信息:        我们主要目的是制作一个AXI接口的IP,因此我们选择编辑这个IP:

             下面是我们的重头戏来了:

             各位看官请移步Sources栏目,我们可以看到工程里自动多了一个顶层模块和一个实例模块,这是什么意思呢?

            这是Xilinx官方给的一个AXI接口的示例,我们设计AXI接口的IP核,如果是主接口,那么我们要有一套操控AXI接口,符合AXI时序的硬件;如果是从接口,那么我们要有能响应AXI接口请求的的一套硬件。

            从理论上来说,这些东西都是要咱们自己写的。我们原本应该仔细研读AXI接口中各个信号的时序关系,然后使用状态机让我们的功能IP能够与AXI的从机通信,或者响应主机请求。但是Xilinx官方在创建AXI接口IP的时候提供给了我们一个例子,让我们可以在这个例子的基础上进行改造。这就是向导的力量!

            顶层代码(从机)

    1. `timescale 1 ns / 1 ps
    2. module myip11_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. // User ports ends
    14. // Do not modify the ports beyond this line
    15. // Ports of Axi Slave Bus Interface S00_AXI
    16. input wire s00_axi_aclk,
    17. input wire s00_axi_aresetn,
    18. input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,
    19. input wire [2 : 0] s00_axi_awprot,
    20. input wire s00_axi_awvalid,
    21. output wire s00_axi_awready,
    22. input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata,
    23. input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb,
    24. input wire s00_axi_wvalid,
    25. output wire s00_axi_wready,
    26. output wire [1 : 0] s00_axi_bresp,
    27. output wire s00_axi_bvalid,
    28. input wire s00_axi_bready,
    29. input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,
    30. input wire [2 : 0] s00_axi_arprot,
    31. input wire s00_axi_arvalid,
    32. output wire s00_axi_arready,
    33. output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata,
    34. output wire [1 : 0] s00_axi_rresp,
    35. output wire s00_axi_rvalid,
    36. input wire s00_axi_rready
    37. );
    38. // Instantiation of Axi Bus Interface S00_AXI
    39. myip11_v1_0_S00_AXI # (
    40. .C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),
    41. .C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)
    42. ) myip11_v1_0_S00_AXI_inst (
    43. .S_AXI_ACLK(s00_axi_aclk),
    44. .S_AXI_ARESETN(s00_axi_aresetn),
    45. .S_AXI_AWADDR(s00_axi_awaddr),
    46. .S_AXI_AWPROT(s00_axi_awprot),
    47. .S_AXI_AWVALID(s00_axi_awvalid),
    48. .S_AXI_AWREADY(s00_axi_awready),
    49. .S_AXI_WDATA(s00_axi_wdata),
    50. .S_AXI_WSTRB(s00_axi_wstrb),
    51. .S_AXI_WVALID(s00_axi_wvalid),
    52. .S_AXI_WREADY(s00_axi_wready),
    53. .S_AXI_BRESP(s00_axi_bresp),
    54. .S_AXI_BVALID(s00_axi_bvalid),
    55. .S_AXI_BREADY(s00_axi_bready),
    56. .S_AXI_ARADDR(s00_axi_araddr),
    57. .S_AXI_ARPROT(s00_axi_arprot),
    58. .S_AXI_ARVALID(s00_axi_arvalid),
    59. .S_AXI_ARREADY(s00_axi_arready),
    60. .S_AXI_RDATA(s00_axi_rdata),
    61. .S_AXI_RRESP(s00_axi_rresp),
    62. .S_AXI_RVALID(s00_axi_rvalid),
    63. .S_AXI_RREADY(s00_axi_rready)
    64. );
    65. // Add user logic here
    66. // User logic ends
    67. endmodule

             实例代码

    1. `timescale 1 ns / 1 ps
    2. module myip11_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. // User ports ends
    15. // Do not modify the ports beyond this line
    16. // Global Clock Signal
    17. input wire S_AXI_ACLK,
    18. // Global Reset Signal. This Signal is Active LOW
    19. input wire S_AXI_ARESETN,
    20. // Write address (issued by master, acceped by Slave)
    21. input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
    22. // Write channel Protection type. This signal indicates the
    23. // privilege and security level of the transaction, and whether
    24. // the transaction is a data access or an instruction access.
    25. input wire [2 : 0] S_AXI_AWPROT,
    26. // Write address valid. This signal indicates that the master signaling
    27. // valid write address and control information.
    28. input wire S_AXI_AWVALID,
    29. // Write address ready. This signal indicates that the slave is ready
    30. // to accept an address and associated control signals.
    31. output wire S_AXI_AWREADY,
    32. // Write data (issued by master, acceped by Slave)
    33. input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
    34. // Write strobes. This signal indicates which byte lanes hold
    35. // valid data. There is one write strobe bit for each eight
    36. // bits of the write data bus.
    37. input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
    38. // Write valid. This signal indicates that valid write
    39. // data and strobes are available.
    40. input wire S_AXI_WVALID,
    41. // Write ready. This signal indicates that the slave
    42. // can accept the write data.
    43. output wire S_AXI_WREADY,
    44. // Write response. This signal indicates the status
    45. // of the write transaction.
    46. output wire [1 : 0] S_AXI_BRESP,
    47. // Write response valid. This signal indicates that the channel
    48. // is signaling a valid write response.
    49. output wire S_AXI_BVALID,
    50. // Response ready. This signal indicates that the master
    51. // can accept a write response.
    52. input wire S_AXI_BREADY,
    53. // Read address (issued by master, acceped by Slave)
    54. input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
    55. // Protection type. This signal indicates the privilege
    56. // and security level of the transaction, and whether the
    57. // transaction is a data access or an instruction access.
    58. input wire [2 : 0] S_AXI_ARPROT,
    59. // Read address valid. This signal indicates that the channel
    60. // is signaling valid read address and control information.
    61. input wire S_AXI_ARVALID,
    62. // Read address ready. This signal indicates that the slave is
    63. // ready to accept an address and associated control signals.
    64. output wire S_AXI_ARREADY,
    65. // Read data (issued by slave)
    66. output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
    67. // Read response. This signal indicates the status of the
    68. // read transfer.
    69. output wire [1 : 0] S_AXI_RRESP,
    70. // Read valid. This signal indicates that the channel is
    71. // signaling the required read data.
    72. output wire S_AXI_RVALID,
    73. // Read ready. This signal indicates that the master can
    74. // accept the read data and response information.
    75. input wire S_AXI_RREADY
    76. );
    77. // AXI4LITE signals
    78. reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
    79. reg axi_awready;
    80. reg axi_wready;
    81. reg [1 : 0] axi_bresp;
    82. reg axi_bvalid;
    83. reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
    84. reg axi_arready;
    85. reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;
    86. reg [1 : 0] axi_rresp;
    87. reg axi_rvalid;
    88. // Example-specific design signals
    89. // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
    90. // ADDR_LSB is used for addressing 32/64 bit registers/memories
    91. // ADDR_LSB = 2 for 32 bits (n downto 2)
    92. // ADDR_LSB = 3 for 64 bits (n downto 3)
    93. localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
    94. localparam integer OPT_MEM_ADDR_BITS = 1;
    95. //----------------------------------------------
    96. //-- Signals for user logic register space example
    97. //------------------------------------------------
    98. //-- Number of Slave Registers 4
    99. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;
    100. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1;
    101. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2;
    102. reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3;
    103. wire slv_reg_rden;
    104. wire slv_reg_wren;
    105. reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out;
    106. integer byte_index;
    107. reg aw_en;
    108. // I/O Connections assignments
    109. assign S_AXI_AWREADY = axi_awready;
    110. assign S_AXI_WREADY = axi_wready;
    111. assign S_AXI_BRESP = axi_bresp;
    112. assign S_AXI_BVALID = axi_bvalid;
    113. assign S_AXI_ARREADY = axi_arready;
    114. assign S_AXI_RDATA = axi_rdata;
    115. assign S_AXI_RRESP = axi_rresp;
    116. assign S_AXI_RVALID = axi_rvalid;
    117. // Implement axi_awready generation
    118. // axi_awready is asserted for one S_AXI_ACLK clock cycle when both
    119. // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
    120. // de-asserted when reset is low.
    121. always @( posedge S_AXI_ACLK )
    122. begin
    123. if ( S_AXI_ARESETN == 1'b0 )
    124. begin
    125. axi_awready <= 1'b0;
    126. aw_en <= 1'b1;
    127. end
    128. else
    129. begin
    130. if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
    131. begin
    132. // slave is ready to accept write address when
    133. // there is a valid write address and write data
    134. // on the write address and data bus. This design
    135. // expects no outstanding transactions.
    136. axi_awready <= 1'b1;
    137. aw_en <= 1'b0;
    138. end
    139. else if (S_AXI_BREADY && axi_bvalid)
    140. begin
    141. aw_en <= 1'b1;
    142. axi_awready <= 1'b0;
    143. end
    144. else
    145. begin
    146. axi_awready <= 1'b0;
    147. end
    148. end
    149. end
    150. // Implement axi_awaddr latching
    151. // This process is used to latch the address when both
    152. // S_AXI_AWVALID and S_AXI_WVALID are valid.
    153. always @( posedge S_AXI_ACLK )
    154. begin
    155. if ( S_AXI_ARESETN == 1'b0 )
    156. begin
    157. axi_awaddr <= 0;
    158. end
    159. else
    160. begin
    161. if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
    162. begin
    163. // Write Address latching
    164. axi_awaddr <= S_AXI_AWADDR;
    165. end
    166. end
    167. end
    168. // Implement axi_wready generation
    169. // axi_wready is asserted for one S_AXI_ACLK clock cycle when both
    170. // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
    171. // de-asserted when reset is low.
    172. always @( posedge S_AXI_ACLK )
    173. begin
    174. if ( S_AXI_ARESETN == 1'b0 )
    175. begin
    176. axi_wready <= 1'b0;
    177. end
    178. else
    179. begin
    180. if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
    181. begin
    182. // slave is ready to accept write data when
    183. // there is a valid write address and write data
    184. // on the write address and data bus. This design
    185. // expects no outstanding transactions.
    186. axi_wready <= 1'b1;
    187. end
    188. else
    189. begin
    190. axi_wready <= 1'b0;
    191. end
    192. end
    193. end
    194. // Implement memory mapped register select and write logic generation
    195. // The write data is accepted and written to memory mapped registers when
    196. // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
    197. // select byte enables of slave registers while writing.
    198. // These registers are cleared when reset (active low) is applied.
    199. // Slave register write enable is asserted when valid address and data are available
    200. // and the slave is ready to accept the write address and write data.
    201. assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
    202. always @( posedge S_AXI_ACLK )
    203. begin
    204. if ( S_AXI_ARESETN == 1'b0 )
    205. begin
    206. slv_reg0 <= 0;
    207. slv_reg1 <= 0;
    208. slv_reg2 <= 0;
    209. slv_reg3 <= 0;
    210. end
    211. else begin
    212. if (slv_reg_wren)
    213. begin
    214. case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
    215. 2'h0:
    216. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
    217. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
    218. // Respective byte enables are asserted as per write strobes
    219. // Slave register 0
    220. slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
    221. end
    222. 2'h1:
    223. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
    224. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
    225. // Respective byte enables are asserted as per write strobes
    226. // Slave register 1
    227. slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
    228. end
    229. 2'h2:
    230. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
    231. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
    232. // Respective byte enables are asserted as per write strobes
    233. // Slave register 2
    234. slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
    235. end
    236. 2'h3:
    237. for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
    238. if ( S_AXI_WSTRB[byte_index] == 1 ) begin
    239. // Respective byte enables are asserted as per write strobes
    240. // Slave register 3
    241. slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
    242. end
    243. default : begin
    244. slv_reg0 <= slv_reg0;
    245. slv_reg1 <= slv_reg1;
    246. slv_reg2 <= slv_reg2;
    247. slv_reg3 <= slv_reg3;
    248. end
    249. endcase
    250. end
    251. end
    252. end
    253. // Implement write response logic generation
    254. // The write response and response valid signals are asserted by the slave
    255. // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
    256. // This marks the acceptance of address and indicates the status of
    257. // write transaction.
    258. always @( posedge S_AXI_ACLK )
    259. begin
    260. if ( S_AXI_ARESETN == 1'b0 )
    261. begin
    262. axi_bvalid <= 0;
    263. axi_bresp <= 2'b0;
    264. end
    265. else
    266. begin
    267. if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
    268. begin
    269. // indicates a valid write response is available
    270. axi_bvalid <= 1'b1;
    271. axi_bresp <= 2'b0; // 'OKAY' response
    272. end // work error responses in future
    273. else
    274. begin
    275. if (S_AXI_BREADY && axi_bvalid)
    276. //check if bready is asserted while bvalid is high)
    277. //(there is a possibility that bready is always asserted high)
    278. begin
    279. axi_bvalid <= 1'b0;
    280. end
    281. end
    282. end
    283. end
    284. // Implement axi_arready generation
    285. // axi_arready is asserted for one S_AXI_ACLK clock cycle when
    286. // S_AXI_ARVALID is asserted. axi_awready is
    287. // de-asserted when reset (active low) is asserted.
    288. // The read address is also latched when S_AXI_ARVALID is
    289. // asserted. axi_araddr is reset to zero on reset assertion.
    290. always @( posedge S_AXI_ACLK )
    291. begin
    292. if ( S_AXI_ARESETN == 1'b0 )
    293. begin
    294. axi_arready <= 1'b0;
    295. axi_araddr <= 32'b0;
    296. end
    297. else
    298. begin
    299. if (~axi_arready && S_AXI_ARVALID)
    300. begin
    301. // indicates that the slave has acceped the valid read address
    302. axi_arready <= 1'b1;
    303. // Read address latching
    304. axi_araddr <= S_AXI_ARADDR;
    305. end
    306. else
    307. begin
    308. axi_arready <= 1'b0;
    309. end
    310. end
    311. end
    312. // Implement axi_arvalid generation
    313. // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
    314. // S_AXI_ARVALID and axi_arready are asserted. The slave registers
    315. // data are available on the axi_rdata bus at this instance. The
    316. // assertion of axi_rvalid marks the validity of read data on the
    317. // bus and axi_rresp indicates the status of read transaction.axi_rvalid
    318. // is deasserted on reset (active low). axi_rresp and axi_rdata are
    319. // cleared to zero on reset (active low).
    320. always @( posedge S_AXI_ACLK )
    321. begin
    322. if ( S_AXI_ARESETN == 1'b0 )
    323. begin
    324. axi_rvalid <= 0;
    325. axi_rresp <= 0;
    326. end
    327. else
    328. begin
    329. if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
    330. begin
    331. // Valid read data is available at the read data bus
    332. axi_rvalid <= 1'b1;
    333. axi_rresp <= 2'b0; // 'OKAY' response
    334. end
    335. else if (axi_rvalid && S_AXI_RREADY)
    336. begin
    337. // Read data is accepted by the master
    338. axi_rvalid <= 1'b0;
    339. end
    340. end
    341. end
    342. // Implement memory mapped register select and read logic generation
    343. // Slave register read enable is asserted when valid address is available
    344. // and the slave is ready to accept the read address.
    345. assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
    346. always @(*)
    347. begin
    348. // Address decoding for reading registers
    349. case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
    350. 2'h0 : reg_data_out <= slv_reg0;
    351. 2'h1 : reg_data_out <= slv_reg1;
    352. 2'h2 : reg_data_out <= slv_reg2;
    353. 2'h3 : reg_data_out <= slv_reg3;
    354. default : reg_data_out <= 0;
    355. endcase
    356. end
    357. // Output register or memory read data
    358. always @( posedge S_AXI_ACLK )
    359. begin
    360. if ( S_AXI_ARESETN == 1'b0 )
    361. begin
    362. axi_rdata <= 0;
    363. end
    364. else
    365. begin
    366. // When there is a valid read address (S_AXI_ARVALID) with
    367. // acceptance of read address by the slave (axi_arready),
    368. // output the read dada
    369. if (slv_reg_rden)
    370. begin
    371. axi_rdata <= reg_data_out; // register read data
    372. end
    373. end
    374. end
    375. // Add user logic here
    376. // User logic ends
    377. endmodule

            从机的代码改造相对主机更加简单,但是想要真正学会AXI协议的IP制作,研读示例代码是必须要去做的事情。

            从机代码改造的逻辑在于寄存器:

             如图,主机会往这些寄存器里写入数据,那么这些寄存器就可以直接和我们功能模块的端口进行对接,以实现参数传递的功能。

    主机写数据--->接口实例--->寄存器-->自定义功能模块                   (数据流向)

            下一节,我想做一期 AXI-Master示例的代码解读。

  • 相关阅读:
    PeLK:101 x 101 的超大卷积网络,同参数量下反超 ViT | CVPR 2024
    找工作笔记
    两个点的距离
    最新Python深度学习技术进阶与应用
    [附源码]SSM计算机毕业设计归元种子销售管理系统JAVA
    three-tile: 三维瓦片地图框架应用示例源码-GitHub
    网络安全(补充)
    Mycat分库分表分片方式
    Java基础面试题【4】
    java毕业设计一点就到家外卖订餐系统Mybatis+系统+数据库+调试部署
  • 原文地址:https://blog.csdn.net/weixin_54358182/article/details/127041949