0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用AXI-Full接口的IP进行DDR的读写测试

FPGA之家 来源:CSDN 作者:Vuko-wxh 2022-07-18 09:53 次阅读

学习内容

本文首先进行自定义IP的AXI总线IP的设计,然后在SDK下编写代码进行DDR的读写数据的测试。

开发环境

vivado 18.3&SDKPYNQ-Z2开发板

系统框图

首先对本次工程进行简要说明:本次工程使用AXI-Full接口的IP进行DDR的读写测试。在我们的DDR读写IP中,我们把读写完成和读写错误信号关联到PL端的LED上,用于指示DDR读写IP的读写运行状态。然后使用PL部分消抖处理后的按键进行启动AXI总线工作,控制数据写入。通过AXI互联模块连接到AXI_HP0端口,由PS端口进行数据的读取操作,并通过串口进行读写数据的监控。pYYBAGLUvaaAO6XJAADNvLJIgRs591.jpg

自定义IP设计

首先打开Vivado软件,在Tasks这里选择New IP lacation

pYYBAGLUvd-ACdbiAABua1bs3Q0706.jpg

点击next,对IP的信息进行设置,这里我们使用默认配置即可。设置好我们IP要保存的位置。

pYYBAGLUvfeAFFyrAACnp8gLUGw995.jpg

点击Tools中的创建和封装新的IP选项,

poYBAGLUvhuAeE9FAAEoh3_cWvg980.jpg

点击NEXT ,选择我们的封装类型。因为这里我们是直接进行打开IP设计的界面,前两个选项是可以在我们的vivado当前工程下面进行封装设计,这里我们只进行了IP设计没有建立工程,所以前两个选项是无法选中的。我们也可以通过工程界面,进入点击Tools中的创建和封装新的IP选项。

poYBAGLUvkiABDIMAADAe_CgTXQ316.jpg

这里是用DDR读写IP来做主机,控制数据写入,PS作为从机进行读取IP中写入的数据。

poYBAGLUvmGAYs8sAACvY_BPA7Q036.jpg

可以直接选中进行编辑IP,用户可以根据自己的设计进行修改编辑IP的功能,这里没有对IP进行修改处理,所以可以直接保存选择第一个添加到IP库中即可。poYBAGLUvniAYb5jAADUz1w-kew197.jpg

若修改相应的逻辑功能打开IP,在对应位置编辑添加代码即可。

poYBAGLUvpKAEv8jAAC-SdZJ3ag510.jpg

添加完成综合后对IP进行重新打包。DDR读写IP设计完成,创建的 IP 核将通过 AXI4 Master 端口向 Slave 端指定的 4K 存储空间中连续写入 1024 个数据, 写入的数值从 1 累加到 1024, 每个数据占 32bit。然后进行硬件平台的构建。

硬件平台构建

首先,添加ZYNQ7 IP核,以及添加已经完成设计的ddr读写IP核。

添加用户自定义IP

用户自定义的IP可通过以下步骤完成添加。点击Settings,

poYBAGLUv6iAFPyfAAD4DSU52ZE818.jpg

在project settings选择IP,依次点击,在IP库那里点击加号,把对应的IP目录文件夹添加后,点击OK或者Apply即可完成添加,在IP库中就可以找到用户设计的IP。

poYBAGLUv7-AVlyxAADZpe6vJnU483.jpg

完成IP和ZYNQ7 IP的导入后,如下图:

pYYBAGLUv9SADRg_AACmGmBsULY185.jpg

双击打开zynq删除多余的接口,这里只需要保留uart,并打开Slave HP0端口、时钟、复位端口。

pYYBAGLUv-mAMZ-LAAD5l36TuIA990.jpg
poYBAGLUwACAW9nYAAEaUjbSIYE282.jpg
pYYBAGLUwBWAOl4qAAEGuRUv9Vk221.jpg

配置完,选择自动连接接口,完成部分连接设计。

pYYBAGLUwCiAXfUlAACZ8qfpjpo680.jpg

整体设计图如下,

pYYBAGLUwDuAErT7AACuhz9p7N4226.jpg

添加按键消抖IP

pYYBAGLUwFOAFkGuAACHbMdxz4c065.jpg

由于ddr读写IP的axi_init_axi_txn接入的是按键,这里按键按下会产生抖动,axi_init_axi_txn与好多读写信号关联,如果不添加消抖IP,在按键按下的时,产生的毛刺会进行影响后续的操作,从而导致读写操作的错误,也就是读写操作的指示灯会亮起。

