module OV5647_Registers 
(
    input clk, 
    input resend, 
    input taken, 
    output waitnull, //wait signal. 1 wait
    output [23:0] command, 
    output finished
);

//------------------------------------------------
localparam STARTTIME = 32'd4_000;
localparam WAITTIME  = 32'd5_000_000; //32'd5_000_000; //10ms 

reg [31:0] wait_cnt;
reg        wait_flag;

    // Internal signals
    reg [23:0] sreg;
    reg finished_temp;
    reg [8:0] address;
    
    // Assign values to outputs
    assign command = sreg; 
    assign finished = finished_temp;
    
    assign waitnull = wait_flag;
    
    // When register and value is FFFF
    // a flag is asserted indicating the configuration is finished
    always @ (sreg) begin
        if(sreg == 24'hFFFFFF) begin
            finished_temp <= 1;
        end
        else begin
            finished_temp <= 0;
        end
    end
 
    //--------------------------------------------------------
	//wait at least 5ms
    always @ (posedge clk)
    begin
    	if(resend == 1)
    		wait_cnt <= 32'd0;
    	else if(address == 1)
    		begin
    			if(wait_cnt>=(STARTTIME+WAITTIME))
    				wait_cnt <= wait_cnt;
    			else
    				wait_cnt <= wait_cnt + 1'b1;
    		end
    	else
    		wait_cnt <= 32'd0;
    end
    
    always @ (posedge clk)
    begin
    	if(resend == 1)
    		wait_flag <= 1'b0;
    	else if(wait_cnt > STARTTIME && wait_cnt < WAITTIME)
    		wait_flag <= 1'b1;
    	else
    		wait_flag <= 1'b0;
    end

    //--------------------------------------------------------
    
    // Get value out of the LUT
    always @ (posedge clk) begin
        if(resend == 1)         address <= 9'd0;// reset the configuration
        else if(taken == 1)     address <= address+2'd1;// Get the next value
           
/*

400x400 at 30Hz
DE duty cycle: 30%
VS duty cycle: 96.4%
Write(adr, 0x30, 0x36, 0x70); // PLL multiplier

Write(adr, 0x38, 0x00, 0x06, 0x80); // hstart
Write(adr, 0x38, 0x04, 0x08, 0xB0); // hend
Write(adr, 0x38, 0x08, 0x01, 0x90); // hout
Write(adr, 0x38, 0x0C, 0x04, 0xF0); // hts

Write(adr, 0x38, 0x02, 0x01, 0xB2); // vstart
Write(adr, 0x38, 0x06, 0x05, 0xF1); // vend
Write(adr, 0x38, 0x0A, 0x01, 0x90); // vout
Write(adr, 0x38, 0x0E, 0x01, 0xA0); // vts
*/

        case (address)  
			000 : sreg <= 24'h0100_00; //0x0100[0] software standby                   //////////////// Global Initial
			001 : sreg <= 24'h0103_01; //0x0103[0] software reset, 1 reset     // then need to wait at least 5ms
			002 : sreg <= 24'h3016_08; //[3] mipi pad enable
			003 : sreg <= 24'h3018_44; //0x3018[7:5] MIPI lane, 0x3018[2] MIPI enable
			004 : sreg <= 24'h4800_04; //MIPI CTRL 00 [4] 1:send line short packet   0:not send
			005 : sreg <= 24'h3106_05; //SRB CTRL  PLL clock divider     //05             
			006 : sreg <= 24'h0100_01; //0x0100[0] wake up from software standby      //////////////// End Global Initial 
			007 : sreg <= 24'h0100_00; //0x0100[0] software standby                   //////////////// Set 1080p:1920*1080@30fps
			008 : sreg <= 24'h3034_18; //[3:0] 8:8 bit mode  A:10 bit mode 
			009 : sreg <= 24'h3035_11; //0x3035[7:4] pll_div, 0x3035[3:0] divider_mipi 
//			009 : sreg <= 24'h3035_21; //0x3035[7:4] pll_div, 0x3035[3:0] divider_mipi 
//			010 : sreg <= 24'h3036_50; //0x3036[7:0] pll_multiplier //x64 //x50
//			010 : sreg <= 24'h3036_BA; //0x3036[7:0] pll_multiplier //x64 //x50
			010 : sreg <= 24'h3036_CB; //0x3036[7:0] pll_multiplier //x64 //x50
			011 : sreg <= 24'h303c_11; //PLL ctrol 
			012 : sreg <= 24'h3800_01; //0x3800[3:0] = dvp_hstart[11:8]
			013 : sreg <= 24'h3801_5c; //0x3801[7:0] = dvp_hstart[7:0]   //348
			014 : sreg <= 24'h3802_01; //0x3802[3:0] = dvp_vstart[11:8]
			015 : sreg <= 24'h3803_b2; //0x3803[7:0] = dvp_vstart[7:0]   //434
			016 : sreg <= 24'h3804_08; //0x3804[3:0] = dvp_hend[11:8]
			017 : sreg <= 24'h3805_e3; //0x3805[7:0] = dvp_hend[7:0]     //2275
			018 : sreg <= 24'h3806_05; //0x3806[3:0] = dvp_vend[11:8]
			019 : sreg <= 24'h3807_f1; //0x3807[7:0] = dvp_vend[7:0]     //1521
			020 : sreg <= 24'h3808_07; //0x3808[3:0] = dvp_hout[11:8]
			021 : sreg <= 24'h3809_80; //0x3809[7:0] = dvp_hout[7:0]     //1920
			022 : sreg <= 24'h380a_04; //0x380a[3:0] = dvp_vout[11:8]
			023 : sreg <= 24'h380b_38; //0x380b[7:0] = dvp_vout[7:0]     //1080
			024 : sreg <= 24'h380c_09; //0x380c[4:0] = h_total[12:8]
			025 : sreg <= 24'h380d_70; //0x380d[7:0] = h_total[7:0]   //70//2416    //4e//2382
			026 : sreg <= 24'h380e_04; //0x380e[4:0] = v_total[12:8]
			027 : sreg <= 24'h380f_50; //0x380f[7:0] = v_total[7:0]   //50//1104    //60//1120
			028 : sreg <= 24'h3814_11; //h subsample inc
			029 : sreg <= 24'h3815_11; //v subsample inc  
			030 : sreg <= 24'h3820_00; //TC_REG20 [2:1] filp
			031 : sreg <= 24'h3821_00; //TC_REG21 [2:1] mirror 
			032 : sreg <= 24'h503d_00; //[7] testpattern_en 0:disable, 1:enable //80 //82 //92
			033 : sreg <= 24'h3612_5b; //0x3600~0x3637 Analog control registers
			034 : sreg <= 24'h3618_04; //0x3600~0x3637 Analog control registers
			035 : sreg <= 24'h3708_64; //0x3700~0x373a Analog control registers //64
			036 : sreg <= 24'h3709_12; //0x3700~0x373a Analog control registers
			037 : sreg <= 24'h370c_03; //0x3700~0x373a Analog control registers ////03 or 0f
			038 : sreg <= 24'h3630_2e; //0x3600~0x3637 Analog control registers
			039 : sreg <= 24'h3632_e2; //0x3600~0x3637 Analog control registers
			040 : sreg <= 24'h3633_23; //0x3600~0x3637 Analog control registers
			041 : sreg <= 24'h3634_44; //0x3600~0x3637 Analog control registers
//			042 : sreg <= 24'h0100_01; //0x0100[0] wake up from software standby      //////////////// End Set 1080p
            //! Adj. MIPI parameters
            042 : sreg <= 24'h4824_00;
            043 : sreg <= 24'h4825_32;  // LPX_P_MIN
            044 : sreg <= 24'h4830_00;  // UI_LPX_P_MIN
            045 : sreg <= 24'h4826_00;
            046 : sreg <= 24'h4827_32;  // HX_PREPAREE_MIN
            047 : sreg <= 24'h4831_04;  // UI_HX_PREPAREE_MIN
            048 : sreg <= 24'h4818_00;
            049 : sreg <= 24'h4819_96;  // HS_ZERO_MIN
            050 : sreg <= 24'h482A_20;  // UI_HS_ZERO_MIN
            051 : sreg <= 24'h481A_00;
            052 : sreg <= 24'h481B_3C;  // HS_TRAIL_MIN
            053 : sreg <= 24'h482B_0C;  // UI_HS_TRAIL_MIN
            054 : sreg <= 24'h4828_00;
            055 : sreg <= 24'h4829_64;  // HS_EXIT_MIN
            056 : sreg <= 24'h4832_04;  // UI_HS_EXIT_MIN
            057 : sreg <= 24'h0100_01;  //0x0100[0] wake up from software standby      //////////////// End Set 1080p
/*
            058 : sreg <= 24'h0100_00; // back to standby
            059 : sreg <= 24'h3800_06;
            060 : sreg <= 24'h3801_80; // hstart = 0x680 = 1664
            061 : sreg <= 24'h3804_08; //
            062 : sreg <= 24'h3805_B0; // hend = 0x8B0 = 2224
            063 : sreg <= 24'h3808_01; //
            064 : sreg <= 24'h3809_90; // hout = 0x190 = 400
            065 : sreg <= 24'h380C_07; //
            066 : sreg <= 24'h380D_B0; // hts = 0x7B0 = 1968
            067 : sreg <= 24'h3802_01; //
            068 : sreg <= 24'h3803_B2; // vstart = 0x1B2 = 434
            069 : sreg <= 24'h3806_05; //
            070 : sreg <= 24'h3807_F1; // vend = 0x5F1 = 1521
            071 : sreg <= 24'h380A_01; //
            072 : sreg <= 24'h380B_90; // vout = 0x190 = 400
            073 : sreg <= 24'h380E_01; //
            074 : sreg <= 24'h380F_A0; // vts = 0x1A0 = 416
            075 : sreg <= 24'h3036_10; // PLL multiplier = 16
            076 : sreg <= 24'h3035_31; // pll div, divider_mipi
            077 : sreg <= 24'h0100_01; // out of standby
*/
			default : sreg <= 24'hFFFF_FF;    // End configuration
        endcase  
            
    end 
    
endmodule               
                        
    //-------------------------------------------------------------------------------  
    // PLL MY_OUTPUT clock(fclk)  
    // fclk = (0x40 - 0x300E[5:0]) x N x Bit8Div x MCLK / M, where  
    //      N = 1, 1.5, 2, 3 for 0x300F[7:6] = 0~3, respectively  
    //      M = 1, 1.5, 2, 3 for 0x300F[1:0] = 0~3, respectively  
    //      Bit8Div = 1, 1, 4, 5 for 0x300F[5:4] = 0~3, respectively  
    // Sys Clk = fclk / Bit8Div / SenDiv  
    // Sensor MY_OUTPUT clock(DVP PCLK)  
    // DVP PCLK = ISP CLK / DVPDiv, where  
    //      ISP CLK =  fclk / Bit8Div / SenDiv / CLKDiv / 2, where  
    //          Bit8Div = 1, 1, 4, 5 for 0x300F[5:4] = 0~3, respectively  
    //          SenDiv = 1, 2 for 0x3010[4] = 0 or 1 repectively  
    //          CLKDiv = (0x3011[5:0] + 1)  
    //      DVPDiv = 0x304C[3:0] * (2 ^ 0x304C[4]), if 0x304C[3:0] = 0, use 16 instead  
    //  
    // Base shutter calculation  
    //      60Hz: (1/120) * ISP Clk / QXGA_MODE_WITHOUT_DUMMY_PIXELS  
    //      50Hz: (1/100) * ISP Clk / QXGA_MODE_WITHOUT_DUMMY_PIXELS  
    //-------------------------------------------------------------------------------                          
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        