☰
【正点原子ZYNQ领航者7020】PL读写PS DDR实验
2026/10/13 10:19:09 网站建设 项目流程

文章目录

    • 前言
      • 1.创建Vivado工程
      • 2.创建axi4_rw_testIP核。
      • 3.创建axi4_rw_testIP核
      • 4.添加tb文件
      • 5.开始仿真
      • 6.搭建bd文件
      • 7.创建vitis工程并编写代码
    • 总结

前言

本文仅作个人学习记录,不具有参考价值。以下操作均基于 hello world 实验工程进行修改,读者需提前准备好可正常运行的 hello world 工程作为基础。

1.创建Vivado工程

在 hello world 工程的基础上,打开 Vivado 并加载已有工程,进入 Block Design 设计界面。


2.创建axi4_rw_testIP核。

在 IP Catalog 中搜索并创建名为 axi4_rw_test 的 AXI 主机 IP 核。创建过程中需根据向导提示配置 AXI 接口参数,包括地址宽度、数据宽度、突发长度等,保持默认配置即可。创建完成后,该 IP 核会自动添加到当前工程的 IP 库中,并可在 Block Design 中通过 Add IP 的方式将其添加到设计中,用于后续对 DDR 进行读写测试。

3.创建axi4_rw_testIP核

在 IP Catalog 中搜索并创建名为 axi4_rw_test 的 AXI 主机 IP 核。创建过程中需根据向导提示配置 AXI 接口参数,包括地址宽度、数据宽度、突发长度等,保持默认配置即可。

创建完成后,该 IP 核会自动添加到当前工程的 IP 库中,并可在 Block Design 中通过 Add IP 的方式将其添加到设计中,用于后续对 DDR 进行读写测试。
打开 axi4_slave_v1_0_S_AXI.v 文件(位于 D:\ldy\VivadoProjects\VIvado2020.3\ATK\Navigator7020\pl_rw_ddr\ip_repo\axi4_slave_1.0\hdl 目录下),对该从机 IP 核的 Verilog 源码进行两处关键修改:

找到always@(mem_data_out, axi_rvalid)语句,将其替换为always@(*)。这样修改的目的是让组合逻辑块对所有的输入信号变化都敏感,避免因敏感列表不完整而导致仿真时出现信号更新不及时的问题,确保读数据通道在仿真中能正确响应地址变化。

找到localparam integer OPT_MEM_ADDR_BITS = 7;语句,将其替换为localparam integer OPT_MEM_ADDR_BITS = 12;。该参数定义了从机内部存储器的地址位宽,修改后从机的存储空间由原来的 128 字节扩展到 4096 字节,从而能够覆盖主机在测试中访问的整个地址范围,保证读写测试的完整性。

4.添加tb文件

在D:\ldy\VivadoProjects\VIvado2020.3\ATK\Navigator7020\pl_rw_ddr\pl_rw_ddr.sim\tb中创建tb_axi4_rw_test_v1_0_M_AXI.v:

