基于FPGA的图像数据采集(二)

一、数据采集时序

  上一篇我们讨论了OV5640的上电时序,下面给出数据采集的时序。

b2231202388a4f34a2b19836f839f8be.png

e6758c4de5674159aacadfc10beb3ec4.png

   上一篇已经提到了VSYNC是场同步信号,每一次拉高就表示一帧图像的开始。两次拉高中间的时间对应上图中的(1),这段时间要发送一帧的完整图像。

  PCLK是像素时钟,当HREF拉高时,每一个PCLK,D传输一个字节的数据。

二、模块划分

  根据前面的相关介绍,可以将数据采集分为以下几个模块,分别编写代码:SCCB控制模块,数据发送模块,OV5640上电模块,串口发送模块。

三、SCCB控制模块代码

module IIC_ctrl (
        input           wire            sys_clk         ,
        input           wire            sys_rst_n       ,
        input           wire            sta_flag        ,//开始标志,由外部传入
        input           wire    [7:0]   ins             ,
        input           wire    [15:0]  addr            ,
        input           wire    [7:0]   data            ,
        inout           wire            sda             ,
        output          wire            scl             ,
        output          wire            sda_en          ,
        output          reg             ready_flag      );//结束标志,高电平时可以继续传输数据
        
        
        reg     [6:0]       current_state       ;
        reg     [6:0]       next_state          ;
        reg     [3:0]       bit_cnt             ;//数据传输位数
        reg     [1:0]       clk_cnt             ;//用于产生4分频时钟
        reg                 sda_out             ;//产生sda
        reg                 stop_flag           ;//停止信号
        reg                 start_flag          ;//开始信号
        wire                iic_clk             ;
        reg                 write               ;//写信号,有效时表示正在写
        reg                 sda_en_2            ;
        
        parameter   IDLE=7'b0000001,
                    START=7'b0000010,
                    INS=7'b0000100,
                    ADDR_1=7'b0001000,
                    ADDR_2=7'b0010000,
                    DATA_W=7'b0100000,
                    STOP=7'b1000000;
        
        
        assign sda=sda_en?sda_out:1'bz;
        assign sda_en=((bit_cnt==4'd0)&&(current_state!=IDLE)&&(current_state!=START)&&(current_state!=STOP)&&(write==1'b1))?1'b0:1'b1;
        assign iic_clk=((clk_cnt>=2'd2)&&(clk_cnt<=2'd3))?1'b1:1'b0;
         assign scl=((current_state==IDLE)||(current_state==START)||(current_state==STOP&&sda_en_2==1'b1))?1'b1:iic_clk; 
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        sda_en_2<=1'b1;
        else
        sda_en_2<=sda_en;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        write<=1'b0;
        else if(bit_cnt==4'd1)
        write<=1'b1;
        else if(stop_flag==1'b1)
        write<=1'b0;
        else
        write<=write;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        start_flag<=1'b0;
        else if((sda==1'b0)&&(scl==1'b1))
        start_flag<=1'b1;
        else
        start_flag<=1'b0;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        stop_flag<=1'b0;
        else if(scl==1'b1&&sda==1'b1&&current_state==STOP)
        stop_flag<=1'b1;
        else
        stop_flag<=1'b0;
        end
        
        
        
        
        
        always@(negedge scl or negedge sys_rst_n) begin
        if(!sys_rst_n)
        bit_cnt<=4'b0;
        else if(bit_cnt==4'd8)
        bit_cnt<=4'b0;
        else if(current_state!=STOP)
        bit_cnt<=bit_cnt+1'b1;
        else
        bit_cnt<=bit_cnt;
        end
        
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        clk_cnt<=2'b0;
        else if(clk_cnt==2'b11)
        clk_cnt<=2'b0;
        else
        clk_cnt<=clk_cnt+1'b1;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        current_state<=IDLE;
        else
        current_state<=next_state;
        end
        
        
        
        
        always@(*) begin//状态机
        if(!sys_rst_n)
        next_state<=IDLE;
        
        else  
        begin
        case(current_state)
        
        IDLE: begin
        if(sta_flag==1'b1)
        next_state<=START;
        else
        next_state<=IDLE;
        end
        
        START:  begin
        if(start_flag==1'b1)
        next_state<=INS;
        else
        next_state<=START;
        end
        
        
        INS:  begin
        if(bit_cnt==4'd0&&clk_cnt==2'd3&&write==1'b1)
        next_state<=ADDR_1;
        else
        next_state<=INS;
        end
        
        ADDR_1: begin
        if(bit_cnt==4'd0&&clk_cnt==2'd3&&write==1'b1)
        next_state<=ADDR_2;
        else
        next_state<=ADDR_1;
        end
        
        
        ADDR_2: begin
        if(bit_cnt==4'd0&&clk_cnt==2'd3&&write==1'b1)
        next_state<=DATA_W;
        else
        next_state<=ADDR_2;
        end
        
        DATA_W: begin
        if(bit_cnt==4'd0&&clk_cnt==2'd3&&write==1'b1)
        next_state<=STOP;
        else
        next_state<=DATA_W;
        end

        STOP: begin
        if(stop_flag==1'b1)
        next_state<=IDLE;
        else
        next_state<=STOP;
        end
        
        default:next_state<=IDLE;
        
        endcase
        end
        end
        
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        ready_flag<=1'b0;
        else if(current_state==IDLE)
        ready_flag<=1'b1;
        else
        ready_flag<=1'b0;
        end
        
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        sda_out<=1'b1;
        else
        begin
        case(current_state)
        
        
        IDLE:
        sda_out<=1'b1;
        
        
        START:
        sda_out<=1'b0;
        
        
        INS:
        begin
        case(bit_cnt)
        4'd0:
        sda_out<=1'b0;
        4'd1:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[7];
        end
        4'd2:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[6];
        end
        4'd3:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[5];
        end
        4'd4:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[4];
        end
        4'd5:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[3];
        end
        4'd6:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[2];
        end
        4'd7:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[1];
        end
        4'd8:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=ins[0];
        end
        default:sda_out<=1'b1;
        
        endcase
        end
        
        ADDR_1:begin
        case(bit_cnt)
        4'd0:sda_out<=1'b0;
        4'd1:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[15];
        end
        4'd2:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[14];
        end
        4'd3:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[13];
        end
        4'd4:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[12];
        end
        4'd5:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[11];
        end
        4'd6:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[10];
        end
        4'd7:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[9];
        end
        4'd8:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[8];
        end
        default:sda_out<=1'b1;
        endcase
        end
        
        
        ADDR_2:begin
        case(bit_cnt)
        4'd0:sda_out<=1'b0;
        4'd1:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[7];
        end
        4'd2:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[6];
        end
        4'd3:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[5];
        end
        4'd4:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[4];
        end
        4'd5:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[3];
        end
        4'd6:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[2];
        end
        4'd7:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[1];
        end
        4'd8:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=addr[0];
        end
        default:sda_out<=1'b1;
        endcase
        end
        
        DATA_W:begin
        case(bit_cnt)
        4'd0:sda_out<=1'b0;
        4'd1:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[7];
        end
        4'd2:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[6];
        end
        4'd3:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[5];
        end
        4'd4:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[4];
        end
        4'd5:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[3];
        end
        4'd6:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[2];
        end
        4'd7:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[1];
        end
        4'd8:begin
        if(clk_cnt==2'd0||clk_cnt==2'd3)
        sda_out<=data[0];
        end
        default:sda_out<=1'b1;
        endcase
        end
        
        STOP:
        begin
        if(scl==1'b1)
        sda_out<=1'b1;
        else
        sda_out<=1'b0;
        end
        
        
	endcase
	end
	end

	endmodule

四、上电时序代码

module power(
            input               wire                sys_clk             ,
            input               wire                sys_rst_n           ,
            output              wire                reset               ,
            output              wire                pwdn                ,
            output              wire                power_done          );
            
            
            reg             [13:0]          cnt;
            
            parameter       max_1=2460,
                            max_2=3280,
                            max_3=12296;
                            
                            
                            always@(posedge sys_clk or negedge sys_rst_n) begin
                            if(!sys_rst_n)
                            cnt<=14'b0;
                            else if(cnt==max_3+8'd100)
                            cnt<=cnt;
                            else
                            cnt<=cnt+1'b1;
                            end
                            
                            
                            assign pwdn=(cnt>=max_1)?1'b0:1'b1;
                            assign reset=(cnt>=max_2)?1'b1:1'b0;
                            assign power_done=(cnt>=max_3)?1'b1:1'b0;
                            
                            
                            endmodule
                            

五、串口发送模块

module data_uart(
    input       wire                clk         ,
    input       wire                pclk        ,
    input       wire                vsync       ,
    input       wire        [7:0]   rgb_din     ,
    input       wire                hsync       ,
    input       wire                sys_rst_n   ,
    output      wire                tx          );
    
    parameter bote=9600,
              period=50_000_000;
              
              parameter max=period/bote;


     
              
    wire            data_valid      ;
    reg     [12:0]   cnt             ;
    reg     [3:0]   bit_cnt         ;
    wire            uart_clk        ;



         Gowin_rPLL uucc(
        .clkout(uart_clk), //output clkout
        .clkin(clk) //input clkin
    );
    
    always@(posedge uart_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
    cnt<=13'b0;
    else if(cnt==max-1'b1)
    cnt<=13'b0;
    else 
    cnt<=cnt+1'b1;
    end
    
    
    always@(posedge uart_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
    bit_cnt<=4'b0;
    else if (bit_cnt==4'd9&&cnt==max-1'b1)
    bit_cnt<=4'b0;
    else if(cnt==max-1'b1)
    bit_cnt<=bit_cnt+1'b1;
    else
    bit_cnt<=bit_cnt;
    end
    
    assign data_valid=(bit_cnt==4'd9&&cnt==max-1'b1&&hsync==1'b1)?1'b1:1'b0;
    
    urat_tx  
 #(.bote(9600),
   .period(50_000_000))
urat_tx_inst
(
    .clk         (uart_clk)    ,
    .rst         (sys_rst_n)    ,
    .data        (rgb_din)    ,
    .data_valid  (data_valid)    ,
    .tx          (tx)    );
    
    
    endmodule
    
    
    
    
    
    
    
module urat_tx
 #(parameter bote=9600,
      parameter period=50_000_000)
(
    input          wire         clk,
    input          wire         rst,
    input          wire  [7:0]  data,
    input          wire         data_valid,
    output         reg          tx);
    
    
    reg                 work_en;
    reg         [15:0]  baud_cnt;
    reg         [3:0]   bit_cnt;
    wire                bit_flag;
    
    parameter max=period/bote;
    
    always@(posedge clk or negedge rst) begin
    if(!rst)
    work_en<=1'b0;
    else if((bit_cnt==4'd10)&&(baud_cnt==16'd1))
    work_en<=1'b0;
    else if(data_valid==1'b1)
    work_en<=1'b1;
    else
    work_en<=work_en;
    end
    
    
    always@(posedge clk or negedge rst) begin
    if(!rst)
    baud_cnt<=16'b0;
    else if((baud_cnt==max-1)&&(work_en==1'b1))
    baud_cnt<=16'b0;
    else if(work_en==1'b1)
    baud_cnt<=baud_cnt+1'b1;
    else
    baud_cnt<=16'b0;
    end
    
    assign bit_falg=((baud_cnt==16'b0)&&(work_en==1'b1))?1'b1:1'b0;
    
    always@(posedge clk or negedge rst) begin
    if(!rst)
    bit_cnt<=4'b0;
    else if((bit_cnt==4'd10)&&(baud_cnt==16'd1))
    bit_cnt<=4'b0;
    else if(bit_falg==1'b1)
    bit_cnt<=bit_cnt+1'b1;
    else
    bit_cnt<=bit_cnt;
    end
    
    
    always@(*) begin
    if(!rst)
    tx<=1'b1;
    else begin
    case(bit_cnt)
    4'd0:tx<=1'b1;
    4'd1:tx<=1'b0;
    4'd2:tx<=data[0];
    4'd3:tx<=data[1];
    4'd4:tx<=data[2];
    4'd5:tx<=data[3];
    4'd6:tx<=data[4];
    4'd7:tx<=data[5];
    4'd8:tx<=data[6];
    4'd9:tx<=data[7];
    default:tx<=1'b1;
    endcase
    end
    end
    
    endmodule

六、数据发送模块

module IIC_start(
    input           wire            sys_clk         ,
    input           wire            sys_rst_n       ,
    input           wire            ready_flag      ,
    output          reg             sta_flag        ,
    output          wire    [7:0]   ins             ,
    output          wire    [15:0]  addr            ,
    output          wire    [7:0]   data            );
    
    
    always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
    sta_flag<=1'b0;
    else if(ready_flag==1'b1)
    sta_flag<=1'b1;
    else
    sta_flag<=1'b0;
    end
    
    
    reg         [9:0]           cnt         ;
    reg         [31:0]          lut_data    ;
    
    assign ins=lut_data[31:24];
    assign addr=lut_data[23:8];
    assign data=lut_data[7:0];
    
    
    always@(posedge sta_flag or negedge sys_rst_n) begin
    if(!sys_rst_n)
    cnt<=10'b0;
    else if(cnt==10'd256)
    cnt<=cnt;
    else
    cnt<=cnt+1'b1;
    end
    
    
    always@(*) begin
    case(cnt)
        10'd  1: lut_data <= {8'h78 , 24'h310311};// system clock from pad, bit[1]
	    10'd  2: lut_data <= {8'h78 , 24'h300882};// software reset, bit[7]// delay 5ms 
	    10'd  3: lut_data <= {8'h78 , 24'h300842};// software power down, bit[6]
	    10'd  4: lut_data <= {8'h78 , 24'h310303};// system clock from PLL, bit[1]
	    10'd  5: lut_data <= {8'h78 , 24'h3017ff};// FREX, Vsync, HREF, PCLK, D[9:6] output enable
	    10'd  6: lut_data <= {8'h78 , 24'h3018ff};// D[5:0], GPIO[1:0] output enable
	    10'd  7: lut_data <= {8'h78 , 24'h30341A};// MIPI 10-bit
	    10'd  8: lut_data <= {8'h78 , 24'h303713};// PLL root divider, bit[4], PLL pre-divider, bit[3:0]
	    10'd  9: lut_data <= {8'h78 , 24'h310801};// PCLK root divider, bit[5:4], SCLK2x root divider, bit[3:2] // SCLK root divider, bit[1:0] 
	    10'd 10: lut_data <= {8'h78 , 24'h363036};
	    10'd 11: lut_data <= {8'h78 , 24'h36310e};
	    10'd 12: lut_data <= {8'h78 , 24'h3632e2};
	    10'd 13: lut_data <= {8'h78 , 24'h363312};
	    10'd 14: lut_data <= {8'h78 , 24'h3621e0};
	    10'd 15: lut_data <= {8'h78 , 24'h3704a0};
	    10'd 16: lut_data <= {8'h78 , 24'h37035a};
	    10'd 17: lut_data <= {8'h78 , 24'h371578};
	    10'd 18: lut_data <= {8'h78 , 24'h371701};
	    10'd 19: lut_data <= {8'h78 , 24'h370b60};
	    10'd 20: lut_data <= {8'h78 , 24'h37051a};
	    10'd 21: lut_data <= {8'h78 , 24'h390502};
	    10'd 22: lut_data <= {8'h78 , 24'h390610};
	    10'd 23: lut_data <= {8'h78 , 24'h39010a};
	    10'd 24: lut_data <= {8'h78 , 24'h373112};
	    10'd 25: lut_data <= {8'h78 , 24'h360008};// VCM control
	    10'd 26: lut_data <= {8'h78 , 24'h360133};// VCM control
	    10'd 27: lut_data <= {8'h78 , 24'h302d60};// system control
	    10'd 28: lut_data <= {8'h78 , 24'h362052};
	    10'd 29: lut_data <= {8'h78 , 24'h371b20};
	    10'd 30: lut_data <= {8'h78 , 24'h471c50};
	    10'd 31: lut_data <= {8'h78 , 24'h3a1343};// pre-gain = 1.047x
	    10'd 32: lut_data <= {8'h78 , 24'h3a1800};// gain ceiling
	    10'd 33: lut_data <= {8'h78 , 24'h3a19f8};// gain ceiling = 15.5x
	    10'd 34: lut_data <= {8'h78 , 24'h363513};
	    10'd 35: lut_data <= {8'h78 , 24'h363603};
	    10'd 36: lut_data <= {8'h78 , 24'h363440};
	    10'd 37: lut_data <= {8'h78 , 24'h362201}; // 50/60Hz detection     50/60Hz
	    10'd 38: lut_data <= {8'h78 , 24'h3c0134};// Band auto, bit[7]
	    10'd 39: lut_data <= {8'h78 , 24'h3c0428};// threshold low sum	 
	    10'd 40: lut_data <= {8'h78 , 24'h3c0598};// threshold high sum
	    10'd 41: lut_data <= {8'h78 , 24'h3c0600};// light meter 1 threshold[15:8]
	    10'd 42: lut_data <= {8'h78 , 24'h3c0708};// light meter 1 threshold[7:0]
	    10'd 43: lut_data <= {8'h78 , 24'h3c0800};// light meter 2 threshold[15:8]
	    10'd 44: lut_data <= {8'h78 , 24'h3c091c};// light meter 2 threshold[7:0]
	    10'd 45: lut_data <= {8'h78 , 24'h3c0a9c};// sample number[15:8]
	    10'd 46: lut_data <= {8'h78 , 24'h3c0b40};// sample number[7:0]
	    10'd 47: lut_data <= {8'h78 , 24'h381000};// Timing Hoffset[11:8]
	    10'd 48: lut_data <= {8'h78 , 24'h381110};// Timing Hoffset[7:0]
	    10'd 49: lut_data <= {8'h78 , 24'h381200};// Timing Voffset[10:8] 
	    10'd 50: lut_data <= {8'h78 , 24'h370864};
	    10'd 51: lut_data <= {8'h78 , 24'h400102};// BLC start from line 2
	    10'd 52: lut_data <= {8'h78 , 24'h40051a};// BLC always update
	    10'd 53: lut_data <= {8'h78 , 24'h300000};// enable blocks
	    10'd 54: lut_data <= {8'h78 , 24'h3004ff};// enable clocks 
	    10'd 55: lut_data <= {8'h78 , 24'h300e58};// MIPI power down, DVP enable
	    10'd 56: lut_data <= {8'h78 , 24'h302e00};
	    10'd 57: lut_data <= {8'h78 , 24'h430060};// RGB565
	    10'd 58: lut_data <= {8'h78 , 24'h501f01};// ISP RGB 
	    10'd 59: lut_data <= {8'h78 , 24'h440e00};
	    10'd 60: lut_data <= {8'h78 , 24'h5000a7}; // Lenc on, raw gamma on, BPC on, WPC on, CIP on 
	    10'd 61: lut_data <= {8'h78 , 24'h3a0f30};// stable range in high
	    10'd 62: lut_data <= {8'h78 , 24'h3a1028};// stable range in low
	    10'd 63: lut_data <= {8'h78 , 24'h3a1b30};// stable range out high
	    10'd 64: lut_data <= {8'h78 , 24'h3a1e26};// stable range out low
	    10'd 65: lut_data <= {8'h78 , 24'h3a1160};// fast zone high
	    10'd 66: lut_data <= {8'h78 , 24'h3a1f14};// fast zone low// Lens correction for
	    10'd 67: lut_data <= {8'h78 , 24'h580023};
	    10'd 68: lut_data <= {8'h78 , 24'h580114};
	    10'd 69: lut_data <= {8'h78 , 24'h58020f};
	    10'd 70: lut_data <= {8'h78 , 24'h58030f};
	    10'd 71: lut_data <= {8'h78 , 24'h580412};
	    10'd 72: lut_data <= {8'h78 , 24'h580526};
	    10'd 73: lut_data <= {8'h78 , 24'h58060c};
	    10'd 74: lut_data <= {8'h78 , 24'h580708};
	    10'd 75: lut_data <= {8'h78 , 24'h580805};
	    10'd 76: lut_data <= {8'h78 , 24'h580905};
	    10'd 77: lut_data <= {8'h78 , 24'h580a08};
	    10'd 78: lut_data <= {8'h78 , 24'h580b0d};
	    10'd 79: lut_data <= {8'h78 , 24'h580c08};
	    10'd 80: lut_data <= {8'h78 , 24'h580d03};
	    10'd 81: lut_data <= {8'h78 , 24'h580e00};
	    10'd 82: lut_data <= {8'h78 , 24'h580f00};
	    10'd 83: lut_data <= {8'h78 , 24'h581003};
	    10'd 84: lut_data <= {8'h78 , 24'h581109};
	    10'd 85: lut_data <= {8'h78 , 24'h581207};
	    10'd 86: lut_data <= {8'h78 , 24'h581303};
	    10'd 87: lut_data <= {8'h78 , 24'h581400};
	    10'd 88: lut_data <= {8'h78 , 24'h581501};
	    10'd 89: lut_data <= {8'h78 , 24'h581603};
	    10'd 90: lut_data <= {8'h78 , 24'h581708};
	    10'd 91: lut_data <= {8'h78 , 24'h58180d};
	    10'd 92: lut_data <= {8'h78 , 24'h581908};
	    10'd 93: lut_data <= {8'h78 , 24'h581a05};
	    10'd 94: lut_data <= {8'h78 , 24'h581b06};
	    10'd 95: lut_data <= {8'h78 , 24'h581c08};
	    10'd 96: lut_data <= {8'h78 , 24'h581d0e};
	    10'd 97: lut_data <= {8'h78 , 24'h581e29};
	    10'd 98: lut_data <= {8'h78 , 24'h581f17};
	    10'd 99: lut_data <= {8'h78 , 24'h582011};
	    10'd100: lut_data <= {8'h78 , 24'h582111};
	    10'd101: lut_data <= {8'h78 , 24'h582215};
	    10'd102: lut_data <= {8'h78 , 24'h582328};
	    10'd103: lut_data <= {8'h78 , 24'h582446};
	    10'd104: lut_data <= {8'h78 , 24'h582526};
	    10'd105: lut_data <= {8'h78 , 24'h582608};
	    10'd106: lut_data <= {8'h78 , 24'h582726};
	    10'd107: lut_data <= {8'h78 , 24'h582864};
	    10'd108: lut_data <= {8'h78 , 24'h582926};
	    10'd109: lut_data <= {8'h78 , 24'h582a24};
	    10'd110: lut_data <= {8'h78 , 24'h582b22};
	    10'd111: lut_data <= {8'h78 , 24'h582c24};
	    10'd112: lut_data <= {8'h78 , 24'h582d24};
	    10'd113: lut_data <= {8'h78 , 24'h582e06};
	    10'd114: lut_data <= {8'h78 , 24'h582f22};
	    10'd115: lut_data <= {8'h78 , 24'h583040};
	    10'd116: lut_data <= {8'h78 , 24'h583142};
	    10'd117: lut_data <= {8'h78 , 24'h583224};
	    10'd118: lut_data <= {8'h78 , 24'h583326};
	    10'd119: lut_data <= {8'h78 , 24'h583424};
	    10'd120: lut_data <= {8'h78 , 24'h583522};
	    10'd121: lut_data <= {8'h78 , 24'h583622};
	    10'd122: lut_data <= {8'h78 , 24'h583726};
	    10'd123: lut_data <= {8'h78 , 24'h583844};
	    10'd124: lut_data <= {8'h78 , 24'h583924};
	    10'd125: lut_data <= {8'h78 , 24'h583a26};
	    10'd126: lut_data <= {8'h78 , 24'h583b28};
	    10'd127: lut_data <= {8'h78 , 24'h583c42};
	    10'd128: lut_data <= {8'h78 , 24'h583dce};// lenc BR offset 
	    10'd129: lut_data <= {8'h78 , 24'h5180ff};// AWB B block
	    10'd130: lut_data <= {8'h78 , 24'h5181f2};// AWB control 
	    10'd131: lut_data <= {8'h78 , 24'h518200};// [7:4] max local counter, [3:0] max fast counter
	    10'd132: lut_data <= {8'h78 , 24'h518314};// AWB advanced 
	    10'd133: lut_data <= {8'h78 , 24'h518425};
	    10'd134: lut_data <= {8'h78 , 24'h518524};
	    10'd135: lut_data <= {8'h78 , 24'h518609};
	    10'd136: lut_data <= {8'h78 , 24'h518709};
	    10'd137: lut_data <= {8'h78 , 24'h518809};
	    10'd138: lut_data <= {8'h78 , 24'h518975};
	    10'd139: lut_data <= {8'h78 , 24'h518a54};
	    10'd140: lut_data <= {8'h78 , 24'h518be0};
	    10'd141: lut_data <= {8'h78 , 24'h518cb2};
	    10'd142: lut_data <= {8'h78 , 24'h518d42};
	    10'd143: lut_data <= {8'h78 , 24'h518e3d};
	    10'd144: lut_data <= {8'h78 , 24'h518f56};
	    10'd145: lut_data <= {8'h78 , 24'h519046};
	    10'd146: lut_data <= {8'h78 , 24'h5191f8};// AWB top limit
	    10'd147: lut_data <= {8'h78 , 24'h519204};// AWB bottom limit
	    10'd148: lut_data <= {8'h78 , 24'h519370};// red limit
	    10'd149: lut_data <= {8'h78 , 24'h5194f0};// green limit
	    10'd150: lut_data <= {8'h78 , 24'h5195f0};// blue limit
	    10'd151: lut_data <= {8'h78 , 24'h519603};// AWB control
	    10'd152: lut_data <= {8'h78 , 24'h519701};// local limit 
	    10'd153: lut_data <= {8'h78 , 24'h519804};
	    10'd154: lut_data <= {8'h78 , 24'h519912};
	    10'd155: lut_data <= {8'h78 , 24'h519a04};
	    10'd156: lut_data <= {8'h78 , 24'h519b00};
	    10'd157: lut_data <= {8'h78 , 24'h519c06};
	    10'd158: lut_data <= {8'h78 , 24'h519d82};
	    10'd159: lut_data <= {8'h78 , 24'h519e38};// AWB control 
	    10'd160: lut_data <= {8'h78 , 24'h548001};// Gamma bias plus on, bit[0] 
	    10'd161: lut_data <= {8'h78 , 24'h548108};
	    10'd162: lut_data <= {8'h78 , 24'h548214};
	    10'd163: lut_data <= {8'h78 , 24'h548328};
	    10'd164: lut_data <= {8'h78 , 24'h548451};
	    10'd165: lut_data <= {8'h78 , 24'h548565};
	    10'd166: lut_data <= {8'h78 , 24'h548671};
	    10'd167: lut_data <= {8'h78 , 24'h54877d};
	    10'd168: lut_data <= {8'h78 , 24'h548887};
	    10'd169: lut_data <= {8'h78 , 24'h548991};
	    10'd170: lut_data <= {8'h78 , 24'h548a9a};
	    10'd171: lut_data <= {8'h78 , 24'h548baa};
	    10'd172: lut_data <= {8'h78 , 24'h548cb8};
	    10'd173: lut_data <= {8'h78 , 24'h548dcd};
	    10'd174: lut_data <= {8'h78 , 24'h548edd};
	    10'd175: lut_data <= {8'h78 , 24'h548fea};
	    10'd176: lut_data <= {8'h78 , 24'h54901d};// color matrix 
	    10'd177: lut_data <= {8'h78 , 24'h53811e};// CMX1 for Y
	    10'd178: lut_data <= {8'h78 , 24'h53825b};// CMX2 for Y
	    10'd179: lut_data <= {8'h78 , 24'h538308};// CMX3 for Y
	    10'd180: lut_data <= {8'h78 , 24'h53840a};// CMX4 for U
	    10'd181: lut_data <= {8'h78 , 24'h53857e};// CMX5 for U
	    10'd182: lut_data <= {8'h78 , 24'h538688};// CMX6 for U
	    10'd183: lut_data <= {8'h78 , 24'h53877c};// CMX7 for V
	    10'd184: lut_data <= {8'h78 , 24'h53886c};// CMX8 for V
	    10'd185: lut_data <= {8'h78 , 24'h538910};// CMX9 for V
	    10'd186: lut_data <= {8'h78 , 24'h538a01};// sign[9]
	    10'd187: lut_data <= {8'h78 , 24'h538b98}; // sign[8:1] // UV adjust 
	    10'd188: lut_data <= {8'h78 , 24'h558006};// saturation on, bit[1]
	    10'd189: lut_data <= {8'h78 , 24'h558340};
	    10'd190: lut_data <= {8'h78 , 24'h558410};
	    10'd191: lut_data <= {8'h78 , 24'h558910};
	    10'd192: lut_data <= {8'h78 , 24'h558a00};
	    10'd193: lut_data <= {8'h78 , 24'h558bf8};
	    10'd194: lut_data <= {8'h78 , 24'h501d40};// enable manual offset of contrast
	    10'd195: lut_data <= {8'h78 , 24'h530008};// CIP sharpen MT threshold 1
	    10'd196: lut_data <= {8'h78 , 24'h530130};// CIP sharpen MT threshold 2
	    10'd197: lut_data <= {8'h78 , 24'h530210};// CIP sharpen MT offset 1
	    10'd198: lut_data <= {8'h78 , 24'h530300};// CIP sharpen MT offset 2
	    10'd199: lut_data <= {8'h78 , 24'h530408};// CIP DNS threshold 1
	    10'd200: lut_data <= {8'h78 , 24'h530530};// CIP DNS threshold 2
	    10'd201: lut_data <= {8'h78 , 24'h530608};// CIP DNS offset 1
	    10'd202: lut_data <= {8'h78 , 24'h530716};// CIP DNS offset 2 
	    10'd203: lut_data <= {8'h78 , 24'h530908};// CIP sharpen TH threshold 1
	    10'd204: lut_data <= {8'h78 , 24'h530a30};// CIP sharpen TH threshold 2
	    10'd205: lut_data <= {8'h78 , 24'h530b04};// CIP sharpen TH offset 1
	    10'd206: lut_data <= {8'h78 , 24'h530c06};// CIP sharpen TH offset 2
	    10'd207: lut_data <= {8'h78 , 24'h502500};
	    10'd208: lut_data <= {8'h78 , 24'h300802}; // wake up from standby, bit[6]
	    10'd209: lut_data <= {8'h78 , 24'h303511};// PLL
	    10'd210: lut_data <= {8'h78 , 24'h30368C};// PLL 46-30fps 8c-60fps
	    10'd211: lut_data <= {8'h78 , 24'h3c0708};// light meter 1 threshold [7:0]
	    10'd212: lut_data <= {8'h78 , 24'h382047};// Sensor flip off, ISP flip on
	    10'd213: lut_data <= {8'h78 , 24'h382101};// Sensor mirror on, ISP mirror on, H binning on
	    10'd214: lut_data <= {8'h78 , 24'h381431};// X INC 
	    10'd215: lut_data <= {8'h78 , 24'h381531};// Y INC
	    10'd216: lut_data <= {8'h78 , 24'h380000};// HS: X address start high byte
	    10'd217: lut_data <= {8'h78 , 24'h380100};// HS: X address start low byte
	    10'd218: lut_data <= {8'h78 , 24'h380200};// VS: Y address start high byte
	    10'd219: lut_data <= {8'h78 , 24'h380304};// VS: Y address start high byte 
	    10'd220: lut_data <= {8'h78 , 24'h38040a};// HW (HE)         
	    10'd221: lut_data <= {8'h78 , 24'h38053f};// HW (HE)
	    10'd222: lut_data <= {8'h78 , 24'h380607};// VH (VE)         
	    10'd223: lut_data <= {8'h78 , 24'h38079b};// VH (VE)      
	    10'd224: lut_data <= {8'h78 , 24'h380803};// DVPHO           //800
	    10'd225: lut_data <= {8'h78 , 24'h380920};// DVPHO
	    10'd226: lut_data <= {8'h78 , 24'h380a01};// DVPVO           //480
	    10'd227: lut_data <= {8'h78 , 24'h380be0};// DVPVO
	    10'd228: lut_data <= {8'h78 , 24'h380c07};// HTS            //Total horizontal size 
	    10'd229: lut_data <= {8'h78 , 24'h380d68};// HTS
	    10'd230: lut_data <= {8'h78 , 24'h380e03};// VTS            //total vertical size
	    10'd231: lut_data <= {8'h78 , 24'h380fd8};// VTS 
	    10'd232: lut_data <= {8'h78 , 24'h381306};// Timing Voffset 
	    10'd233: lut_data <= {8'h78 , 24'h361800};
	    10'd234: lut_data <= {8'h78 , 24'h361229};
	    10'd235: lut_data <= {8'h78 , 24'h370952};
	    10'd236: lut_data <= {8'h78 , 24'h370c03}; 
	    10'd237: lut_data <= {8'h78 , 24'h3a0217};// 60Hz max exposure, night mode 5fps
	    10'd238: lut_data <= {8'h78 , 24'h3a0310};// 60Hz max exposure // banding filters are calculated automatically in camera driver
	    10'd239: lut_data <= {8'h78 , 24'h3a1417};// 50Hz max exposure, night mode 5fps
	    10'd240: lut_data <= {8'h78 , 24'h3a1510};// 50Hz max exposure     
	    10'd241: lut_data <= {8'h78 , 24'h400402};// BLC 2 lines 
	    10'd242: lut_data <= {8'h78 , 24'h30021c};// reset JFIFO, SFIFO, JPEG
	    10'd243: lut_data <= {8'h78 , 24'h3006c3};// disable clock of JPEG2x, JPEG
	    10'd244: lut_data <= {8'h78 , 24'h471303};// JPEG mode 3
	    10'd245: lut_data <= {8'h78 , 24'h440704};// Quantization scale 
	    10'd246: lut_data <= {8'h78 , 24'h460b35};
	    10'd247: lut_data <= {8'h78 , 24'h460c22};
	    10'd248: lut_data <= {8'h78 , 24'h483722}; // DVP CLK divider
	    10'd249: lut_data <= {8'h78 , 24'h382402}; // DVP CLK divider 
	    10'd250: lut_data <= {8'h78 , 24'h5001a3}; // SDE on, scale on, UV average off, color matrix on, AWB on
	    10'd251: lut_data <= {8'h78 , 24'h350300}; // AEC/AGC on 
	    10'd252: lut_data <= {8'h78 , 24'h301602}; //Strobe output enable
	    10'd253: lut_data <= {8'h78 , 24'h3b070a}; //FREX strobe mode1		 
	    10'd254: lut_data <= {8'h78 , 24'h3b0083}; //STROBE CTRL: strobe request ON, Strobe mode: LED3 
	    10'd255: lut_data <= {8'h78 , 24'h3b0000}; //STROBE CTRL: strobe request OFF 
		10'd256: lut_data <= {8'hff , 24'hffffff};
		default:lut_data <= {8'h00,16'h0000,8'h00};
	endcase
end

endmodule

七、SCCB顶层文件

module IIC_top(
        input               wire                clk                 ,
        input               wire                sys_rst_n           ,
        input               wire                rst_n               ,
        inout               wire                sda                 ,
        output              wire                sda_en              ,
        output              wire                sys_clk             ,
        output              wire                xclk                ,
        output              wire                scl                 );
        
         reg     [5:0]   cnt_rs         ;
         wire    [7:0]   ins            ;
         wire    [15:0]  addr           ;
         wire    [7:0]   data           ;
         wire            sta_flag       ;
         wire            ready_flag     ;
         wire            clk_1          ;
reg             [5:0]       cnt_yu      ;

xclk_pll your_instance_name(
        .clkout(xclk), //output clkout
        .clkin(clk) //input clkin
    );




icck_pll iic_inst(
        .clkout(clk_1), //output clkout
        .clkin(clk) //input clkin
    );
         

assign sys_clk=((cnt_yu>=6'd0)&&(cnt_yu<=6'd25))?1'b1:1'b0;


always@(posedge clk_1 or negedge rst_n) begin
if(!rst_n)
cnt_yu<=6'b0;
else if(cnt_yu==6'd51)
cnt_yu<=6'b0;
else
cnt_yu<=cnt_yu+1'b1;
end


        IIC_start  IIC_start_inst(
    .sys_clk       (sys_clk    )  ,
    .sys_rst_n     (sys_rst_n  )  ,
    .ready_flag    (ready_flag )  ,
    .sta_flag      (sta_flag   )  ,
    .ins           (ins        )  ,
    .addr          (addr       )  ,
    .data          (data       )  );
    
    
    IIC_ctrl   IIC_ctrl_inst (
        .sys_clk     (sys_clk   )  ,
        .sys_rst_n   (sys_rst_n )  ,
        .sta_flag    (sta_flag  )  ,//开始标志,由外部传入
        .ins         (ins       )  ,
        .addr        (addr      )  ,
        .data        (data      )  ,
        .sda         (sda       )  ,
        .scl         (scl       )  ,
        .sda_en      (sda_en    )  ,
        .ready_flag  (ready_flag)  );
        
        
        endmodule
    

八、实验顶层代码

module IIC_data_uart (
        input               wire                clk                     ,
        input               wire                sys_rst_n               ,
        input               wire                rst_n                   ,
        input               wire                pclk                    ,
        input               wire                hsync                   ,
        input               wire        [7:0]   rgb_din                 ,
        input               wire                vsync                   ,
        output              wire                scl                     ,
        inout               wire                sda                     ,
        output              wire                xclk                    ,
        output              wire                pwdn                    ,
        output              wire                reset                   ,
        output              wire                sda_en                  ,
        output              wire                tx                      );
        
        
        data_uart data_uart_inst(
   .clk       (clk      )  ,
   .pclk      (pclk     )  ,
   .vsync     (vsync    )  ,
   .rgb_din   (rgb_din  )  ,
   .hsync     (hsync    )  ,
   .sys_rst_n (sys_rst_n)  ,
   .tx        (tx       )  );
        
        
        wire                power_done              ;
        
      
        IIC_top   IIC_top_inst(
        .clk           (clk         )     ,
        .sys_rst_n     (power_done  )     ,
        .sda           (sda         )     ,
        .sda_en        (sda_en      )     ,
        .sys_clk       (sys_clk     )     ,
        .xclk          (xclk        )     ,
        .rst_n         (rst_n       )     ,
        .scl           (scl         )     );
        
        
        power  power_inst(
           . sys_clk         (sys_clk     )   ,
           . sys_rst_n       (sys_rst_n   )   ,
           . reset           (reset       )   ,
           . pwdn            (pwdn        )   ,
           . power_done      (power_done  )   );
           
           
           endmodule

九、一些话

  由于SCCB协议和IIC协议几乎一摸一样,这里的模块命名都是用的IIC。数据手册这里贴不上来,兄弟们如果有需求的话评论区指出来,我到时候甩个网盘链接上去。OV5640输出数据类似于VGA和HDMI的时序,接下来会继续更新VGA和HDMI的相关时序分析和代码。

  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值