目录
一、理论基础
二、核心程序
三、仿真结论
一、理论基础
VmodCAM板提供数字成像适用于任何Digilent FPGA系统的功能带有VHDCI连接器的板。它有两个特点Aptina MT9D112 200万像素CMOS数字图像传感器。传感器可以提供框架速率从15 FPS以上,具体取决于决议。其片上系统设计集成了图像流处理器,并启用可选输出格式、缩放和特殊效果。集成PLL(锁相环)和微处理器提供灵活的串行控制界面输出数据以并行方式发送处理后的YCrCb、RGB或原始拜耳中的总线格式。
功能包括:
•两个独立的Aptina MT9D112 2-百万像素CMOS数字图像传感器
•最大分辨率为1600x1200,分辨率为15每秒
•63mm摄像头间距(立体声基线)
•10位原始颜色深度
•I2C控制总线
•拜耳、RGB、YCrCb输出格式
•自动曝光、增益和白色均衡
•强大的图像校正算法
•图像缩放
•输出FIFO
•68针内螺纹VHDCI连接器
整个系统的结构如下所示:
1.显示器HDMI口介绍:
这个部分对应的verilog程序为d_output.v
这三个是时钟,复位,测试数据,
这个是这个模块控制HDMI口的几个接口信号,其中最为关键的控制信号就是行列同步信号h_sync ,v_sync。行列同步信号是用来保证输出视频为稳定的,不抖动的视频信号。
这个是读写地址输出。
具体的图像信息,我们这里通过RD_DATA,进行输出的。
下面,我们对这个模块进行简要的分析。
这个是个时钟分频信号,得到CLK的一半的时钟频率。
这个是产生行扫描计数器。
产生列扫描计数器
这两个模块产生行列同步信号。
其中
以下的程序是我测试HDMI口写的测试程序,就不用管了。
那么这个模块的其本质功能就是产生行列同步信号,告诉HDMI接口,使得需要输出的视频信号按行列进行逐行的扫描,完成整个视频的显示。
2.摄像头配置介绍:
cam_input.v
cam_iic.v
这两个函数,其中第一个是将摄像头采集到的数据发送给SDRAM.
第二个函数式摄像头的配置函数,通过I2C接口进行配置。关于配置的详细信息,具体的配置参考这个datasheet。
这个部分,所以的摄像头都是按这个步骤进行,即先进行配置,然后接收数据,你按你的摄像头进行进行处理即可。
首先,我们来看下对应的程序:
摄像头图像采集信号,将摄像头采集到的信号写入到DDR中,这里下面的W*信号就
这个是由于这款摄像头是支持左右双通道的图像采集的,所以在采集的时候,需要设置为两倍的800X600。
这个是根据视频的宽度,进行line计数器的计数。
这个是根据视频的长度,进行pix计数器的计数。
这个test是测试数据集,不用管,这里没有使用这个测试数据集。
每16个时钟周期,产生一个写使能信号WDFIFO_WEN。
这个是数据写使能信号。
每32个时钟周期,产生一个写使能信号WAFIFO_WEN。
这个是地址写使能信号。
根据行列扫描器产生对应的地址信号。
再写下摄像头的配置模块:
这个模块是通过串行接口I2C,将配置数据传输到摄像头的寄存器中,
首先输入配置指令为comd这个变量,根据摄像头的datasheet文档可知:
文档中写到对于MT9D112,需要输入78这个参数值。即我们这个程序中额comd这个值。
然后代码中:
这个是依据文档中:
即上面159行,其余后面的根据数据手册中的地址寄存器的配置进行。
3.DDR配置介绍:
这个模块,其对应的接口如下所示:
这个是复位和时钟。
这六个信号分别为FPGA到外部芯片的写入数据以及写地址对应的数据,full以及写使能六个信号,通过这几个信号。
读取DDR中的图像数据的读控制信号。
MIG接口。
首先介绍ddr_rwctrl.v这个模块,这个模块是MIG接口控制器,下面对这个模块进行介绍一下:这里是一个四状态机过程,状态机的过程如下所示:初始状态,准备状态,读状态,写状态。
.......
到100行,这个是状态机的的状态转移过程。
...................
当状态机在WRITE_BURST状态的时候,则fifo写使能为1.否则为0.
...................
当状态机在READ_BURST状态的时候,则fifo读使能为1.否则为0.
这个模块的四个主要接口信号:
分别用来控制读写数据传输FIFO,读写地址传输FIFO。
摄像头的图像采集以及显示的调试:
这个部分的调试,按如下的过程调试的:
第一:首先是使用简单的颜色对HDMI口进行测试,通过设置输出颜色像素,用来进行HDMI接口的显示。
第二:然后通过I2C对摄像头进行参数配置,然后将数据保存到DDR中,并从DDR中将数据读取。
第三:将从DDR中读取的数据放到HDMI口上进行显示。这里,主要的调试困难在于,反复的修改行列扫描的时序,直到得到较为稳定的输出图像为止。文章来源:https://www.toymoban.com/news/detail-670553.html
二、核心程序
//tt_ddr_top
//05/10/2014
module tt_ddr_top#(
parameter PIX_DWIDTH = 16,
parameter PIX_AWIDTH = 11,
//parameter DDR_BANK_WIDTH = 2,
//parameter DDR_COL_WIDTH = 10,
//parameter DDR_ROW_WIDTH = 13,
parameter APP_DWIDTH = 128,
parameter APP_AWIDTH = 31
)
(
input rst_n,
input vga_clk,
// input [PIX_DWIDTH-1:0] vga_data,
// input vga_data_valid,
// input [PIX_AWIDTH-1:0] addr_x,
// input [PIX_AWIDTH-1:0] addr_y,
input [APP_DWIDTH-1:0] wdata_in,
input [APP_AWIDTH-1:0] waddr_in,
output wdfifo_afull,
output wafifo_afull,
input wdfifo_wen,
input wafifo_wen,
input dvi_clk,
output read_data_fifo_prog_full,
output read_addr_fifo_afull,
input [APP_AWIDTH-1:0] raddr_in,
input read_data_addr_valid,
//input frame_reset,
// input frame_valid,
input wdfifo_rd_en,
output[PIX_DWIDTH-1:0] dvi_data,
output dvi_data_valid,
input ddr_clk,
output [2:0] app_af_cmd,
output [30:0] app_af_addr,
output app_af_wen,
output app_wdf_wen,
output [APP_DWIDTH-1:0] app_wdf_data,
input app_af_afull,
input app_wdf_afull,
input rd_data_valid,
input [APP_DWIDTH-1:0] rd_data_fifo_out,
input phy_init_done,
output [1:0] ready_status
//output [3:0] led_tmp
);
//input data/addr fifo ctrl
/*ddr_input_dctrl ddr_input_dctrl_ins(
.vga_data (vga_data),
.vga_data_valid(vga_data_valid),
.addr_x (addr_x),
.addr_y (addr_y),
.vga_clk (vga_clk), //40mhz
.rst_n (rst_n),
.wdata_in (wdata_in), //data to wd fifo
.waddr_in (waddr_in), //addr to wa fifo
.wdfifo_afull (wdfifo_afull),
.wafifo_afull (wafifo_afull),
.wdfifo_wen (wdfifo_wen),
.wafifo_wen (wafifo_wen)
);*/
/*ddr_read_addr_ctrl ddr_read_addr_ctrl_ins(
.rst_n(rst_n),
.dvi_clk(dvi_clk),
.frame_valid(frame_valid),
.read_data_fifo_prog_full(read_data_fifo_prog_full),
.read_addr_fifo_afull(read_addr_fifo_afull),
.read_data_addr(raddr_in),
.read_data_addr_valid(read_data_addr_valid)
);*/
wire [APP_DWIDTH-1:0] rdata_out;
wire read_data_fifo_empty;
wire read_data_fifo_valid;
wire read_data_fifo_ren;
wire [PIX_DWIDTH-1:0] dvi_data_tmp;
wire dvi_tmp_data_valid;
wire write_fifo_ready;
wire read_fifo_ready;
wire rdwr_flag;
wire write_data_fifo_ren;
wire write_addr_fifo_ren;
wire read_addr_fifo_ren;
wire read_data_fifo_wen;
//mig interface ctrl
ddr_rwctrl ddr_rwctrl_ins(
.ddr_clk (ddr_clk),
.rst_n (rst_n),
.phy_init_done (phy_init_done), //from mig input to this ctrl
.write_fifo_ready (write_fifo_ready), //from wd/wa fifo input to this ctrl
.read_fifo_ready (read_fifo_ready), //from ra fifo input to this ctrl
.rd_data_valid (rd_data_valid), //from mig input to this ctrl
.app_wdf_wen (app_wdf_wen), //output to mig
.app_af_wen (app_af_wen), //output to mig
.app_af_cmd (app_af_cmd), //output to mig
.rdwr_flag (rdwr_flag), //select addr to addr_fifo
.write_data_fifo_ren (write_data_fifo_ren), //output to wd fifo
.write_addr_fifo_ren (write_addr_fifo_ren), //output to wa fifo
.read_addr_fifo_ren (read_addr_fifo_ren), //output to ra fifo
.read_data_fifo_wen (read_data_fifo_wen) //output to rd fifo
);
wire [APP_AWIDTH-1:0] raddr_tomig;
wire [APP_AWIDTH-1:0] waddr_tomig;
assign app_af_addr = (rdwr_flag==1'b0) ? waddr_tomig : raddr_tomig;
wire wdfifo_prog_empty;
wire wdfifo_empty;
wire wafifo_prog_empty;
wire wafifo_empty;
assign write_fifo_ready = (~wdfifo_prog_empty) && (~wafifo_prog_empty) && (~wdfifo_empty) && (~wafifo_empty) && (~app_wdf_afull) && (~app_af_afull);
//wdata_fifo
wdata_fifo wdata_fifo_ins(
.rst (~rst_n),
.wr_clk (~vga_clk),
.wr_en (wdfifo_wen),
.din (wdata_in),
.rd_clk (ddr_clk),
.rd_en (write_data_fifo_ren),
.dout (app_wdf_data),
.almost_full (wdfifo_afull),
.empty (wdfifo_empty),
.full (),
.prog_empty (wdfifo_prog_empty),
.valid ()
);
//waddr_fifo
waddr_fifo waddr_fifo_ins(
.rst (~rst_n),
.wr_clk (~vga_clk),
.wr_en (wafifo_wen),
.din (waddr_in),
.rd_clk (ddr_clk),
.rd_en (write_addr_fifo_ren),
.dout (waddr_tomig),
.almost_full (wafifo_afull),
.empty (wafifo_empty),
.full (),
.prog_empty (wafifo_prog_empty),
.valid ()
);
assign read_addr_fifo_wen = read_data_addr_valid;
wire rafifo_empty;
wire rafifo_prog_empty;
wire rdfifo_afull;
assign read_fifo_ready = (~rafifo_prog_empty) && (~rafifo_empty) && (~app_af_afull);//&& (~read_data_fifo_prog_full)
//raddr fifo
raddr_fifo raddr_fifo_ins(
.rst (~rst_n),
.wr_clk (~dvi_clk),
.wr_en (read_addr_fifo_wen),
.din (raddr_in),
.rd_clk (ddr_clk),
.rd_en (read_addr_fifo_ren),
.dout (raddr_tomig),
.almost_full (read_addr_fifo_afull),
.empty (rafifo_empty),
.full (),
.prog_empty (rafifo_prog_empty),
.valid ()
);
output_data_fifo new_rdfifo_ins (
.rst (~rst_n),
.wr_clk (~ddr_clk),
.wr_en (read_data_fifo_wen),
.din (rd_data_fifo_out), // Bus [127 : 0]
.rd_clk (~dvi_clk),
.rd_en (wdfifo_rd_en),
.dout (dvi_data), // Bus [15 : 0]
.valid (dvi_data_valid),
//.full (full),
.almost_full (rdfifo_afull),
.empty (read_data_fifo_empty),
.almost_empty (),
.prog_full (read_data_fifo_prog_full)
);
assign ready_status[0] = write_fifo_ready;
assign ready_status[1] = read_fifo_ready;
endmodule
A10-30
三、仿真结论
文章来源地址https://www.toymoban.com/news/detail-670553.html
到了这里,关于基于HDMI接口和DDR存储器的VmodCAM双目摄像头驱动verilog程序开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!