<font color="#FD8900">作者:bt(CSDN)</font>
本文使用工程源码已上传https://download.csdn.net/download/botao_li/10891304
从本文档开始将介绍PS和PL之间通过AXI总线互联。
三种AXI总线协议为
① AXI_LITE:性能较低的地址映射传输,一次只能传输4字节
② AXI_STREAM:高速流数据传输,无地址映射,不能直接与PS连接
③ AXI(又称AXI_FULL):性能较高的地址映射传输
AXI_LITE一般用于小规模的数据交互,比如参数、指令或者状态信息
本文档用AXI_LITE总线实现2项功能:
① PS读写PL的寄存器读取板上按钮状态控制LED灯开关
② PL读写PS的DDR内存
<font color="red" style="line-height: 40px;"><strong>axi lite时序</strong></font>
下文中生成的AXI_LITE接口的IP模块自带的示例代码可以修改后使用,AXI_LITE的接口时序来源于示例代码的参考
<font color="#FD8900">写操作时序</font>
master:同时设置awvalid和wvalid有效
slave:等待awvalid和wvalid同时有效,同时将awready和wready设置1
slave:在awvalid awready wvalid wready同时为1的情况下,bvalid设1,同时取出awaddr和wdata
master:收到awready将awvalid设0,收到wready将wvalid设0
master:收到bvalid将bready设1,下个时钟周期设0
slave:收到bready将bvalid设0
<font color="#FD8900">读操作时序</font>
master:设置arvalidy为1
slave:收到arvalid将arready设1,下个时钟周期设0
slave:在arready arvalid同时为1的情况下,rvalid设1,axi_rresp设0有效
master:收到arready将arvalid设0
master:收到rvalid将rready设1,下个时钟周期设0
slave:收到rready将rvalid设1
master:在rready rvalid同时为1的情况下,检查rdata数值
<font color="red" style="line-height: 40px;"><strong>建立工程</strong></font>
与之前相同的方法建立zcu102的Vivado工程
<font color="red" style="line-height: 40px;"><strong>配置Zynq模块</strong></font>
建立Block Design,并添加Zynq模块
选择Run Block Automation
<center><img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
在弹出窗口中按照默认配置选择OK
双击打开Zynq模块配置,在PS-PL Configuration页进行如下配置
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
使用pl_clk0作为PL端工作时钟,并且连接2个AXI接口的aclk
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
<font color="red" style="line-height: 40px;"><strong>自定义Slave AXI_LITE接口的IP模块</strong></font>
在Tools菜单选择Create and Package New IP
<center><img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
在弹出窗口中选中Create AXI4 Peripheral
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center>
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center>
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
选择Edit IP后点击Finish
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
之后弹出当前IP的Vivado工程
在Sources窗口双击打开接口模块
<center><img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
在代码注释中指示的位置**(非必须)**添加自定义的模块端口
注意:端口定义必须加上wire
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
根据代码所示,前述步骤配置的4个32位寄存器分别为slv_reg0~3
若当前IP在PS端的基地址为base_addr,则slv_reg0读写地址为base_addr,slv_reg1读写地址为base_addr+4,svl_reg2和3以此类推
将slv_reg0用于写入PL端LED,slv_reg1用于读取PL端按钮
根据注释位置(位置非必须)添加以下代码
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
并修改读操作赋值
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
打开IP的顶层模块,进行如下修改
<img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt="">
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt="">
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
在当前IP的Vivado工程界面,在Tools菜单选择Create and Package IP
选择Package your current project
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt="">
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
在弹出窗口选择Overwrite
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
最后点击Finish
完成后关闭当前IP的Vivado工程
<font color="red" style="line-height: 40px;"><strong>自定义Master AXI_LITE接口的IP模块</strong></font>
参考[Slave AXI_LITE的模块的生成](#自定义Slave AXI_LITE接口的IP模块),进行如下配置
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
最后选择Edit IP打开IP的Vivado工程
由于默认生成的示例代码过于复杂,因此根据AXI_LITE接口时序全部重写,并添加读写接口
进入Vivado工程后,使用与[自定义Slave接口IP相同的方式](#自定义Slave AXI_LITE接口的IP模块)修改接口模块和顶层模块如下
<font color="#FD8900">接口模块代码</font>
<embed style="overflow-x:auto; background-color:#e9e9e9;" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; width="600px" height="500" />
<font color="#FD8900">顶层模块代码</font>
<embed style="overflow-x:auto; background-color:#e9e9e9;" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; width="600px" height="500" />
最后,参考[Slave AXI_LITE的模块的生成](#自定义Slave AXI_LITE接口的IP模块),打包IP
<font color="red" style="line-height: 40px;"><strong>建立Verilog的master端测试模块</strong></font>
在Sources窗口创建新verilog模块,命名为master_test.v,用于连接master_axi_lite的读写接口进行测试
代码如下:
<embed style="overflow-x:auto; background-color:#e9e9e9;" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; width="600px" height="500" />
<font color="red" style="line-height: 40px;"><strong>实现Vivado工程</strong></font>
回到之前建立的Zynq工程
在PROJECT MANAGER内打开Settings,在IP > Repository页确认前述2个IP的路径已添加
<img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
向Block Design中添加2个自定义的AXI_LITE模块
<img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt="">
<img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""><br>
之后从Sources窗口将master_test.v文件用鼠标拖动至Diagram窗口,自动生成master_test的模块
在Block Design点击Run Connection Automation
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
点击OK后,Block Design完成自动连接
之后手动连接master_test与master_axi_lite模块的接口
完成连接后的Diagram如下:
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
在Block Design上右键菜单执行Generate Output Products,完成后在右键菜单执行Create HDL Wrapper
在Flow Navigator中Run Synthesis,完成后,打开Synthesized Design,从Layout菜单打开I/O Planning窗口设置button和leds管脚
保存并新建xdc约束文件top.xdc
接下来在Flow Navigator中SYNTHESIS下选择Set Up Debug,添加master_test中的测试信号
最终的top.xdc文件内容如下:
<pre>set_property PACKAGE_PIN AG14 [get_ports {leds_0[0]}]
set_property PACKAGE_PIN AF13 [get_ports {leds_0[1]}]
set_property PACKAGE_PIN AE13 [get_ports {leds_0[2]}]
set_property PACKAGE_PIN AJ14 [get_ports {leds_0[3]}]
set_property PACKAGE_PIN AJ15 [get_ports {leds_0[4]}]
set_property PACKAGE_PIN AH13 [get_ports {leds_0[5]}]
set_property PACKAGE_PIN AH14 [get_ports {leds_0[6]}]
set_property PACKAGE_PIN AL12 [get_ports {leds_0[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[2]}]
set_property PACKAGE_PIN AF15 [get_ports button_0]
set_property IOSTANDARD LVCMOS33 [get_ports button_0]
create_debug_core u_ila_0 ila
set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0]
set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0]
set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0]
set_property C_DATA_DEPTH 2048 [get_debug_cores u_ila_0]
set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0]
set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0]
set_property C_TRIGIN_EN false [get_debug_cores u_ila_0]
set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0]
set_property port_width 1 [get_debug_ports u_ila_0/clk]
connect_debug_port u_ila_0/clk [get_nets [list bd_i/zynq_ultra_ps_e_0/inst/pl_clk0]]
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0]
set_property port_width 32 [get_debug_ports u_ila_0/probe0]
connect_debug_port u_ila_0/probe0 [get_nets [list {bd_i/master_test_0/rd_data[0]} {bd_i/master_test_0/rd_data[1]} {bd_i/master_test_0/rd_data[2]} {bd_i/master_test_0/rd_data[3]} {bd_i/master_test_0/rd_data[4]} {bd_i/master_test_0/rd_data[5]} {bd_i/master_test_0/rd_data[6]} {bd_i/master_test_0/rd_data[7]} {bd_i/master_test_0/rd_data[8]} {bd_i/master_test_0/rd_data[9]} {bd_i/master_test_0/rd_data[10]} {bd_i/master_test_0/rd_data[11]} {bd_i/master_test_0/rd_data[12]} {bd_i/master_test_0/rd_data[13]} {bd_i/master_test_0/rd_data[14]} {bd_i/master_test_0/rd_data[15]} {bd_i/master_test_0/rd_data[16]} {bd_i/master_test_0/rd_data[17]} {bd_i/master_test_0/rd_data[18]} {bd_i/master_test_0/rd_data[19]} {bd_i/master_test_0/rd_data[20]} {bd_i/master_test_0/rd_data[21]} {bd_i/master_test_0/rd_data[22]} {bd_i/master_test_0/rd_data[23]} {bd_i/master_test_0/rd_data[24]} {bd_i/master_test_0/rd_data[25]} {bd_i/master_test_0/rd_data[26]} {bd_i/master_test_0/rd_data[27]} {bd_i/master_test_0/rd_data[28]} {bd_i/master_test_0/rd_data[29]} {bd_i/master_test_0/rd_data[30]} {bd_i/master_test_0/rd_data[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1]
set_property port_width 32 [get_debug_ports u_ila_0/probe1]
connect_debug_port u_ila_0/probe1 [get_nets [list {bd_i/master_test_0/rd_addr[0]} {bd_i/master_test_0/rd_addr[1]} {bd_i/master_test_0/rd_addr[2]} {bd_i/master_test_0/rd_addr[3]} {bd_i/master_test_0/rd_addr[4]} {bd_i/master_test_0/rd_addr[5]} {bd_i/master_test_0/rd_addr[6]} {bd_i/master_test_0/rd_addr[7]} {bd_i/master_test_0/rd_addr[8]} {bd_i/master_test_0/rd_addr[9]} {bd_i/master_test_0/rd_addr[10]} {bd_i/master_test_0/rd_addr[11]} {bd_i/master_test_0/rd_addr[12]} {bd_i/master_test_0/rd_addr[13]} {bd_i/master_test_0/rd_addr[14]} {bd_i/master_test_0/rd_addr[15]} {bd_i/master_test_0/rd_addr[16]} {bd_i/master_test_0/rd_addr[17]} {bd_i/master_test_0/rd_addr[18]} {bd_i/master_test_0/rd_addr[19]} {bd_i/master_test_0/rd_addr[20]} {bd_i/master_test_0/rd_addr[21]} {bd_i/master_test_0/rd_addr[22]} {bd_i/master_test_0/rd_addr[23]} {bd_i/master_test_0/rd_addr[24]} {bd_i/master_test_0/rd_addr[25]} {bd_i/master_test_0/rd_addr[26]} {bd_i/master_test_0/rd_addr[27]} {bd_i/master_test_0/rd_addr[28]} {bd_i/master_test_0/rd_addr[29]} {bd_i/master_test_0/rd_addr[30]} {bd_i/master_test_0/rd_addr[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2]
set_property port_width 32 [get_debug_ports u_ila_0/probe2]
connect_debug_port u_ila_0/probe2 [get_nets [list {bd_i/master_test_0/wr_addr[0]} {bd_i/master_test_0/wr_addr[1]} {bd_i/master_test_0/wr_addr[2]} {bd_i/master_test_0/wr_addr[3]} {bd_i/master_test_0/wr_addr[4]} {bd_i/master_test_0/wr_addr[5]} {bd_i/master_test_0/wr_addr[6]} {bd_i/master_test_0/wr_addr[7]} {bd_i/master_test_0/wr_addr[8]} {bd_i/master_test_0/wr_addr[9]} {bd_i/master_test_0/wr_addr[10]} {bd_i/master_test_0/wr_addr[11]} {bd_i/master_test_0/wr_addr[12]} {bd_i/master_test_0/wr_addr[13]} {bd_i/master_test_0/wr_addr[14]} {bd_i/master_test_0/wr_addr[15]} {bd_i/master_test_0/wr_addr[16]} {bd_i/master_test_0/wr_addr[17]} {bd_i/master_test_0/wr_addr[18]} {bd_i/master_test_0/wr_addr[19]} {bd_i/master_test_0/wr_addr[20]} {bd_i/master_test_0/wr_addr[21]} {bd_i/master_test_0/wr_addr[22]} {bd_i/master_test_0/wr_addr[23]} {bd_i/master_test_0/wr_addr[24]} {bd_i/master_test_0/wr_addr[25]} {bd_i/master_test_0/wr_addr[26]} {bd_i/master_test_0/wr_addr[27]} {bd_i/master_test_0/wr_addr[28]} {bd_i/master_test_0/wr_addr[29]} {bd_i/master_test_0/wr_addr[30]} {bd_i/master_test_0/wr_addr[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3]
set_property port_width 32 [get_debug_ports u_ila_0/probe3]
connect_debug_port u_ila_0/probe3 [get_nets [list {bd_i/master_test_0/wr_data[0]} {bd_i/master_test_0/wr_data[1]} {bd_i/master_test_0/wr_data[2]} {bd_i/master_test_0/wr_data[3]} {bd_i/master_test_0/wr_data[4]} {bd_i/master_test_0/wr_data[5]} {bd_i/master_test_0/wr_data[6]} {bd_i/master_test_0/wr_data[7]} {bd_i/master_test_0/wr_data[8]} {bd_i/master_test_0/wr_data[9]} {bd_i/master_test_0/wr_data[10]} {bd_i/master_test_0/wr_data[11]} {bd_i/master_test_0/wr_data[12]} {bd_i/master_test_0/wr_data[13]} {bd_i/master_test_0/wr_data[14]} {bd_i/master_test_0/wr_data[15]} {bd_i/master_test_0/wr_data[16]} {bd_i/master_test_0/wr_data[17]} {bd_i/master_test_0/wr_data[18]} {bd_i/master_test_0/wr_data[19]} {bd_i/master_test_0/wr_data[20]} {bd_i/master_test_0/wr_data[21]} {bd_i/master_test_0/wr_data[22]} {bd_i/master_test_0/wr_data[23]} {bd_i/master_test_0/wr_data[24]} {bd_i/master_test_0/wr_data[25]} {bd_i/master_test_0/wr_data[26]} {bd_i/master_test_0/wr_data[27]} {bd_i/master_test_0/wr_data[28]} {bd_i/master_test_0/wr_data[29]} {bd_i/master_test_0/wr_data[30]} {bd_i/master_test_0/wr_data[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4]
set_property port_width 1 [get_debug_ports u_ila_0/probe4]
connect_debug_port u_ila_0/probe4 [get_nets [list bd_i/master_test_0/rd_done]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5]
set_property port_width 1 [get_debug_ports u_ila_0/probe5]
connect_debug_port u_ila_0/probe5 [get_nets [list bd_i/master_test_0/rd_en]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6]
set_property port_width 1 [get_debug_ports u_ila_0/probe6]
connect_debug_port u_ila_0/probe6 [get_nets [list bd_i/master_test_0/rd_valid]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7]
set_property port_width 1 [get_debug_ports u_ila_0/probe7]
connect_debug_port u_ila_0/probe7 [get_nets [list bd_i/master_test_0/wr_done]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8]
set_property port_width 1 [get_debug_ports u_ila_0/probe8]
connect_debug_port u_ila_0/probe8 [get_nets [list bd_i/master_test_0/wr_en]]
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets u_ila_0_pl_clk0]
</pre>
在Flow Navigator中PROGRAM AND DEBUG选择Generate Bitstream
完成后在File菜单选择Export > Export Hardware,注意选中Include bitstream
<center><img src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
之后在File菜单选择Launch SDK
<font color="red" style="line-height: 40px;"><strong>SDK编程</strong></font>
默认建立的bd_wrapper_hw_platform_0工程目录中已包含前文生成的bit配置文件
根据HelloWorld模板建立test_axi_lite工程
SDK工程用于测试slave_axi_lite,即按钮控制led开关
修改helloworld.c文件代码如下:
<embed style="overflow-x:auto; background-color:#e9e9e9;" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; width="600px" height="480" />
在test_axi_lite工程选择Debug Configurations
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
配置如下:
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
注意,一定不能在Vivado中加载FPGA,再启动PS程序。PL程序会在PS载入过程中被清除!!!
在SDK中启动调试
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
发现按钮控制led开关功能正确
回到Vivado,从Hardware Manager进入Debugl界面,测试发现master_test运行正确:
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-09/%E5%8D%9A%E5%AE%A2/100045103-80…; alt=""></center><br>
版权声明:本文为CSDN博主「bt_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/botao_li/article/details/85630090