//****************************************Copyright (c)***********************************////原子哥在线教学平台:www.yuanzige.com//技术支持:http://www.openedv.com/forum.php//淘宝店铺:https://zhengdianyuanzi.tmall.com//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。//版权所有,盗版必究。//Copyright(C) 正点原子 2023-2033//All rights reserved//----------------------------------------------------------------------------------------// File name: tb_flow_led// Created by: 正点原子// Created date: 2023年1月31日11:12:36// Version: V1.0// Descriptions: LED灯闪烁激励文件////----------------------------------------------------------------------------------------//****************************************************************************************//`timescale1ns/1ns//仿真单位/仿真精度moduletb_axi4_rw_test_v1_0_M_AXI();//parameter defineparameter CLK_PERIOD=20;//时钟周期 20nsparameter C_M_AXI_TARGET_SLAVE_BASE_ADDR=32'h40000000;parameter integer C_M_AXI_BURST_LEN=16;parameter integer C_M_AXI_ID_WIDTH=1;parameter integer C_M_AXI_ADDR_WIDTH=32;parameter integer C_M_AXI_DATA_WIDTH=32;parameter integer C_M_AXI_AWUSER_WIDTH=0;parameter integer C_M_AXI_ARUSER_WIDTH=0;parameter integer C_M_AXI_WUSER_WIDTH=0;parameter integer C_M_AXI_RUSER_WIDTH=0;parameter integer C_M_AXI_BUSER_WIDTH=0;parameter integer C_S_AXI_ID_WIDTH=1;parameter integer C_S_AXI_DATA_WIDTH=32;parameter integer C_S_AXI_ADDR_WIDTH=32;parameter integer C_S_AXI_AWUSER_WIDTH=0;parameter integer C_S_AXI_ARUSER_WIDTH=0;parameter integer C_S_AXI_WUSER_WIDTH=0;parameter integer C_S_AXI_RUSER_WIDTH=0;parameter integer C_S_AXI_BUSER_WIDTH=0;//reg definereg sys_clk;reg sys_rst_n;reg key_init=0;//wire definewire compare_done;wire error_flag;wire[C_M_AXI_ID_WIDTH-1:0]m_axi_awid;wire[C_M_AXI_ADDR_WIDTH-1:0]m_axi_awaddr;wire[7:0]m_axi_awlen;wire[2:0]m_axi_awsize;wire[1:0]m_axi_awburst;wire m_axi_awlock;wire[3:0]m_axi_awcache;wire[2:0]m_axi_awprot;wire[3:0]m_axi_awqos;wire[C_M_AXI_AWUSER_WIDTH-1:0]m_axi_awuser;wire m_axi_awvalid;wire m_axi_awready;wire[C_M_AXI_DATA_WIDTH-1:0]m_axi_wdata;wire[C_M_AXI_DATA_WIDTH/8-1:0]m_axi_wstrb;wire m_axi_wlast;wire[C_M_AXI_WUSER_WIDTH-1:0]m_axi_wuser;wire m_axi_wvalid;wire m_axi_wready;wire[C_M_AXI_ID_WIDTH-1:0]m_axi_bid;wire[1:0]m_axi_bresp;wire[C_M_AXI_BUSER_WIDTH-1:0]m_axi_buser;wire m_axi_bvalid;wire m_axi_bready;wire[C_M_AXI_ID_WIDTH-1:0]m_axi_arid;wire[C_M_AXI_ADDR_WIDTH-1:0]m_axi_araddr;wire[7:0]m_axi_arlen;wire[2:0]m_axi_arsize;wire[1:0]m_axi_arburst;wire m_axi_arlock;wire[3:0]m_axi_arcache;wire[2:0]m_axi_arprot;wire[3:0]m_axi_arqos;wire[C_M_AXI_ARUSER_WIDTH-1:0]m_axi_aruser;wire m_axi_arvalid;wire m_axi_arready;wire[C_M_AXI_ID_WIDTH-1:0]m_axi_rid;wire[C_M_AXI_DATA_WIDTH-1:0]m_axi_rdata;wire[1:0]m_axi_rresp;wire m_axi_rlast;wire[C_M_AXI_RUSER_WIDTH-1:0]m_axi_ruser;wire m_axi_rvalid;wire m_axi_rready;//信号初始化initial begin sys_clk<=1'b0;sys_rst_n<=1'b0;key_init<=1'b0;#200sys_rst_n<=1'b1;#1000key_init<=1'b1;end//产生时钟always #(CLK_PERIOD/2)sys_clk=~sys_clk;axi4_rw_test_v1_0_M_AXI #(.C_M_TARGET_SLAVE_BASE_ADDR(C_M_AXI_TARGET_SLAVE_BASE_ADDR),.C_M_AXI_BURST_LEN(C_M_AXI_BURST_LEN),.C_M_AXI_ID_WIDTH(C_M_AXI_ID_WIDTH),.C_M_AXI_ADDR_WIDTH(C_M_AXI_ADDR_WIDTH),.C_M_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH),.C_M_AXI_AWUSER_WIDTH(C_M_AXI_AWUSER_WIDTH),.C_M_AXI_ARUSER_WIDTH(C_M_AXI_ARUSER_WIDTH),.C_M_AXI_WUSER_WIDTH(C_M_AXI_WUSER_WIDTH),.C_M_AXI_RUSER_WIDTH(C_M_AXI_RUSER_WIDTH),.C_M_AXI_BUSER_WIDTH(C_M_AXI_BUSER_WIDTH))axi4_rw_test_v1_0_M_AXI_inst(.INIT_AXI_TXN(key_init),.TXN_DONE(compare_done),.ERROR(error_flag),.M_AXI_ACLK(sys_clk),.M_AXI_ARESETN(sys_rst_n),.M_AXI_AWID(m_axi_awid),.M_AXI_AWADDR(m_axi_awaddr),.M_AXI_AWLEN(m_axi_awlen),.M_AXI_AWSIZE(m_axi_awsize),.M_AXI_AWBURST(m_axi_awburst),.M_AXI_AWLOCK(m_axi_awlock),.M_AXI_AWCACHE(m_axi_awcache),.M_AXI_AWPROT(m_axi_awprot),.M_AXI_AWQOS(m_axi_awqos),.M_AXI_AWUSER(m_axi_awuser),.M_AXI_AWVALID(m_axi_awvalid),.M_AXI_AWREADY(m_axi_awready),.M_AXI_WDATA(m_axi_wdata),.M_AXI_WSTRB(m_axi_wstrb),.M_AXI_WLAST(m_axi_wlast),.M_AXI_WUSER(m_axi_wuser),.M_AXI_WVALID(m_axi_wvalid),.M_AXI_WREADY(m_axi_wready),.M_AXI_BID(m_axi_bid),.M_AXI_BRESP(m_axi_bresp),.M_AXI_BUSER(m_axi_buser),.M_AXI_BVALID(m_axi_bvalid),.M_AXI_BREADY(m_axi_bready),.M_AXI_ARID(m_axi_arid),.M_AXI_ARADDR(m_axi_araddr),.M_AXI_ARLEN(m_axi_arlen),.M_AXI_ARSIZE(m_axi_arsize),.M_AXI_ARBURST(m_axi_arburst),.M_AXI_ARLOCK(m_axi_arlock),.M_AXI_ARCACHE(m_axi_arcache),.M_AXI_ARPROT(m_axi_arprot),.M_AXI_ARQOS(m_axi_arqos),.M_AXI_ARUSER(m_axi_aruser),.M_AXI_ARVALID(m_axi_arvalid),.M_AXI_ARREADY(m_axi_arready),.M_AXI_RID(m_axi_rid),.M_AXI_RDATA(m_axi_rdata),.M_AXI_RRESP(m_axi_rresp),.M_AXI_RLAST(m_axi_rlast),.M_AXI_RUSER(m_axi_ruser),.M_AXI_RVALID(m_axi_rvalid),.M_AXI_RREADY(m_axi_rready));axi4_slave_v1_0_S_AXI #(.C_S_AXI_ID_WIDTH(C_S_AXI_ID_WIDTH),.C_S_AXI_DATA_WIDTH(C_S_AXI_DATA_WIDTH),.C_S_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH),.C_S_AXI_AWUSER_WIDTH(C_S_AXI_AWUSER_WIDTH),.C_S_AXI_ARUSER_WIDTH(C_S_AXI_ARUSER_WIDTH),.C_S_AXI_WUSER_WIDTH(C_S_AXI_WUSER_WIDTH),.C_S_AXI_RUSER_WIDTH(C_S_AXI_RUSER_WIDTH),.C_S_AXI_BUSER_WIDTH(C_S_AXI_BUSER_WIDTH))axi4_slave_v1_0_S_AXI_inst(.S_AXI_ACLK(sys_clk),.S_AXI_ARESETN(sys_rst_n),.S_AXI_AWID(m_axi_awid),.S_AXI_AWADDR(m_axi_awaddr),.S_AXI_AWLEN(m_axi_awlen),.S_AXI_AWSIZE(m_axi_awsize),.S_AXI_AWBURST(m_axi_awburst),.S_AXI_AWLOCK(m_axi_awlock),.S_AXI_AWCACHE(m_axi_awcache),.S_AXI_AWPROT(m_axi_awprot),.S_AXI_AWQOS(m_axi_awqos),.S_AXI_AWREGION(m_axi_awregion),.S_AXI_AWUSER(m_axi_awuser),.S_AXI_AWVALID(m_axi_awvalid),.S_AXI_AWREADY(m_axi_awready),.S_AXI_WDATA(m_axi_wdata),.S_AXI_WSTRB(m_axi_wstrb),.S_AXI_WLAST(m_axi_wlast),.S_AXI_WUSER(m_axi_wuser),.S_AXI_WVALID(m_axi_wvalid),.S_AXI_WREADY(m_axi_wready),.S_AXI_BID(m_axi_bid),.S_AXI_BRESP(m_axi_bresp),.S_AXI_BUSER(m_axi_buser),.S_AXI_BVALID(m_axi_bvalid),.S_AXI_BREADY(m_axi_bready),.S_AXI_ARID(m_axi_arid),.S_AXI_ARADDR(m_axi_araddr),.S_AXI_ARLEN(m_axi_arlen),.S_AXI_ARSIZE(m_axi_arsize),.S_AXI_ARBURST(m_axi_arburst),.S_AXI_ARLOCK(m_axi_arlock),.S_AXI_ARCACHE(m_axi_arcache),.S_AXI_ARPROT(m_axi_arprot),.S_AXI_ARQOS(m_axi_arqos),.S_AXI_ARREGION(m_axi_arregion),.S_AXI_ARUSER(m_axi_aruser),.S_AXI_ARVALID(m_axi_arvalid),.S_AXI_ARREADY(m_axi_arready),.S_AXI_RID(m_axi_rid),.S_AXI_RDATA(m_axi_rdata),.S_AXI_RRESP(m_axi_rresp),.S_AXI_RLAST(m_axi_rlast),.S_AXI_RUSER(m_axi_ruser),.S_AXI_RVALID(m_axi_rvalid),.S_AXI_RREADY(m_axi_rready));endmodule

