Day9上午1

讲两种 PS 向 PL 传输数据的办法

昨天数字识别的结果是通过 vio 控制的,如果实现全硬件的数字识别,那也是在 PL 端完成,所以用 PL 端把 vio 换掉就行

但是纯硬件的话会比较难,这边用软件识别的方法作为一个保底

也就是在 vitis 的 main.c 里面编写识别的算法

所以需要一种手段,把识别结果从 main.c 送到 PL 端


打开昨天显示黑框+数字,把 vio 删掉

先讲一种 HI 总线的方案

我们要对官方的 IP 进行一定修改,这边创建一个新的 IP 

image

 选择建一个 HI 通道的

image

 对着他的路径去建立一个文件夹 ip_repo,把这个 IP 存起来

image

孩子们,一定要找到正确的路径啊,狡兔三窟也要修改一个后就全修改啊


 

 这里可以看到他的一个原理图,是一个类似总线的形式,最后是 PS 往 PL 里面写东西

总线模式有三种,前两个比较像,是 HI 接口的一些模式

Life 比较简单,但是处理不了突发的传输,不过本工程无需顾虑,就选 Life 就行

image

因为他相当于是 arm 核上的 CPU 的一个从属存储,所以选 Slave 模式

默认配置是 4 个寄存器,是 32 位

image

image

 左边这个 IP 是验证的,右边这个 IP 是接收的,最后会包装成一个顶层

数据从 M_AXI 到 S00_AXI ,存储到刚才的四个寄存器里面

但是四个寄存器不能作为终点,期望是让他作为输出给到 vga 识别模块,所以要对右边模块进行修改

image


 这里从外部找到这两个 .v 文件

image

这个名称较短的文件,是展示了 IP 核的一个顶层,内化了 AXI 这个模块,以及上面有相应的输入输出

image

image

文件名长的这个是底层,这里就是刚才配置生成的 4 个寄存器,这四个的地址分别是 HI 地址 $+4n$

寄存器地址是以字节为单位,一个比特是 8 位,而 32 位就是 +4

image


 这边我们是让 PS 端往 reg0 那个寄存器里面写东西,想让他作为输出

本文件的第一个括号是参数,第二个括号是接口

把刚才的  reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;  剪切过来,并改为 output 作为输出

   而刚才那个位置就可以删掉了

image

再到刚才顶层的那个 IP

在下面修改,其中 "." 是他在底层的名称,而括号内是在顶层的名称

image

 顶层模块只是把底层模块的输出,连到顶层模块的 OI 口,所以上面只是一个连线,用 wire 的数据类型

image


回到 vivado,可见这里多了这个模块

image

打开之前项目的 design

image

 这边再加入新的 IP

image

 他大概会卡卡的,一开始还是不显示输出端

image

那就是在这里修改

image

image

 让上面那个全是✅️就可以出来了,然后这样刷新一下就好了

image

 有了右边的接口,就如下连线,Run Connection Automation

image

 自动连线后,可见 S00_AXI 连到了 M01

这是说明从 ZYNQ 出来之后,分为两路

一路是给 VDMA 到输出,一路是给到新模块

 

image


 可以跑综合+比特流应用模块了


 vitis 这里可以看到他的地址

 image

这个文件显示了所有的地址信息

image


 

要对之前代码进行修改,下面是新代码

#include <stdio.h>
#include "xil_io.h"
#include "xparameters.h"
#include "xil_types.h"
#include "xil_cache.h"
#include "sleep.h"

#define VDMA_BASEADDR XPAR_AXI_VDMA_0_BASEADDR
#define VDMA_FRAME0 0x01000000             //视频帧缓冲区使用的内存起始地址
#define AXI_LITE_BASEADDR 0x43C00000    //AXI_LITE地址

#define STRIDE    1024
#define HSIZE    1024
#define VSIZE    720

int main(){
    
    //VDMA写通道配置
    Xi1_Out32(VDMA_BASEADDR+θx30,    0x1);
    Xi1_Out32(VDMA_BASEADDR+0xAC,    VDMA_FRAME0);
    Xi1_Out32(VDMA_BASEADDR+0xA8,    STRIDE*2);
    Xi1_Out32(VDMA_BASEADDR+0xA4,    HVSIZE);
    Xi1_Out32(VDMA_BASEADDR+0xA0,    VSIZE*2);
    
    Xi1_Out32(VDMA_BASEADDR,        0x1);//开启VDMA
    Xi1_Out32(VDMA_BASEADDR+θx5c,    VDMA_FRAMEe);//帧缓冲区基地址
    Xi1_Out32(VDMA_BASEADDR+θx58,    STRIDE*2);//步长(字节数,16位像素=2字节/像素)
    Xi1_Out32(VDMA_BASEADDR+0x54,    HSIZE*2);//水平尺寸(字节数)
    Xi1_Out32(VDMA_BASEADDR+θx50,     VSIZE);//垂直尺寸(行数)
    
    for(int i=0; i<=100;i++){
        Xi1_Out32(AXI_LITE_BASEADDR,i%10);
        usleep(100000);
    }

    return 0;
}
新代码

1. 这里要加一个头文件 sleep.h ,进行微秒级的控制

image

image

2.  这里加了一个 AXI 的地址

image

image

 3. 在最后加了一个循环,要往 AXI 这个地址里面写东西,这个循环就是往里面放变化的数字

这个 sleep 模块里面的单位是微秒,也就说0.1秒进行一次循环

posted @ 2026-07-29 14:59  little_sheep_xiaoen  阅读(5)  评论(0)    收藏  举报