pYYBAGLUwGuALaHZAACeCniyL-E421.jpg

系统复位后, 状态机处于初始状态,在该状态下等待外部输入的启动传输脉冲 init_txn_pulse。一旦检测到 init_txn_pulse 为高电平,状态机跳转到 INIT_WRITE 状态。在 INIT_WRITE 状态下, 状态机拉高 start_single_burst_write 信号, 来不断地启动 AXI4 Master 接口对Slave 端大小为 4KB 的存储空间进行突发写操作。写操作完成后, write_done 信号会拉高,状态机进入INIT_READ 状态。在 INIT_READ 状态下, 状态机拉高 start_single_burst_read 信号, 不断地启动 AXI4 Master 接口对 Slave端同一存储空间进行突发读操作, 同时将读出的数据与写入的数据进行对比。读操作完成后, read_done 信号拉高,状态机进入 INIT_COMPARE 状态。在 INIT_COMPARE 状态下, 判断 AXI4 接口在读写过程中的是否发生错误, 并将错误状态赋值给ERROR 信号, 然后将 compare_done 信号拉高,表示一次读写测试完成。最后跳转到 IDLE 状态,等待下一次读写操作的启动信号。这里的消抖模块直接添加之前写过的按键消抖模块即可,这里给出我的设计:

module key_filter(
Clk,      //50M时钟输入
Rst_n,    //模块复位
key_in,   //按键输入
key_flag, //按键标志信号
key_state //按键状态信号
);

input Clk;
input Rst_n;
input key_in;

output reg key_flag;
output reg key_state;

localparam
IDEL= 4'b0001,
FILTER0= 4'b0010,
DOWN= 4'b0100,
FILTER1 = 4'b1000;

reg [3:0]state;
reg [19:0]cnt;
reg en_cnt;//使能计数寄存器

//对外部输入的异步信号进行同步处理
reg key_in_sa,key_in_sb;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
key_in_sa <= 1'b0;
key_in_sb <= 1'b0;
end
else begin
key_in_sa <= key_in;
key_in_sb <= key_in_sa;
end

reg key_tmpa,key_tmpb;
wire pedge,nedge;
reg cnt_full;//计数满标志信号

//使用D触发器存储两个相邻时钟上升沿时外部输入信号(已经同步到系统时钟域中)的电平状态
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
key_tmpa <= 1'b0;
key_tmpb <= 1'b0;
end
else begin
key_tmpa <= key_in_sb;
key_tmpb <= key_tmpa;
end

//产生跳变沿信号
assign nedge = !key_tmpa & key_tmpb;
assign pedge = key_tmpa & (!key_tmpb);

always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
en_cnt <= 1'b0;
state <= IDEL;
key_flag <= 1'b0;
key_state <= 1'b1;
end
else begin
case(state)
IDEL :
begin
key_flag <= 1'b0;
if(nedge)begin
state <= FILTER0;
en_cnt <= 1'b1;
end
else
state <= IDEL;
end

FILTER0:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b0;
en_cnt <= 1'b0;
state <= DOWN;
end
else if(pedge)begin
state <= IDEL;
en_cnt <= 1'b0;
end
else
state <= FILTER0;

DOWN:
begin
key_flag <= 1'b0;
if(pedge)begin
state <= FILTER1;
en_cnt <= 1'b1;
end
else
state <= DOWN;
end

FILTER1:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b1;
state <= IDEL;
en_cnt <= 1'b0;
end
else if(nedge)begin
en_cnt <= 1'b0;
state <= DOWN;
end
else
state <= FILTER1;

default:
begin 
state <= IDEL; 
en_cnt <= 1'b0;
key_flag <= 1'b0;
key_state <= 1'b1;
end

endcase
end



always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 20'd0;
else if(en_cnt)
cnt <= cnt + 1'b1;
else
cnt <= 20'd0;

