AXI协议 AXI4 、 AXI4-Lite 、AXI4-Stream接口 AXI 作为 ARM AMBA 微控制器总线的一部分,第一次出现在AMBA 3.0中。后面AMBA 4.0发布,AXI4出现了。
AXI 4总线和别的总线一样,都用来传输bits信息(包含了数据或者地址)。AXI4总线有三种类型,分别是AXI4、AXI4-Lite、AXI4-Stream。
AXI4 是一种高性能memory-mapped总线,AXI4-Lite是一只简单的、低通量的memory-mapped 总线,而 AXI4-Stream 可以传输高速数据流。从字面意思去理解,AXI4-Lite是AXI4的轻量版。这里保留了memory-mapped的写法,主要是为了与AXI4-Stream区分开。
memory-mapped 可以这样去理解,假设有master A , 和 slave B, A与B通过AXI4或者AXI4-Lite连接通讯,A可以把B这个外设看作A上的某个地址。当A向B传输数据时,就等同于A向这个地址传输数据。
AXI4-Stream与AXI4、AXI4-Lite不同, 它不需要地址通道。
AXI4 和 AXI4-Lite接口包含5个不同的通道:两个读通道和三个写通道。
两个读通道:读地址通道(read address channel)、读数据通道(read data channel);
三个写通道:写地址通道(write address channel)、写数据通道(write data channel)、写响应通道(write response channel);
读通道和写通道是分开的,因此可以完成数据的双向传输。此外AXI4能够实现burs t传输,换句说就是,可以在一个地址后传输多个数据,最多可以达256 字节。AXI4-Lite不支持burst传输。
AXI4-Stream 只有一个通道,不需要地址,可以burst 传输无限的数据。
常见的辅助IP AXI Interconnect IP 和AXI SmartConnect IP :
AXI Interconnect IP允许将任意组合的AXI主设备和从设备连接到它,这些设备在数据宽度、时钟域和AXI子协议(AXI4、AXI3或AXI4-Lite)方面可能互不相同。当任何连接的主设备或从设备的接口特性与互连内部的交叉开关不同时,将自动推断并连接适当的基础架构 IP在互连内执行必要的转换。
Vivado中的smartConnect和InterConnect有什么区别?
1 2 Both IP have the same functionnalities. AXI SmartConnect is the successor to AXI Interconnect, it uses a different IP technology. You should use it for any new design.
UG994
1 2 3 The AMD LogiCORE™ IP AXI InterConnect and SmartConnect cores both connect one or more AXI memory-mapped master devices to one or more memory-mapped slave devices There are certain cases for high bandwidth application where using a SmartConnect provides better optimization. The SmartConnect IP delivers the maximum system throughput at low latency by synthesizing a low area custom interconnect that is optimized for important interfaces.
SmartConnect比InterConnect的性能更好,延时更低,带宽更大。
AXI FIFOs :
缓存数据,或者跨时钟 域时有用。
AXI Direct Memory Ac cess (DMA ) engines
当我们有一个AXI4-stream接口的IP想与AXI4接口的IP相连时,可以通过AXI DMA完成转换。
ZYNQ上的AXI接口
图片源自 zynq 7 processing system ip
zynq的ps上共留了9个AXI接口,其中两个GP AXI master、两个GP AXI slave、四个HP AXI slave、以及一个ACP AXI slave。
这些接口都是AXI3类型的,但使用AXI4-Lite、AXI4 的IP仍然可以与这些接口通讯,因为在实际使用中,软件会使用AXI Interconnect ip帮助我们完成接口的转换。
主要参考
[1] ug1037-vivado-axi-reference-guide
[2] ug585-Zynq-7000-TRM
AXI LITE
AXI4和AXI3的主要区别 主要区别如下:
AXI4支持更长的突发传输(AxLEN从4bit扩展为8bit,相应的突发长度最大可以到256);
增加了QoS信号,以提供服务质量。减少延迟,便于仲裁;
多Slave Region(即AxRegion信号);
移除了WID信号,因此不支持写数据interleave;
AxLOCK从2bit变为1bit,不再支持Lock Transfer;
写响应必须在写数据和写地址全部给了以后才允许返回(之前可以在给了写数据以后就返回写响应);
将Cacheable改为Modifyable
Write
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ___ ___ ___ ___ ___ clk ___/ \___/ \___/ \___/ \___/ \___ _______ awid XXXX_ID____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ awaddr XXXX_ADDR__XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ awlen XXXX_00____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ awsize XXXX_0_____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ awburst XXXX_0_____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ awprot XXXX_PROT__XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ awvalid ___/ \_______________________________ ___________ _______________________ awready \_______/ _______________ wdata XXXX_DATA__________XXXXXXXXXXXXXXXXXXXXXXXX _______________ wstrb XXXX_STRB__________XXXXXXXXXXXXXXXXXXXXXXXX _______________ wvalid ___/ \_______________________ _______ wready ___________/ \_______________________ _______ bid XXXXXXXXXXXXXXXXXXXXXXXXXXXX_ID____XXXXXXXX _______ bresp XXXXXXXXXXXXXXXXXXXXXXXXXXXX_RESP__XXXXXXXX _______ bvalid ___________________________/ \_______ ___________________________________________ bready
Read
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ___ ___ ___ ___ ___ clk ___/ \___/ \___/ \___/ \___/ \___ _______ arid XXXX_ID____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ araddr XXXX_ADDR__XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ arlen XXXX_00____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ arsize XXXX_0_____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ arburst XXXX_0_____XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ arprot XXXX_PROT__XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX _______ arvalid ___/ \_______________________________ ___________________________________________ arready _______ rid XXXXXXXXXXXXXXXXXXXXXXXXXXXX_ID____XXXXXXXX _______ rdata XXXXXXXXXXXXXXXXXXXXXXXXXXXX_DATA__XXXXXXXX _______ rresp XXXXXXXXXXXXXXXXXXXXXXXXXXXX_RESP__XXXXXXXX _______ rvalid ___________________________/ \_______ ___________________________________________ rready
1 创建Vivado IP工程 1 ) 具体步骤 新建一个VIVADO 工程,打开软件 选中Create Project, 如下图所示
2)点击NEXT ,在出现的第二个对话框“Project name”中输入工程名;在“Project location”中选择保存路径;勾选“Create project subdirectory”,最后点击“Next” 备注,所有的路径均不能出现中文名称
3) 第四步Add Sources 选项直接留空,NEXT
4)第五步Add Constraints 选项直接留空,NEXT
5)选择芯片型号 我们板子上用的芯片是XC7Z010 ,并在列表栏中选择对应的封装型号,完整型号是XC7Z010CLG400-1 如下所示,选中后点NEXT
6)确认所选信息 点击“Finish”,完成vivado的工程创建
7)创建verilog源文件
8)创建文件并命名为axi_ram.v
9)提示添加约束接口留空即可。
10)编辑axi_ram.v,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 module axi_ram # ( parameter DATA_WIDTH = 32 , parameter ADDR_WIDTH = 16 , parameter STRB_WIDTH = (DATA_WIDTH/8 ), parameter ID_WIDTH = 8 , parameter PIPELINE_OUTPUT = 0 ) ( input wire clk, input wire rst, input wire [ID_WIDTH-1 :0 ] s_axi_awid, input wire [ADDR_WIDTH-1 :0 ] s_axi_awaddr, input wire [7 :0 ] s_axi_awlen, input wire [2 :0 ] s_axi_awsize, input wire [1 :0 ] s_axi_awburst, input wire s_axi_awlock, input wire [3 :0 ] s_axi_awcache, input wire [2 :0 ] s_axi_awprot, input wire s_axi_awvalid, output wire s_axi_awready, input wire [DATA_WIDTH-1 :0 ] s_axi_wdata, input wire [STRB_WIDTH-1 :0 ] s_axi_wstrb, input wire s_axi_wlast, input wire s_axi_wvalid, output wire s_axi_wready, output wire [ID_WIDTH-1 :0 ] s_axi_bid, output wire [1 :0 ] s_axi_bresp, output wire s_axi_bvalid, input wire s_axi_bready, input wire [ID_WIDTH-1 :0 ] s_axi_arid, input wire [ADDR_WIDTH-1 :0 ] s_axi_araddr, input wire [7 :0 ] s_axi_arlen, input wire [2 :0 ] s_axi_arsize, input wire [1 :0 ] s_axi_arburst, input wire s_axi_arlock, input wire [3 :0 ] s_axi_arcache, input wire [2 :0 ] s_axi_arprot, input wire s_axi_arvalid, output wire s_axi_arready, output wire [ID_WIDTH-1 :0 ] s_axi_rid, output wire [DATA_WIDTH-1 :0 ] s_axi_rdata, output wire [1 :0 ] s_axi_rresp, output wire s_axi_rlast, output wire s_axi_rvalid, input wire s_axi_rready );parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2 (STRB_WIDTH);parameter WORD_WIDTH = STRB_WIDTH;parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH;initial begin if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin $error ("Error: AXI data width not evenly divisble (instance %m)" ); $finish ; end if (2 **$clog2 (WORD_WIDTH) != WORD_WIDTH) begin $error ("Error: AXI word width must be even power of two (instance %m)" ); $finish ; end end localparam [0 :0 ] READ_STATE_IDLE = 1'd0 , READ_STATE_BURST = 1'd1 ;reg [0 :0 ] read_state_reg = READ_STATE_IDLE, read_state_next;localparam [1 :0 ] WRITE_STATE_IDLE = 2'd0 , WRITE_STATE_BURST = 2'd1 , WRITE_STATE_RESP = 2'd2 ;reg [1 :0 ] write_state_reg = WRITE_STATE_IDLE, write_state_next;reg mem_wr_en;reg mem_rd_en;reg [ID_WIDTH-1 :0 ] read_id_reg = {ID_WIDTH{1'b0 }}, read_id_next;reg [ADDR_WIDTH-1 :0 ] read_addr_reg = {ADDR_WIDTH{1'b0 }}, read_addr_next;reg [7 :0 ] read_count_reg = 8'd0 , read_count_next;reg [2 :0 ] read_size_reg = 3'd0 , read_size_next;reg [1 :0 ] read_burst_reg = 2'd0 , read_burst_next;reg [ID_WIDTH-1 :0 ] write_id_reg = {ID_WIDTH{1'b0 }}, write_id_next;reg [ADDR_WIDTH-1 :0 ] write_addr_reg = {ADDR_WIDTH{1'b0 }}, write_addr_next;reg [7 :0 ] write_count_reg = 8'd0 , write_count_next;reg [2 :0 ] write_size_reg = 3'd0 , write_size_next;reg [1 :0 ] write_burst_reg = 2'd0 , write_burst_next;reg s_axi_awready_reg = 1'b0 , s_axi_awready_next;reg s_axi_wready_reg = 1'b0 , s_axi_wready_next;reg [ID_WIDTH-1 :0 ] s_axi_bid_reg = {ID_WIDTH{1'b0 }}, s_axi_bid_next;reg s_axi_bvalid_reg = 1'b0 , s_axi_bvalid_next;reg s_axi_arready_reg = 1'b0 , s_axi_arready_next;reg [ID_WIDTH-1 :0 ] s_axi_rid_reg = {ID_WIDTH{1'b0 }}, s_axi_rid_next;reg [DATA_WIDTH-1 :0 ] s_axi_rdata_reg = {DATA_WIDTH{1'b0 }}, s_axi_rdata_next;reg s_axi_rlast_reg = 1'b0 , s_axi_rlast_next;reg s_axi_rvalid_reg = 1'b0 , s_axi_rvalid_next;reg [ID_WIDTH-1 :0 ] s_axi_rid_pipe_reg = {ID_WIDTH{1'b0 }};reg [DATA_WIDTH-1 :0 ] s_axi_rdata_pipe_reg = {DATA_WIDTH{1'b0 }};reg s_axi_rlast_pipe_reg = 1'b0 ;reg s_axi_rvalid_pipe_reg = 1'b0 ;reg [DATA_WIDTH-1 :0 ] mem[(2 **VALID_ADDR_WIDTH)-1 :0 ];wire [VALID_ADDR_WIDTH-1 :0 ] s_axi_awaddr_valid = s_axi_awaddr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);wire [VALID_ADDR_WIDTH-1 :0 ] s_axi_araddr_valid = s_axi_araddr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);wire [VALID_ADDR_WIDTH-1 :0 ] read_addr_valid = read_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH);wire [VALID_ADDR_WIDTH-1 :0 ] write_addr_valid = write_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH);assign s_axi_awready = s_axi_awready_reg;assign s_axi_wready = s_axi_wready_reg;assign s_axi_bid = s_axi_bid_reg;assign s_axi_bresp = 2'b00 ;assign s_axi_bvalid = s_axi_bvalid_reg;assign s_axi_arready = s_axi_arready_reg;assign s_axi_rid = PIPELINE_OUTPUT ? s_axi_rid_pipe_reg : s_axi_rid_reg;assign s_axi_rdata = PIPELINE_OUTPUT ? s_axi_rdata_pipe_reg : s_axi_rdata_reg;assign s_axi_rresp = 2'b00 ;assign s_axi_rlast = PIPELINE_OUTPUT ? s_axi_rlast_pipe_reg : s_axi_rlast_reg;assign s_axi_rvalid = PIPELINE_OUTPUT ? s_axi_rvalid_pipe_reg : s_axi_rvalid_reg;integer i, j;initial begin for (i = 0 ; i < 2 **VALID_ADDR_WIDTH; i = i + 2 **(VALID_ADDR_WIDTH/2 )) begin for (j = i; j < i + 2 **(VALID_ADDR_WIDTH/2 ); j = j + 1 ) begin mem[j] = 0 ; end end end always @* begin write_state_next = WRITE_STATE_IDLE; mem_wr_en = 1'b0 ; write_id_next = write_id_reg; write_addr_next = write_addr_reg; write_count_next = write_count_reg; write_size_next = write_size_reg; write_burst_next = write_burst_reg; s_axi_awready_next = 1'b0 ; s_axi_wready_next = 1'b0 ; s_axi_bid_next = s_axi_bid_reg; s_axi_bvalid_next = s_axi_bvalid_reg && !s_axi_bready; case (write_state_reg) WRITE_STATE_IDLE: begin s_axi_awready_next = 1'b1 ; if (s_axi_awready && s_axi_awvalid) begin write_id_next = s_axi_awid; write_addr_next = s_axi_awaddr; write_count_next = s_axi_awlen; write_size_next = s_axi_awsize < $clog2 (STRB_WIDTH) ? s_axi_awsize : $clog2 (STRB_WIDTH); write_burst_next = s_axi_awburst; s_axi_awready_next = 1'b0 ; s_axi_wready_next = 1'b1 ; write_state_next = WRITE_STATE_BURST; end else begin write_state_next = WRITE_STATE_IDLE; end end WRITE_STATE_BURST: begin s_axi_wready_next = 1'b1 ; if (s_axi_wready && s_axi_wvalid) begin mem_wr_en = 1'b1 ; if (write_burst_reg != 2'b00 ) begin write_addr_next = write_addr_reg + (1 << write_size_reg); end write_count_next = write_count_reg - 1 ; if (write_count_reg > 0 ) begin write_state_next = WRITE_STATE_BURST; end else begin s_axi_wready_next = 1'b0 ; if (s_axi_bready || !s_axi_bvalid) begin s_axi_bid_next = write_id_reg; s_axi_bvalid_next = 1'b1 ; s_axi_awready_next = 1'b1 ; write_state_next = WRITE_STATE_IDLE; end else begin write_state_next = WRITE_STATE_RESP; end end end else begin write_state_next = WRITE_STATE_BURST; end end WRITE_STATE_RESP: begin if (s_axi_bready || !s_axi_bvalid) begin s_axi_bid_next = write_id_reg; s_axi_bvalid_next = 1'b1 ; s_axi_awready_next = 1'b1 ; write_state_next = WRITE_STATE_IDLE; end else begin write_state_next = WRITE_STATE_RESP; end end endcase end always @(posedge clk) begin write_state_reg <= write_state_next; write_id_reg <= write_id_next; write_addr_reg <= write_addr_next; write_count_reg <= write_count_next; write_size_reg <= write_size_next; write_burst_reg <= write_burst_next; s_axi_awready_reg <= s_axi_awready_next; s_axi_wready_reg <= s_axi_wready_next; s_axi_bid_reg <= s_axi_bid_next; s_axi_bvalid_reg <= s_axi_bvalid_next; for (i = 0 ; i < WORD_WIDTH; i = i + 1 ) begin if (mem_wr_en & s_axi_wstrb[i]) begin mem[write_addr_valid][WORD_SIZE*i +: WORD_SIZE] <= s_axi_wdata[WORD_SIZE*i +: WORD_SIZE]; end end if (rst) begin write_state_reg <= WRITE_STATE_IDLE; s_axi_awready_reg <= 1'b0 ; s_axi_wready_reg <= 1'b0 ; s_axi_bvalid_reg <= 1'b0 ; end end always @* begin read_state_next = READ_STATE_IDLE; mem_rd_en = 1'b0 ; s_axi_rid_next = s_axi_rid_reg; s_axi_rlast_next = s_axi_rlast_reg; s_axi_rvalid_next = s_axi_rvalid_reg && !(s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg)); read_id_next = read_id_reg; read_addr_next = read_addr_reg; read_count_next = read_count_reg; read_size_next = read_size_reg; read_burst_next = read_burst_reg; s_axi_arready_next = 1'b0 ; case (read_state_reg) READ_STATE_IDLE: begin s_axi_arready_next = 1'b1 ; if (s_axi_arready && s_axi_arvalid) begin read_id_next = s_axi_arid; read_addr_next = s_axi_araddr; read_count_next = s_axi_arlen; read_size_next = s_axi_arsize < $clog2 (STRB_WIDTH) ? s_axi_arsize : $clog2 (STRB_WIDTH); read_burst_next = s_axi_arburst; s_axi_arready_next = 1'b0 ; read_state_next = READ_STATE_BURST; end else begin read_state_next = READ_STATE_IDLE; end end READ_STATE_BURST: begin if (s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg) || !s_axi_rvalid_reg) begin mem_rd_en = 1'b1 ; s_axi_rvalid_next = 1'b1 ; s_axi_rid_next = read_id_reg; s_axi_rlast_next = read_count_reg == 0 ; if (read_burst_reg != 2'b00 ) begin read_addr_next = read_addr_reg + (1 << read_size_reg); end read_count_next = read_count_reg - 1 ; if (read_count_reg > 0 ) begin read_state_next = READ_STATE_BURST; end else begin s_axi_arready_next = 1'b1 ; read_state_next = READ_STATE_IDLE; end end else begin read_state_next = READ_STATE_BURST; end end endcase end always @(posedge clk) begin read_state_reg <= read_state_next; read_id_reg <= read_id_next; read_addr_reg <= read_addr_next; read_count_reg <= read_count_next; read_size_reg <= read_size_next; read_burst_reg <= read_burst_next; s_axi_arready_reg <= s_axi_arready_next; s_axi_rid_reg <= s_axi_rid_next; s_axi_rlast_reg <= s_axi_rlast_next; s_axi_rvalid_reg <= s_axi_rvalid_next; if (mem_rd_en) begin s_axi_rdata_reg <= mem[read_addr_valid]; end if (!s_axi_rvalid_pipe_reg || s_axi_rready) begin s_axi_rid_pipe_reg <= s_axi_rid_reg; s_axi_rdata_pipe_reg <= s_axi_rdata_reg; s_axi_rlast_pipe_reg <= s_axi_rlast_reg; s_axi_rvalid_pipe_reg <= s_axi_rvalid_reg; end if (rst) begin read_state_reg <= READ_STATE_IDLE; s_axi_arready_reg <= 1'b0 ; s_axi_rvalid_reg <= 1'b0 ; s_axi_rvalid_pipe_reg <= 1'b0 ; end end endmodule
11) 点击Create and package New IP创建我们自己ip
12) 直接下一步
13)选择打包当前工程
14)默认下一步即可
14)点击finish
15)配置IP核参数,保持默认即可。
16) 直接到最后一步 package IP。
17)显示打包完成,到此创建完成我们自己的axi ram ip核。
2 创建Vivado BLOCK工程 1 ) 具体步骤 新建一个VIVADO 工程,打开软件 选中Create Project, 如下图所示
2)点击NEXT ,在出现的第二个对话框“Project name”中输入工程名;在“Project location”中选择保存路径;勾选“Create project subdirectory”,最后点击“Next” 备注,所有的路径均不能出现中文名称
3) 第四步Add Sources 选项直接留空,NEXT
4)第五步Add Constraints 选项直接留空,NEXT
5)选择芯片型号 我们板子上用的芯片是XC7Z010 ,并在列表栏中选择对应的封装型号,完整型号是XC7Z010CLG400-1 如下所示,选中后点NEXT
6)确认所选信息 点击“Finish”,完成vivado的工程创建
7)IP INTEGRATOR→Create Block Design,在弹出的对话框中输入设计名,最后点击“OK”,如下图所示
8)在右侧的窗口里 ,点击加号,在选择框里搜索ZYNQ,并找到ZYNQ7 PROCESSING SYSTEM ,双击并打开
9)软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
10)添加串口UART 1引脚为MIO 24-24, 串口在调试时用到。
11)此项目没有用到DDR,可以取消ENABLE
12)加入上面我们自己创建的axi ram ip核到当前工程,选择Tool下的Settings.
13)添加IP工程路径到Repository。
14)提示添加路径下包含的IP核。
15)完成IP的添加
16)在BLOCK设计中添加我们自己的IP核。
17)点击自动连接
17)选择a_axi后确认。
18)自动连接完成后的框图
18)由于我们的IP核的rst是高有效,所以重新连接rst引脚。
19)到此完成了我们的BLOCK设计,点击生成顶层工程
20) 选择自动更新
3.生成bit文件 21 )按下Generate Bitstream 完成综合以及生成bit文件
22) 生成bit流后,选择导出Hardware
4.SDK程序编写 1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
系统将自动打开SDK开发环境
3)新建一个工程 file→new→Application Project,来新建一个“Application Project”,如下图所示。
4)在新建工程名中输入自己的工程名称,点击NEXT
5)选择空工程,点击完成FINISH
6)编写测试程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "xparameters.h" #include <xil_io.h> #include <sleep.h> #define PhyRead(addr) Xil_In32(addr) #define PhyWrite(addr, value) Xil_Out32(addr, value) #define AXILITE_BASEADDR XPAR_AXI_RAM_0_BASEADDR int main () { init_platform(); print("Hello World\n\r" ); for (int i=0 ;i<20 ;i++) { sleep(1 ); printf ("i is %d\n\r" ,i); } int reg0in = 320 ; int reg0out = 0 ; PhyWrite(AXILITE_BASEADDR, reg0in); reg0out = PhyRead(AXILITE_BASEADDR); printf ("reg0out is %d\r\n" ,reg0out); cleanup_platform(); return 0 ; }
5.下载到板子上进行验证 选中工程中的硬件平台,并点击右键→Program FPGA,在弹出的对话框中选择默认,点击“program”,完成FPGA PL部分的Program工作
2)选中我们生成的GPIO工程 展开绿色箭头(RUN)右边的图标,选择Run As→1 Launch on Hardware(System Debugger)
6.查看串口打印 显示读写成功
AXI4 、 AXI4-Lite 、AXI4-Stream接口
https://www.elecfans.com/d/1856571.html
FPGA - AXI4_Lite(实现用户端与axi4_lite之间的交互逻辑)_axi4-lite-CSDN博客