OV5640数据的解码

  为了配合开发板的使用,笔者搞了一个OV5640的摄像头模组,OV5640具体的相关手册及资料网上已经很多,感兴趣的都可以自行去查找,基本大同小异。这里也不把OV5640初始化的代码贴出来,因为就是简单的类似I2C接口配置数据。这里主要讲下初始化后的CMOS数据的解码,笔者是根据自己的需求把数据的VS,HS信号分别表示在了数据流的第一第二位,不过也是处理后的表示。

  这里初始化后的数据是RGB565的数据格式,对于初始化完成的COMS,一般情况是先要把前面不稳定的帧弃,笔者这里设置为15帧。具体可根据代码来解读,笔者前面做的边缘检测,高斯滤波就是基于此解码方式做的实验。

  顶层文件Cmosbuf.v:

  1 //**************************************************************************
  2 // *** file name      : Cmosbuf.v
  3 // *** version        : 1.0
  4 // *** Description    : Cmos data turn to stream
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.08.23
  8 // *** Changes        : Initial
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module Cmosbuf
 12 #(
 13     parameter                    DROP_FPS   = 15      ,
 14     parameter                    FIFO_DEPTH = 2048    ,
 15     parameter                    H_Active   = 1280    ,
 16     parameter                    V_Active   = 720
 17 )
 18 (
 19     input                        i_sys_clk          ,
 20     input                        i_sys_rstn         ,
 21     input                        i_cmos_clk         ,
 22     input                        i_cmos_pclk        ,
 23     input                        i_cmos_vs          ,
 24     input                        i_cmos_hs          ,
 25     input        [7:0]           i_cmos_data        ,
 26     output                       o_cmos_xclk        ,
 27     input                        i_fifo_ready       ,
 28     output       [31:0]          o_stream_data      ,
 29     output                       o_stream_valid     ,
 30     output                       o_frame_rst        ,
 31     output                       o_cmos_vs        
 32 );
 33     wire                        w_cmos_vs           ;
 34     wire                        w_cmos_hs           ;
 35     wire                        w_cmos_de           ;
 36     wire    [15:0]              w_cmos_data         ;
 37     wire                        w_start_frame       ;
 38     wire                        w_end_line          ;
 39     wire    [17:0]              w_fifo_din          ;
 40     wire    [17:0]              w_fifo_dout         ;
 41     wire                        w_rst_vs            ;
 42     reg     [5:0]               r_sys_rstn          ;
 43     reg     [3:0]               r_vs_buf            ;
 44     
 45     function integer clog;
 46         input    [31:0]    i_data;
 47         begin
 48             for(clog=0;i_data >0; clog = clog + 1)
 49             begin
 50                 i_data = i_data >> 1;
 51             end
 52         end
 53     endfunction
 54     
 55     always@(posedge i_cmos_clk)
 56     begin
 57         r_sys_rstn <= {r_sys_rstn[4:0],i_sys_rstn};
 58     end
 59     Cmosdecode
 60     #(
 61         .DROP_FPS         (DROP_FPS           ),
 62         .H_Active         (H_Active           ),
 63         .V_Active         (V_Active           )
 64     )u_Cmosdecode
 65     (
 66         .i_sys_clk        (i_sys_clk          ),
 67         .i_sys_rstn       (i_sys_rstn         ),
 68         .i_cmos_clk       (i_cmos_clk         ),
 69         .i_cmos_vs        (i_cmos_vs          ),
 70         .i_cmos_hs        (i_cmos_hs          ),
 71         .i_cmos_data      (i_cmos_data        ),
 72         .o_cmos_xclk      (                   ),
 73         .o_cmos_vs        (w_cmos_vs          ),
 74         .o_cmos_hs        (w_cmos_hs          ),
 75         .o_cmos_de        (w_cmos_de          ),
 76         .o_cmos_data      (w_cmos_data        ),
 77         .o_start_frame    (w_start_frame      ),
 78         .o_end_line       (w_end_line         )
 79     );
 80     
 81     always@(posedge i_sys_clk)
 82     begin
 83         r_vs_buf <= {r_vs_buf[2:0],i_cmos_vs};
 84     end
 85     
 86     assign w_rst_vs   = ~r_vs_buf[2] & r_vs_buf[3];
 87     assign w_fifo_din = {w_start_frame,w_end_line,w_cmos_data};
 88     
 89     xpm_fifo_async 
 90     #(
 91         .FIFO_MEMORY_TYPE           ("block"                    ),
 92         .ECC_MODE                   ("no_ecc"                   ),
 93         .RELATED_CLOCKS             (0                          ),
 94         .FIFO_WRITE_DEPTH           (FIFO_DEPTH                 ),
 95         .WRITE_DATA_WIDTH           (18                         ),
 96         .WR_DATA_COUNT_WIDTH        (clog(FIFO_DEPTH)           ),
 97         .PROG_FULL_THRESH           (10                         ),
 98         .FULL_RESET_VALUE           (0                          ),
 99         .USE_ADV_FEATURES           ("0707"                     ),