always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt_full <= 1'b0;
else if(cnt == 20'd999_999)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;

endmodule

添加完模块后系统设计如下:注:axi_init_axi_txn是上升沿有效,这里为了保证系统上电后是初始默认随机状态,要确保按键未按下给启动脉冲时,是低电平。因为PYNQZ2开发板按键默认电位是低,按下为高,这里不用进行处理,若按键按下后为低,默认拉高,这里可以对按键进行添加非逻辑的IP进行取反。(使用 utility vector logic IP完成配置)

pYYBAGLUwIaALS_fAAD68Czzad8486.jpg

双击DDR读写的IP核进行配置,这里没有用到user的接口所以都设置为0,如图:

pYYBAGLUwJqAJ5MsAADn9RQGLk4990.jpg

对于Base address,我们可以查看下接口的地址范围,避免数据操作超过可操作范围,这里我们就取中间值0X10000000。

poYBAGLUwK2AYJ35AACMfjhmlww326.jpg

然后我们进行generate output product 然后生成HDL封装。接着就对应引脚进行引脚约束即可(PYNQ的粉色开发板可以直接引用这个约束):

##LEDs
set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { m0_axi_error_0 }]; #IO_L6N_T0_VREF_34 Sch=led[0]
set_property -dict { PACKAGE_PIN P14   IOSTANDARD LVCMOS33 } [get_ports { m0_axi_txn_done_0}]; #IO_L6P_T0_34 Sch=led[1]

##Buttons
set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports { key }]; #IO_L4P_T0_35 Sch=btn[0]

完成约束后进行综合布局布线,等待生成bit流文件。

poYBAGLUwMSAco7DAACV94ZYr9Y653.jpg

bit文件生成后在FILE处,点击导出硬件资源(包含bit流文件),接着launch SDK。

SDK软件部分

打开SDK后,新建application project。在main.c中输入以下代码:

