OV5640摄像头的数据处理配置流程(一)

做~自己de王妃 提交于 2019-11-30 12:36:52
  1 module RGB_init(
  2     //系统信号输入(时钟+复位)
  3     input cmos_clk_i,  //模块控制时钟
  4     input rst_n_i,     //系统复位信号
  5     //OV5640输出信号(从5640输入到FPGA)
  6     input cmos_pclk_i,  //摄像头时钟
  7     input cmos_href_i,   //帧输出行同步信号
  8     input cmos_vsync_i,  //场同步信号
  9     input [7:0] cmos_data_i,  //像素数据
 10     //模块的输出信号
 11     output clk_ce,   //摄像头帧数据输出/捕获使能信号(12Mhz),该信号的理解是最难的
 12     output de_o,     //数据有效信号
 13     output [23:0] rgb_o,  //输出的24bit像素数据
 14     output vs_o, //输出的场同步信号
 15     output hs_o,  //输出的行同步信号
 16     //输出道5640模块的像素时钟
 17     output cmos_xclk   
 18     );
 19  
 20  //为了保持系统稳定,需要丢弃前期一部分帧图像,此处选择丢弃15个,自行选择,也有10个的
 21  parameter[3:0]CMOS_FRAME_WAITCNT=15;
 22  
 23  assign cmos_xclk=cmos_clk_i;   //xclk为5640驱动时钟,为24/25Mhz
 24  
 25  //在米联客的对复位信号的处理中,复位信号延迟了5个时钟,好像不延迟也可以,可以在例程2中查看
 26  //个人认为复位信号的处理是为了使复位信号保持一个完整的信号周期
 27  reg[4:0]rst_n_reg=5'd0;
 28  always@(posedge cmos_clk_i)  //同步于FPGA输入时钟
 29  begin
 30   rst_n_reg<={rst_n_reg[3:0],rst_n_i};
 31  end 
 32  
 33  reg cmos_href_r=1'b0;   //将行同步信号进行缓存
 34  reg [1:0]cmos_vsync_r;   //将场同步信号进行缓存
 35  reg[7:0]cmos_data_r;   //将5640输出到FPGA的数据进行寄存,因为是处理输出16bit,就是将两个周期的输入信号进行拼接处理
 36  //进行行、场同步信号进行缓存,输入数据进行一级缓存
 37  always@(posedge cmos_pclk_i)
 38  begin
 39   cmos_vsync_r<=cmos_vsync_i;
 40   cmos_href_r<=cmos_href_i;
 41   cmos_data_r<=cmos_data_i;
 42  end 
 43  
 44  //为了判断一帧数据的开始&结束,同时对帧进行计数,对场同步信号进行寄存
 45  reg [1:0]cmos_vsync_d;
 46  always@(posedge cmos_pclk_i)   //同步于5640输出时钟
 47  begin
 48   cmos_vsync_d<={cmos_vsync_d[0],cmos_vsync_r};
 49  end 
 50  //场开始与结束信号
 51  wire vs_start;
 52  assign vs_start=(!cmos_vsync_d[1])&(cmos_vsync_d[0]);   //posedge mark the action
 53  wire vs_end;
 54  assign vs_end=(cmos_vsync_d[1])&(!cmos_vsync_d[0]); 
 55  
 56  //行同步信号缓存
 57  reg [1:0]cmos_href_d=2'd0;
 58  always@(posedge cmos_pclk_i)
 59  begin
 60   cmos_href_d<={cmos_href_d[0],cmos_href_r};
 61  end 
 62  
 63  //前期丢弃部分帧
 64  reg [4:0]frame_cnt=0;  //帧计数器
 65  reg out_en=0;   //开始正常启动操作
 66  always@(posedge cmos_pclk_i) 
 67   if(!rst_n_reg[4])
 68   begin
 69    frame_cnt<=5'd0;
 70     out_en<=1'b0;
 71   end
 72  else begin 
 73  if(vs_start) begin
 74  frame_cnt<=frame_cnt+1;
 75  out_en<=0;
 76  end 
 77  else if(frame_cnt>=CMOS_FRAME_WAITCNT) 
 78  begin
 79   out_en<=1;
 80   frame_cnt<=CMOS_FRAME_WAITCNT;  //保持正常帧处理完毕
 81  end 
 82  end  
 83  //由于输出的是24bit数据,是由16bit数据转化而来,将两个帧的RGB数据进行拼接
 84  reg href_cnt=0;
 85  reg data_en=1'b0;
 86  reg [15:0]RGBm=16'd0;   //middle RGB data
 87   
 88  always@(posedge cmos_pclk_i)begin
 89  if(!rst_n_reg[4])begin
 90   href_cnt<=0;
 91   data_en<=1'b0; 
 92   RGBm<=16'd0;  
 93  end 
 94  //两个数据拼接完毕之后将data_en置一,第0次拼接使低8位有效,第1次使得低八位有效(位移)
 95  else begin
 96   href_cnt<=(cmos_href_r)?href_cnt+1'b1:href_cnt;
 97   data_en<=(href_cnt==1);  
 98   if(href_cnt) RGBm<={RGBm[7:0],cmos_data_r};  //此处cmos_data_r lag 2 clocks,thus later all lag 2clks 
 99  end 
100  end 
101  
102  assign rgb_o={RGBm[15:11],3'd0,RGBm[10:5],2'd0,RGBm[4:0],3'd0};
103  //模块行同步输出
104  assign hs_o=out_en?(cmos_href_d[0]):0;   //为了与暑促信号同步,该同步信号是滞后两个pclk
105  //模块场同步信号输出
106  assign vs_o=out_en?(cmos_vsync_r):0;  //行同步结束之后开始场同步,场同步信号知乎一个pclk,觉得这个程序真的很nb,考虑的太全了
107  //模块数据输出同步时钟信号,12M,
108  assign de_o=out_en?data_en:0;
109  //输出时钟enable signal
110  assign clk_ce=out_en?((data_en&hs_o)||!hs_o):0;  //其实好像1也行,没有边沿驱动
111  //在init complete的情况下,d0是经过了2个pclk延迟的,该output信号同步(更准确地说是对齐)于这个数据输入时的时钟,
112  //同步于12Mhz的data_en时钟
113  //该模块每2个pclk输出一次rgb[23:0]的数据,需要听过clk_ce对时钟频率进行同步,该处理解决了模块接口之间的同步问题
114  /*
115    举例说明:
116        在do==0时,clk_ce恒为高,没有时钟脉冲
117         在do==1时,该时钟始终同步于12M时钟
118  */
119 endmodule 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!