本设计用到的FPGA开发板是Digilent Nexys_Video 开发板,程序的基础是正点原子为其FPGA产品提供的驱动程序,由于板子硬件的不同,我做了一些改动,使之能在Nexys_Video上运行,正点原子程序在其官网可以下载。HDMI驱动用的是Digilent提供的IP核,在其官网可以下载。
vivado 版本 2018.1
摄像头用的是这个
首先用Clocking Wizard生成摄像头核HDMI IP核需要的65M时钟。
摄像头的驱动是用SCCB协议配置寄存器,正点原子给提供了,直接用就好了。
在其驱动最后的输出模块中,输出了两个信号:分别是cmos_frame_valid,cmos_frame_data。一个是有效信号,一个是数据。我们就用这两个信号就可以了。
获得的数据是不能直接传送到HDMI去显示的,因为OV5640模块产生的行信号很不好,并且有效信号并不是连续的(OV5640每次传送8bit的数据,而RGB565格式下,一个像素需要两次传输才能获得,所以有效信号是隔一个时钟周期才有效一次),并且,对OV5640的不同配置可能导致模块的PCLK不同,所以这里需要通过一些媒介对数据进行缓存。
在正点原子原程序中,视频流会被存储在SDRAM中,这里由于我的开发板资源很大,用BRAM就装下了。
根据协议对寄存器的配置,输出视频流大小为1024x768,每一个像素点是16位,所以,生成如下大小的双端口BRAM
注:实际开发板上也有DDR3存储器,但是其需要用MIG IP核驱动,相对麻烦,在有处理器的SOC中可以用MIG内核,我也已经实现过,如果有空我就再写出来。
根据写有效信号驱动写地址变化
always @(posedge cam_pclk,negedge rst_n) begin
if(~rst_n) begin
addra<=0;
end else begin
if(wr_en) begin
addra<=addra+1;
if(addra==20'hc0000-1) addra<=0;
end
end
end
读地址同理实现
always @(posedge clk_65m,negedge rst_n) begin
if(~rst_n) begin
addrb<=0;
end else begin
if(rd_en) begin
addrb<=addrb+1;
if(addrb==20'hc0000-1) addrb<=0;
end
end
end
最后连上HDMI IP核即可。由于该IP核是24位,并且绿蓝像素位置貌似反了,所以要对数据进行处理。
vid_pData<={rd_data[15:11],3'b0,rd_data[4:0],3'b0,rd_data[10:5],2'b0};
工程下载地址:
https://download.csdn.net/download/dongze2/11224991