100         .READ_MODE                  ("fwft"                     ),
101         .FIFO_READ_LATENCY          (0                          ),
102         .READ_DATA_WIDTH            (18                         ),
103         .RD_DATA_COUNT_WIDTH        (clog(FIFO_DEPTH)           ),
104         .PROG_EMPTY_THRESH          (10                         ),
105         .DOUT_RESET_VALUE           ("0"                        ),
106         .CDC_SYNC_STAGES            (2                          ),
107         .WAKEUP_TIME                (0                          ) 
108     ) 
109     u_cmos_fifo
110     (
111         .rst                        (w_rst_vs | (~r_sys_rstn[5])),
112         .wr_clk                     (i_cmos_clk                 ),
113         .wr_en                      (w_cmos_de                  ),
114         .din                        (w_fifo_din                 ),
115         .full                       (                           ),
116         .overflow                   (                           ),
117         .prog_full                  (                           ),
118         .wr_data_count              (                           ),
119         .almost_full                (                           ),
120         .wr_ack                     (                           ),
121         .wr_rst_busy                (                           ),
122         .rd_clk                     (i_sys_clk                  ),
123         .rd_en                      (i_fifo_ready               ),
124         .dout                       (w_fifo_dout                ),
125         .empty                      (w_fifo_empty               ),
126         .underflow                  (                           ),
127         .rd_rst_busy                (                           ),
128         .prog_empty                 (                           ),
129         .rd_data_count              (                           ),
130         .almost_empty               (                           ),
131         .data_valid                 (                           ),
132         .sleep                      (1'b0                       ),
133         .injectsbiterr              (1'b0                       ),
134         .injectdbiterr              (1'b0                       ),
135         .sbiterr                    (                           ),
136         .dbiterr                    (                           )
137     );
138     assign o_cmos_xclk    = i_cmos_pclk;
139     assign o_stream_valid = ~w_fifo_empty & i_fifo_ready;
140     assign o_cmos_vs      = w_cmos_vs;
141     assign o_frame_rst    = w_rst_vs;
142     assign o_stream_data  = {w_fifo_dout[17:16],6'd0,w_fifo_dout[15:11],3'd0,w_fifo_dout[10:5],2'd0,w_fifo_dout[4:0],3'd0};
143 
144 endmodule

  上述的i_cmos_pclk是需要提供给FPGA外部OV5640的o_cmos_xclk,而i_cmos_clk则是OV5640输入像素数据的同步时钟,i_sys_clk这里是整个系统的时钟。如果i_sys_clki_cmos_clk不是同一个时钟就存在跨时钟域,因此这里通过一个异步FIFO来实现跨时钟域的处理。

  数据解码模块Cmosdecode.v

  1 //**************************************************************************
  2 // *** file name      : Cmosdecode.v
  3 // *** version        : 1.0
  4 // *** Description    : Cmos data decode
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.08.23
  8 // *** Changes        : Initial
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module    Cmosdecode
 12 #(
 13     parameter                    DROP_FPS = 15      ,
 14     parameter                    H_Active = 640     ,
 15     parameter                    V_Active = 480
 16 )
 17 (
 18     input                         i_sys_clk         ,
 19     input                         i_sys_rstn        ,
 20     input                         i_cmos_clk        ,
 21     input                         i_cmos_vs         ,
 22     input                         i_cmos_hs         ,
 23     input       [7:0]             i_cmos_data       ,
 24     output                        o_cmos_xclk       ,
 25     output                        o_cmos_vs         ,
 26     output                        o_cmos_hs         ,
 27     output                        o_cmos_de         ,
 28     output      [15:0]            o_cmos_data       ,
 29     output                        o_start_frame     ,
 30     output                        o_end_line        
 31 );
 32     wire                            w_vs_pos        ;
 33     wire                            w_vs_neg        ;
 34     wire                            w_hs_neg        ;
 35     reg            [5:0]            r_sys_rstn      ;
 36     reg            [2:0]            r_vs            ;
 37     reg            [2:0]            r_hs            ;
 38     reg            [7:0]            r_cmos_data     ;
 39     reg            [6:0]            r_cmos_fps      ;
 40     reg                             r_out_en        ;
 41     reg                             r_1st_hs        ;
 42     reg                             r_reverse_en    ;
 43     reg                             r_reverse_en_dly;
 44     reg            [15:0]           r_rgb_data      ;
 45     reg            [11:0]           r_cnt_pixel     ;
 46     
 47     always@(posedge i_cmos_clk)
 48     begin
 49         r_sys_rstn <= {r_sys_rstn[4:0],i_sys_rstn};
 50     end
 51     
 52     always@(posedge i_cmos_clk)
 53     begin
 54         r_vs <= {r_vs[1:0],i_cmos_vs};
 55         r_hs <= {r_hs[1:0],i_cmos_hs};
 56     end
 57     always@(posedge i_cmos_clk)
 58     begin
 59         r_cmos_data <= i_cmos_data;
 60     end
 61     assign w_vs_pos = ~r_vs[2] & r_vs[1];
 62     assign w_vs_neg = ~r_vs[1] & r_vs[2];
 63     assign w_hs_neg = ~r_hs[1] & r_hs[2];
 64 /******************************************************************************\
 65 Drop some frames
 66 \******************************************************************************/    
 67     always@(posedge i_cmos_clk)
 68     begin
 69         if(~r_sys_rstn[5])
 70         begin
 71             r_cmos_fps <= 'd0;
 72         end
 73         else if(r_cmos_fps >= DROP_FPS)
 74         begin
 75             r_cmos_fps <= r_cmos_fps;
 76         end
 77         else if(w_vs_pos)
 78         begin
 79             r_cmos_fps <= r_cmos_fps + 1'b1;
 80         end
 81     end
 82     always@(posedge i_cmos_clk)
 83     begin
 84         if(~r_sys_rstn[5])
 85         begin
 86             r_out_en <= 'd0;
 87         end
 88         else if(r_cmos_fps >= DROP_FPS)
 89         begin
 90             r_out_en <= 1'b1;
 91         end
 92         else 
 93         begin
 94             r_out_en <= r_out_en;
 95         end
 96     end
 97     always@(posedge i_cmos_clk)
 98     begin
 99         if(~r_sys_rstn[5])
100         begin
101             r_1st_hs <= 'd0;
102         end
103         else if(w_vs_neg)
104         begin
105             r_1st_hs <= 1'b1;
106         end
107         else if(w_hs_neg)
108         begin
109             r_1st_hs <= 'd0;
110         end
111     end
112 /******************************************************************************\
113 decode the data from cmos
114 \******************************************************************************/    
115     always@(posedge i_cmos_clk)
116     begin
117         if(~r_sys_rstn[5])
118         begin
119             r_reverse_en <= 'd0;
120         end
121         else if(r_hs[1])
122         begin
123             r_reverse_en <= ~r_reverse_en;
124         end
125         else
126         begin
127             r_reverse_en <= 'd0;
128         end
129     end
130     always@(i_cmos_clk)
131     begin
132         if(~r_sys_rstn[5])
133         begin
134             r_reverse_en_dly <= 'd0;
135         end
136         else
137         begin
138             r_reverse_en_dly <= r_reverse_en;
139         end
140     end
141     always@(posedge i_cmos_clk)
142     begin
143         if(~r_sys_rstn[5])
144         begin
145             r_rgb_data <= 'd0;
146         end
147         else if(r_hs[1])
148         begin
149             r_rgb_data <= {r_rgb_data[7:0],r_cmos_data};
150         end
151         else if(~r_hs[1])
152         begin
153             r_rgb_data <= 'd0;
154         end
155     end
156     always@(posedge i_cmos_clk)
157     begin
158         if(~r_sys_rstn[5])
159         begin
160             r_cnt_pixel <= 'd0;
161         end
162         else if(~r_hs[2])
163         begin
164             r_cnt_pixel <= 'd0;
165         end
166         else if(r_reverse_en)
167         begin
168             r_cnt_pixel <= r_cnt_pixel + 1'b1;
169         end
170     end
171 /******************************************************************************\
172 output cmos signal
173 \******************************************************************************/        
174     assign o_cmos_vs     = r_out_en ? r_vs[2] : 1'b0;
175     assign o_cmos_hs     = r_out_en ? r_hs[2] : 1'b0;
176     assign o_cmos_de     = r_reverse_en & o_cmos_hs & (r_cnt_pixel < H_Active);
177     assign o_start_frame = r_reverse_en & (r_cnt_pixel == 'd0) &  r_1st_hs;
178     assign o_end_line    = r_reverse_en & (r_cnt_pixel == H_Active - 1'b1);
179     assign o_cmos_xclk   = i_cmos_clk;
180     assign o_cmos_data   = r_rgb_data;
181     
182 endmodule

  以上便是CMOS数据的解码的Verilog代码,笔者在前面两个实验已经验证过了,是可以正常使用的。

posted on 2022-10-19 10:45  Galois_V  阅读(295)  评论(0编辑  收藏  举报