--- /dev/null
+`timescale 1 ns / 100 ps
+module iic_init( Clk, //I
+ Reset_n, //I
+ Pixel_clk_greater_than_65Mhz, //I
+ SDA, //IO
+ SCL, //IO
+ Done //O
+ );
+
+input Clk;
+input Reset_n;
+input Pixel_clk_greater_than_65Mhz;
+inout SDA;
+inout SCL;
+output Done;
+
+parameter CLK_RATE_MHZ = 200,
+ SCK_PERIOD_US = 30,
+ TRANSITION_CYCLE = (CLK_RATE_MHZ * SCK_PERIOD_US) / 2,
+ TRANSITION_CYCLE_MSB = 11;
+
+
+localparam IDLE = 3'd0,
+ INIT = 3'd1,
+ START = 3'd2,
+ CLK_FALL = 3'd3,
+ SETUP = 3'd4,
+ CLK_RISE = 3'd5,
+ WAIT = 3'd6,
+ START_BIT = 1'b1,
+ SLAVE_ADDR= 7'b1110110,
+ ACK = 1'b1,
+ WRITE = 1'b0,
+ REG_ADDR0 = 8'h49,
+ REG_ADDR1 = 8'h21,
+ REG_ADDR2 = 8'h33,
+ REG_ADDR3 = 8'h34,
+ REG_ADDR4 = 8'h36,
+ DATA0 = 8'hC0,
+ DATA1 = 8'h09,
+ DATA2a = 8'h06,
+ DATA3a = 8'h26,
+ DATA4a = 8'hA0,
+ DATA2b = 8'h08,
+ DATA3b = 8'h16,
+ DATA4b = 8'h60,
+ STOP_BIT=1'b0,
+ SDA_BUFFER_MSB=27;
+
+reg SDA_out;
+reg SCL_out;
+reg [TRANSITION_CYCLE_MSB:0] cycle_count;
+reg [2:0] c_state;
+reg [2:0] n_state;
+reg Done;
+reg [2:0] write_count;
+reg [31:0] bit_count;
+reg [SDA_BUFFER_MSB:0] SDA_BUFFER;
+wire transition;
+
+always @ (posedge Clk) begin
+ if (~Reset_n||c_state==IDLE ) begin
+ SDA_out <= 1'b1;
+ SCL_out <=1'b1;
+ end
+ else if (c_state==INIT && transition) begin
+ SDA_out <=1'b0;
+ end
+ else if (c_state==SETUP) begin
+ SDA_out <=SDA_BUFFER[SDA_BUFFER_MSB];
+ end
+ else if (c_state==CLK_RISE && cycle_count==TRANSITION_CYCLE/2 && bit_count==SDA_BUFFER_MSB) begin
+ SDA_out <= 1'b1;
+ end
+ else if (c_state==CLK_FALL) begin
+ SCL_out <=1'b0;
+ end
+
+ else if (c_state==CLK_RISE) begin
+ SCL_out <=1'b1;
+ end
+end
+
+//OBUFT_LVCMOS33 sda0(.O(SDA), .I(1'b0), .T(SDA_out));
+//OBUFT_LVCMOS33 scl0(.O(SCL), .I(1'b0), .T(SCL_out));
+assign SDA = SDA_out;
+assign SCL = SCL_out;
+
+always @ (posedge Clk) begin
+ //reset or end condition
+ if(~Reset_n) begin
+ SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR0,ACK,DATA0,ACK,STOP_BIT};
+ cycle_count<=0;
+
+ end
+ //setup sda for sck rise
+ else if ( c_state==SETUP && cycle_count==TRANSITION_CYCLE)begin
+ SDA_BUFFER <= {SDA_BUFFER[SDA_BUFFER_MSB-1:0],1'b0};
+ cycle_count<=0;
+ end
+ //reset count at end of state
+ else if ( cycle_count==TRANSITION_CYCLE)
+ cycle_count<=0;
+ //reset sda_buffer
+ else if (c_state==WAIT && Pixel_clk_greater_than_65Mhz )begin
+ case(write_count)
+ 0:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR1,ACK,DATA1,ACK,STOP_BIT};
+ 1:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR2,ACK,DATA2a,ACK,STOP_BIT};
+ 2:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR3,ACK,DATA3a,ACK,STOP_BIT};
+ 3:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR4,ACK,DATA4a,ACK,STOP_BIT};
+ default: SDA_BUFFER <=28'dx;
+ endcase
+ cycle_count<=cycle_count+1;
+
+ end
+ else if (c_state==WAIT && ~Pixel_clk_greater_than_65Mhz )begin
+ case(write_count)
+ 0:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR1,ACK,DATA1,ACK,STOP_BIT};
+ 1:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR2,ACK,DATA2b,ACK,STOP_BIT};
+ 2:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR3,ACK,DATA3b,ACK,STOP_BIT};
+ 3:SDA_BUFFER <= {SLAVE_ADDR,WRITE,ACK,REG_ADDR4,ACK,DATA4b,ACK,STOP_BIT};
+ default: SDA_BUFFER <=28'dx;
+ endcase
+ cycle_count<=cycle_count+1;
+ end
+ else
+ cycle_count<=cycle_count+1;
+end
+
+always @ (posedge Clk) begin
+ if(~Reset_n)
+ write_count<=3'd0;
+ else if (c_state==WAIT && cycle_count==TRANSITION_CYCLE)
+ write_count<=write_count+1;
+end
+
+
+always @ (posedge Clk) begin
+ if(~Reset_n)
+ Done<=1'b0;
+ else if (c_state==IDLE)
+ Done<=1'b1;
+end
+
+
+
+
+always @ (posedge Clk) begin
+ if(~Reset_n||(c_state==WAIT))
+ bit_count<=0;
+ else if ( c_state==CLK_RISE && cycle_count==TRANSITION_CYCLE)
+ bit_count<=bit_count+1;
+end
+
+
+
+always @ (posedge Clk) begin
+ if(~Reset_n)
+ c_state<=INIT;
+ else
+ c_state<=n_state;
+end
+
+
+
+assign transition = (cycle_count==TRANSITION_CYCLE);
+
+//Next state
+always @ (*) begin
+ case(c_state)
+ IDLE: begin
+ if(~Reset_n) n_state = INIT;
+ else n_state = IDLE;
+ end
+ INIT: begin
+ if (transition) n_state = START;
+ else n_state = INIT;
+ end
+ START: begin
+ if(~Reset_n) n_state = INIT;
+ else if( transition) n_state = CLK_FALL;
+ else n_state = START;
+ end
+ CLK_FALL: begin
+ if(~Reset_n) n_state = INIT;
+ else if( transition) n_state = SETUP;
+ else n_state = CLK_FALL;
+ end
+ SETUP: begin
+ if(~Reset_n) n_state = INIT;
+ else if( transition) n_state = CLK_RISE;
+ else n_state = SETUP;
+ end
+ CLK_RISE: begin
+ if(~Reset_n)
+ n_state = INIT;
+ else if( transition && bit_count==SDA_BUFFER_MSB)
+ n_state = WAIT;
+ else if (transition )
+ n_state = CLK_FALL;
+ else n_state = CLK_RISE;
+ end
+ WAIT: begin
+ if(~Reset_n|(transition && write_count!=3'd4))
+ n_state = INIT;
+ else if (transition )
+ n_state = IDLE;
+ else n_state = WAIT;
+ end
+ default: n_state = IDLE;
+
+ endcase
+end
+
+
+
+
+
+endmodule