module i2c_fifo ( input wire clk, aclr, input wire wrreq, input wire [15:0] data, output wire full, inout wire i2c_sda, output wire i2c_scl ); wire int_rdempty, i2c_clk, start, stop; wire [15:0] int_q; reg int_rdreq, int_clken, int_sdo, int_scl, int_ack; reg [15:0] int_data; reg [8:0] counter; reg [4:0] state; assign i2c_clk = counter[8]; assign i2c_sda = int_sdo ? 1'bz : 1'b0; assign i2c_scl = int_scl | (int_clken ? ~i2c_clk : 1'b0); assign start = int_data[8]; assign stop = int_data[9]; dcfifo #( .intended_device_family("Cyclone III"), .lpm_numwords(16), .lpm_showahead("ON"), .lpm_type("dcfifo"), .lpm_width(16), .lpm_widthu(4), .rdsync_delaypipe(4), .wrsync_delaypipe(4), .overflow_checking("ON"), .underflow_checking("ON"), .use_eab("OFF"), .write_aclr_synch("OFF")) fifo_tx ( .aclr(aclr), .data(data), .rdclk(i2c_clk), .rdreq((~int_rdempty) & int_rdreq), .wrclk(clk), .wrreq(wrreq), .q(int_q), .rdempty(int_rdempty), .wrfull(full), .rdfull(), .rdusedw(), .wrempty(), .wrusedw()); always @ (posedge clk) begin counter <= counter + 9'd1; end always @ (posedge i2c_clk) begin case (state) 0: begin int_ack <= 1'b0; int_sdo <= 1'b1; int_scl <= 1'b1; int_rdreq <= 1'b1; state <= 5'd1; end 1: begin if (~int_rdempty) begin int_data <= int_q; int_rdreq <= 1'b0; state <= 5'd2; end end 2: begin if (start) begin int_sdo <= 1'b1; int_scl <= 1'b1; state <= 5'd3; end else begin state <= 5'd5; end end 3: begin // start int_sdo <= 1'b0; state <= 5'd4; end 4: begin int_scl <= 1'b0; state <= 5'd5; end 5: begin // data int_clken <= 1'b1; int_sdo <= int_data[7]; state <= 5'd6; end 6: begin int_sdo <= int_data[6]; state <= 5'd7; end 7: begin int_sdo <= int_data[5]; state <= 5'd8; end 8: begin int_sdo <= int_data[4]; state <= 5'd9; end 9: begin int_sdo <= int_data[3]; state <= 5'd10; end 10: begin int_sdo <= int_data[2]; state <= 5'd11; end 11: begin int_sdo <= int_data[1]; state <= 5'd12; end 12: begin int_sdo <= int_data[0]; state <= 5'd13; end 13: begin // ack int_sdo <= 1'b1; int_rdreq <= 1'b1; state <= 5'd14; end 14: begin int_ack <= i2c_sda; int_rdreq <= 1'b0; if (stop | int_rdempty) begin int_clken <= 1'b0; int_sdo <= 1'b0; int_scl <= 1'b0; state <= 5'd15; end else if (~int_rdempty) begin int_data <= int_q; int_sdo <= int_q[7]; state <= 5'd6; end end 15: begin // stop int_scl <= 1'b1; state <= 5'd16; end 16: begin int_sdo <= 1'b1; state <= 5'd0; end endcase end endmodule