#include "stdio.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_io.h"
int main(){
int i;
char chardata;
Xil_DCacheDisable();
printf("AXI4-FULL RW TEST~

");
while(1){
scanf("%c",chardata);
if(chardata="y"){
printf("start
");
for(i=0;i<4096;i=i+4){
printf("%d is %d
",i,(int)(Xil_In32(0x10000000+i)));
}
}
}
return 0;
}

代码简要说明

这里使用的IP我们设定成不需要进行缓存的,所以在main函数中调用Xil_DCacheDisable();。使用Xil_In32(),对DDR对应位置的数据进行读取。参数只需要传递所要读取的地址即可。因为一次写入的数据是32位的,每个地址的数据位宽是8位,所以在for循环中使用了i=i+4。

在串口中使用printf("%d is %d ",i,(int)(Xil_In32(0x10000000+i)));对相应地址的数据进行读取显示。

运行效果

当按键未按下时,也就是未进行写入操作直接读取数据,DDR中的数据是默认的随机状态,如下所示:

pYYBAGLUwOCASjXAAACEo9Cvmvs368.jpg

当按键按下后,IP完成数据写入操作,数据是从1-1024自增的

poYBAGLUwPaALuQFAADuMKaD0XY062.jpg

如何波形进行debug?

这里我们选中要进行DEBUG的数据信号右击选中debug


poYBAGLUwQyAU7ulAACFBd-cCPc264.jpg

然后点击自动连接,完成debug功能搭建

pYYBAGLUwSGAH797AACUjZ-uvnQ516.jpg

综合后会多出ILA的IP进行波形分析帮助DEBUG。

poYBAGLUwTaAfPOLAAA10xprmRg156.jpg

然后打开硬件设备,如下图在ila界面即可看到我们debug的波形数据了。

poYBAGLUwU2AWu4-AAF0R7VMSXE599.jpg

添加触发条件,标号2是单次触发,标号1是一直运行debug抓取波形。

pYYBAGLUwVyAOqXOAAGcBZHMWR4164.jpg


审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • DDR
    DDR
    +关注

    关注

    11

    文章

    712

    浏览量

    65318
  • AXI总线
    +关注

    关注

    0

    文章

    66

    浏览量

    14261
  • SDK
    SDK
    +关注

    关注

    3

    文章

    1035

    浏览量

    45909
  • AXI
    AXI
    +关注

    关注

    1

    文章

    127

    浏览量

    16625

原文标题:如何波形进行debug?

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何使用AXI VIP在AXI4(Full)主接口中执行验证和查找错误

    AXI 基础第 2 讲 一文中,曾提到赛灵思 Verification IP (AXI VIP) 可用作为 AXI 协议检查工具。在本次第4讲中,我们将来了解下如何使用它在
    发表于 07-08 09:31 2895次阅读

    XILINX FPGA IPAXI Traffic Generator

    AXI Traffic Generator IP 用于在AXI4和AXI4-Stream互连以及其他AXI4系统外设上生成特定序列(流量)。
    的头像 发表于 11-23 16:03 2561次阅读
    XILINX FPGA <b class='flag-5'>IP</b>之<b class='flag-5'>AXI</b> Traffic Generator

    例说FPGA连载41:DDR控制器集成与读写测试DDR2 IP接口描述

    `例说FPGA连载41:DDR控制器集成与读写测试DDR2 IP接口描述特权同学,版权所有配
    发表于 10-27 16:36

    ZYNQ调用XDMA PCIE IP同时读写PS DDR,导致蓝屏问题。

    你好!我在ZYNQ 7015里(或者7035)调用XDMA PCIE IP 从上位机HOST PC通过PCIE接口给ZYNQ的PS DDR发送数据(XDMA PCIE IP接到了PS的
    发表于 11-21 10:35

    如何用zedboard创建一个AXI接口应用程序?

    FULL支持突发传输)。在我的vivado设计中,我使用AXI CDMA作为DDR RAM,BRAM以及定制从AXI的主设备。zynq为AXI
    发表于 08-12 10:37

    【正点原子FPGA连载】第九章AXI4接口DDR读写实验--摘自【正点原子】达芬奇之Microblaze 开发指南

    Vivado中实现一个AXI4接口IP核,用于对DDR3进行读写
    发表于 10-22 15:16

    XILINX MIG(DDR3) IPAXI接口与APP接口的区别以及优缺点对比

    XILINX MIG(DDR3) IPAXI接口与APP接口的区别以及优缺点对比
    发表于 11-24 21:47

    AXI接口简介_AXI IP核的创建流程及读写逻辑分析

    本文包含两部分内容:1)AXI接口简介;2)AXI IP核的创建流程及读写逻辑分析。 1AXI
    的头像 发表于 06-29 09:33 1.6w次阅读
    <b class='flag-5'>AXI</b><b class='flag-5'>接口</b>简介_<b class='flag-5'>AXI</b> <b class='flag-5'>IP</b>核的创建流程及<b class='flag-5'>读写</b>逻辑分析

    FPGA程序设计:如何封装AXI_SLAVE接口IP

    M_AXI接口对数据进行读取操作,此时设计一个基于AXI-Slave接口IP
    的头像 发表于 10-30 12:32 4387次阅读
    FPGA程序设计:如何封装<b class='flag-5'>AXI</b>_SLAVE<b class='flag-5'>接口</b><b class='flag-5'>IP</b>

    全面介绍ZYNQ-AXI互联IP

    学习内容 近期设计需要用到AXI总线的IP,所以就对应常用的IP进行简要的说明,本文主要对AXI互联IP
    的头像 发表于 05-11 14:52 6461次阅读
    全面介绍ZYNQ-<b class='flag-5'>AXI</b>互联<b class='flag-5'>IP</b>

    简单讲解AXI Interconnect IP核的使用方法

    最近需要用到AXI接口的模块,xilinx的IP核很多都用到了AXI总线进行数据和指令传输。如果有多个设备需要使用
    的头像 发表于 06-19 15:45 1w次阅读
    简单讲解<b class='flag-5'>AXI</b> Interconnect <b class='flag-5'>IP</b>核的使用方法

    基于AXI总线的DDR3读写测试

    本文开源一个FPGA项目:基于AXI总线的DDR3读写。之前的一篇文章介绍了DDR3简单用户接口读写
    的头像 发表于 09-01 16:20 4509次阅读
    基于<b class='flag-5'>AXI</b>总线的<b class='flag-5'>DDR</b>3<b class='flag-5'>读写</b><b class='flag-5'>测试</b>

    基于FPGA的DDR3读写测试

    本文介绍一个FPGA开源项目:DDR3读写。该工程基于MIG控制器IP核对FPGA DDR3实现读写操作。
    的头像 发表于 09-01 16:23 1655次阅读
    基于FPGA的<b class='flag-5'>DDR</b>3<b class='flag-5'>读写</b><b class='flag-5'>测试</b>

    AXI传输数据的过程

    AXI4为例,有AXI full/lite/stream之分。 在Xilinx系列FPGA及其有关IP核中,经常见到AXI总线
    的头像 发表于 10-31 15:37 1138次阅读
    <b class='flag-5'>AXI</b>传输数据的过程

    AXI通道读写DDR的阻塞问题?

    基于vivado2020.1和zcu102开发板(rev1.1)开发项目,工程涉及DDR4(MIG)和PL端多个读写接口交互的问题,通过AXI interconnect
    的头像 发表于 12-01 09:04 1062次阅读
    <b class='flag-5'>AXI</b>通道<b class='flag-5'>读写</b><b class='flag-5'>DDR</b>的阻塞问题?