module i2c_fifo ( input wire clock, reset, input wire bus_ssel, bus_wren, input wire [15:0] bus_mosi, output wire bus_busy, inout wire i2c_sda, inout wire i2c_scl ); wire int_rdempty, int_wrfull, i2c_clk, start, stop; wire [15:0] int_q; reg int_bus_busy; reg int_rdreq, int_wrreq, int_clken, int_sdo, int_scl, int_ack; reg [15:0] int_bus_mosi; reg [15:0] int_data; reg [9:0] counter; reg [4:0] state; assign i2c_sda = int_sdo ? 1'bz : 1'b0; assign i2c_scl = int_scl | (int_clken ? counter[9] : 1'b0); assign start = int_data[8]; assign stop = int_data[9]; scfifo #( .add_ram_output_register("OFF"), .intended_device_family("Cyclone III"), .lpm_numwords(16), .lpm_showahead("ON"), .lpm_type("scfifo"), .lpm_width(16), .lpm_widthu(4), .overflow_checking("ON"), .underflow_checking("ON"), .use_eab("OFF")) fifo_tx ( .rdreq((~int_rdempty) & (int_rdreq) & (&counter)), .aclr(1'b0), .clock(clock), .wrreq(int_wrreq), .data(int_bus_mosi), .empty(int_rdempty), .q(int_q), .full(int_wrfull), .almost_empty(), .almost_full(), .sclr(), .usedw()); always @ (posedge clock) begin int_bus_busy <= int_wrfull; if (bus_ssel) begin if (~int_wrfull & bus_wren) begin int_bus_mosi <= bus_mosi; int_wrreq <= 1'b1; end end if (~int_wrfull & int_wrreq) begin int_wrreq <= 1'b0; end end always @ (posedge clock) begin counter <= counter + 10'd1; if (&counter) 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 end // output logic assign bus_busy = int_bus_busy; endmodule