整体设计
先将图片rgb数据存入DDR中,之后配置vdma从DDR中读取数据并输出。
Block Design框图:
主要模块有MicroBlaze(软核),Video Timing Controller(vtc,控制hdmi时序用的,主要信号有场同步信号vs,行同步信号hs,有效信号de等),VDMA(Video DMA,通过AXI总线从DDR里读取图片数据),Vid Out模块(将信号整合),最后将VGA信号转成HDMI的差分信号。
Microblaze设置
就是个CPU,充当ZYNQ里面的硬核用,但是性能比不上而已,相比硬核可能需要初始化配置啥的
初始化配置
首先允许外部存储BRAM作为程序运行缓冲区
然后允许AXI数据流
DDR4设置
其他默认。
在添加完软核和ddr之后,可以点击自动连接,自动连接后查验一下跟bd的连线的区别,复位和时钟建议自己改一下,自动连的也不一定好用。如果ddr如上图设置,ddr的输出时钟为300MHz。
Video Timing control,VTC
vtc模块用于根据需求产生对应的行/场同步信号等时序信号
可以输入参考的video timing,也可以不输入。
也可以用核配置vtc,用核链接AXI4-Lite线即可。
主要需要连接的是左下角的那几个。
clk为核的工作时钟,用像素时钟即可。
clken是时钟使能,高有效的。
gen_aclken和det_aclken分别是生成模式工作时钟使能和探测模式工作时钟使能。(高有效)。
resetn复位 低有效
irq为中断信号输出,高有效
fsync_out为帧同步输出
输出信号中,Blank信号感觉不是必要的,因为active部分的de是为高的。
hdmi时序图
主要信号为行同步信号hs和场同步信号vs,hs为高之后开始一行的打印,vs为高之后开始打印一帧(一个图像),de为高时为显示区域,为低时为显示区域外的(hblank与vblank)。
另外hs和vs不一定是高有效,也有可能是低有效,其实就是个同步信号,高低影响不大,如果低有效如图:
VTC核设置
不用观测输入,也不用灵活配置分辨率就这样配置。
因为要显示的图片为800600的,查一下可以知道这些参数怎么配置了,另外要是60Hz输出的的话,计算1056628*60可得像素时钟为40MHz。
VDMA
vdma就是一个帧缓冲器,把数据从DDR中拿出来之后一帧一帧往外送。
帧缓冲区(frame buffers)设置三个,stream数据位宽设置为rgb的24位。
因为也就是个图片的输出,暂时用不到帧同步啥的,同步选项就如图设置就可以,如果是视频输出,同步(synchronization)很重要。
设置好了之后,具体的配置是在PS端用AXI-Lite对VDMA的寄存器进行配置的。
Vid Out
vtg_ce和sof_state_out要接回vtc。
vid_io_out_clk接像素时钟,aclk接axi总线的时钟(ddr生成的300MHz就可以)。
PS端代码
#include "xparameters.h"
#include "xil_io.h"
#include "xil_cache.h"
#include "image_rgb_800600.h"
#define VDMA_BASEADDR XPAR_AXI_VDMA_0_BASEADDR //vdma
#define H_ACTIVE 800 //
#define V_ACTIVE 600
#define H_STRIDE 800*3 //VDMA MM2S
#define DDR_ADDR 0x90000000
#define DDR_ADDR1 0xa0000000
#define DDR_ADDR2 0xb0000000//三个缓冲区的头地址
int main()
{
Xil_DCacheDisable();
int i;
//Xil_DCacheFlushRange((unsigned int) frame,H_STRIDE*V_ACTIVE);//
for(i=0;i<H_STRIDE*V_ACTIVE;i++)
{
Xil_Out8(DDR_ADDR+i,image_Y[i]);
Xil_Out8(DDR_ADDR1+i,image_Y[i]);
Xil_Out8(DDR_ADDR2+i,image_Y[i]);
}
Xil_Out32((VDMA_BASEADDR + 0x00),0x8B);
Xil_Out32((VDMA_BASEADDR + 0x5c),DDR_ADDR);
Xil_Out32((VDMA_BASEADDR + 0x60),DDR_ADDR1);
Xil_Out32((VDMA_BASEADDR + 0x64),DDR_ADDR2);
Xil_Out32((VDMA_BASEADDR + 0x58),(H_STRIDE));
Xil_Out32((VDMA_BASEADDR + 0x54),(H_ACTIVE*3));
Xil_Out32((VDMA_BASEADDR + 0x50),V_ACTIVE);
return 0;
}
设置的三个缓冲区不要用DDR的前面几块地址,放指令要用的。(我的地址从0x80000000开始的)。
寄存器的配置参考手册:
图片存在头文件里即可,形式类似这样
运行即可啦~