ZYNQ-使用自定义AXI总线IP核进行DDR读写测试(二)

简介: ZYNQ-使用自定义AXI总线IP核进行DDR读写测试

添加按键消抖IP


image.png

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

image.png

系统复位后, 状态机处于初始状态,在该状态下等待外部输入的启动传输脉冲 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完成配置)

image.png

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

image.png

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

image.png

然后我们进行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流文件。

image.png

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~\n\r");
  while(1){
    scanf("%c",chardata);
    if(chardata="y"){
      printf("start\r\n");
      for(i=0;i<4096;i=i+4){
        printf("%d is %d\n",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\n",i,(int)(Xil_In32(0x10000000+i)));对相应地址的数据进行读取显示。

运行效果


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

image.png

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

image.png

如何波形进行debug?


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

image.png

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

image.png

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

image.png

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

image.png

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

image.png

目录
相关文章
|
3月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
25天前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
219 2
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
25天前
|
机器学习/深度学习 JSON 算法
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
本文介绍了DeepLab V3在语义分割中的应用,包括数据集准备、模型训练、测试和评估,提供了代码和资源链接。
144 0
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
|
25天前
|
机器学习/深度学习 算法 PyTorch
目标检测实战(五): 使用YOLOv5-7.0版本对图像进行目标检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-7.0版本进行目标检测的完整流程,包括算法介绍、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。YOLOv5以其高精度、快速度和模型小尺寸在计算机视觉领域受到广泛应用。
244 0
目标检测实战(五): 使用YOLOv5-7.0版本对图像进行目标检测完整版(从自定义数据集到测试验证的完整流程)
|
1月前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
18 0
|
4月前
|
存储 Web App开发 Java
《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)
【7月更文挑战第13天】这篇文章介绍了如何在Java中创建一个简单的自定义日志系统,以替代Log4j或logback。
292 5
|
3月前
|
SQL 缓存 关系型数据库
MySQL配置简单优化与读写测试
MySQL配置简单优化与读写测试
|
4月前
|
XML 测试技术 数据格式
《手把手教你》系列基础篇(八十五)-java+ selenium自动化测试-框架设计基础-TestNG自定义日志-下篇(详解教程)
【7月更文挑战第3天】TestNG教程展示了如何自定义日志记录。首先创建一个名为`TestLog`的测试类,包含3个测试方法,其中一个故意失败以展示日志。使用`Assert.assertTrue`和`Reporter.log`来记录信息。接着创建`CustomReporter`类,继承`TestListenerAdapter`,覆盖`onTestFailure`, `onTestSkipped`, 和 `onTestSuccess`,在这些方法中自定义日志输出。
50 6
|
5月前
|
数据采集 安全 网络安全
代理IP纯净度如何测试?
代理IP的纯净度关乎网络隐私、稳定性和安全性。纯净IP能保护用户身份,提供稳定连接,降低被识别为恶意访问的风险,并确保数据安全。测试纯净度包括检查IP历史、黑名单状态、SSL支持、匿名度及网络性能。在网络安全至关重要的今天,纯净代理IP是重要保障。
|
5月前
|
JavaScript Java 测试技术
《手把手教你》系列技巧篇(七十一)-java+ selenium自动化测试-自定义类解决元素同步问题(详解教程)
【6月更文挑战第12天】本文介绍了如何创建一个自定义类库来解决自动化测试中的元素同步问题。作者指出,大部分错误源于元素因时间不同步而引发,为此提供了一种解决方案。在项目实践中,首先在`library`包下创建名为`MyWait`的类,包含一个方法`isElementPresent`,该方法通过循环尝试并等待指定元素出现,避免了直接使用时间等待可能导致的不准确性。之后,在测试类中调用此自定义方法,成功实现了元素同步。代码示例展示了如何在Java+Selenium自动化测试中应用这个自定义类。
57 2