5.开始仿真


在仿真文件中加入这三个文件,记住将tb_axi4_rw_test_v1_0_M_AXI.v设为顶层
之后开启仿真:

在打开的wave窗口,删除modelsim自己给的信号,并添加axi4_rw_test_v1_0_M_AXI_inst的信号进入wave窗口

添加之后:

修改进制为10进制:

在命令行中输入run 100us得到以下结果:


(若要将modelsim中的信号分组,选中要分组的信号邮件点击group…;若要修改信号颜色:右击信号选择,Properties…,在波形窗口ctrl+s可以保存wave.do将界面及设置保存下来,之后在波形界面点击file+Load…选中保存的wave.do可以将波形界面复现)

6.搭建bd文件

在工程中加入key_debounce,右击选择block design界面选择add module:


再加入axi4_rw_testIP核,修改基地址:

再加入Utility Vector Logic核,改逻辑为not,并设置位宽为1
连接如图信号:


之后点击自动连接
若要更换互联模块为AXI SmartConnect,可以先删除AXI Interconnect,然后添加AXI SmartConnect,AXI SmartConnect的设置如下:
并连线




接下来将key引出端口并改名:

以及这两个端口:

创建pin.xdc:

#----------------------PL_KEY---------------------------set_property-dict{PACKAGE_PIN L14 IOSTANDARD LVCMOS33}[get_ports key_init]#----------------------PL_LED---------------------------#底板 set_property-dict{PACKAGE_PIN H15 IOSTANDARD LVCMOS33}[get_ports compare_done]set_property-dict{PACKAGE_PIN L15 IOSTANDARD LVCMOS33}[get_ports error_flag]

之后,老流程生成xsa文件。

7.创建vitis工程并编写代码

老步骤:创建工程,并新建main.c:

#include"stdio.h"#include"xil_printf.h"#include"xil_io.h"#include"xil_cache.h"#defineRW_DDR_BASE_ADDRESS0x10000000intmain(){charc;intdata;printf("AXI4 PL write and read PS DDR test \r\n");// Xil_DCacheDisable();while(1){scanf("%c",&c);if(c=='c'){Xil_DCacheInvalidateRange(RW_DDR_BASE_ADDRESS,4096);printf("PS start read DDR");for(inti=0;i<4096;i=i+4){data=Xil_In32(RW_DDR_BASE_ADDRESS+i);printf("Address is %d, Data is %d.\r\n",i,data);}}}}

总结

工程分享:
pl_rw_ddr.zip

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询