module i2c_write ( input clk, output scl, output sda, input [7:0] tx_byte, input transmit, input [5:0] more_bytes, /* 0 or 1 or 16 are reasonable */ input [7:0] mb_in, output [5:0] mb_addr, output is_transmitting); parameter CLOCK_DIVIDE = 1; // States for the transmitting state machine. // We transmit a START, then the address (constant 0xE1), then // [tx_byte], then [more_bytes] bytes from [mb_in] parameter TX_IDLE = 0; parameter TX_START = 1; parameter TX_ADDRESS = 2; parameter TX_FIRST_BYTE = 3; parameter TX_MORE_BYTES = 4; parameter TX_STOP = 5; reg [30:0] tx_clk_divider = CLOCK_DIVIDE; reg data_out = 1'b1; reg clk_out = 1'b1; reg [3:0] tx_state = TX_IDLE; reg [5:0] tx_countdown; reg [3:0] tx_bits_remaining; reg [7:0] tx_data; reg [3:0] step = 0; reg [5:0] more_bytes_idx = 0; wire [7:0] address = {7'h70, 1'b0}; // address 0x70, write wire [15:0] address_data = {address, tx_data}; assign sda = data_out; assign scl = clk_out; assign is_transmitting = tx_state != TX_IDLE; assign mb_addr = more_bytes_idx; always @(posedge clk) begin if(tx_clk_divider) begin tx_clk_divider <= tx_clk_divider - 1; end else begin tx_clk_divider <= CLOCK_DIVIDE - 1; end case (tx_state) TX_IDLE: begin if (transmit) begin tx_data = tx_byte; tx_bits_remaining = 8; step = 0; tx_state = TX_START; tx_clk_divider <= CLOCK_DIVIDE - 1; end end // case: TX_IDLE TX_START: begin if(tx_clk_divider) begin end else begin data_out = 0; tx_state = TX_ADDRESS; end end TX_ADDRESS: begin if(tx_clk_divider) begin end else if(step == 0) begin clk_out <= 0; step <= 1; end else if (tx_bits_remaining == 0) begin if(step == 1) begin data_out <= 0; // really should be z, not 0 step <= 2; end else if(step == 2)begin clk_out <= 1; step <= 3; end else begin step <= 0; tx_state <= TX_FIRST_BYTE; tx_bits_remaining <= 8; end end else if(step == 1) begin data_out <= address[tx_bits_remaining - 1]; step <= 2; end else if(step == 2) begin clk_out <= 1; step <= 3; end else begin // step == 3 tx_bits_remaining = tx_bits_remaining - 1; step <= 0; end end // case: TX_ADDRESS TX_FIRST_BYTE: begin if(tx_clk_divider) begin end else if(step == 0) begin clk_out <= 0; step <= 1; end else if (tx_bits_remaining == 0) begin if(step == 1) begin data_out <= 0; // really should be z, not 0 step <= 2; end else if(step == 2)begin clk_out <= 1; step <= 3; end else begin step <= 0; if(more_bytes) tx_state <= TX_MORE_BYTES; else tx_state <= TX_STOP; tx_bits_remaining <= 8; more_bytes_idx <= 0; end end else if(step == 1) begin data_out <= tx_data[tx_bits_remaining - 1]; step <= 2; end else if(step == 2) begin clk_out <= 1; step <= 3; end else begin // step == 3 tx_bits_remaining = tx_bits_remaining - 1; step <= 0; end end // case: TX_FIRST_BYTE TX_MORE_BYTES: begin if(tx_clk_divider) begin end else if(step == 0) begin clk_out <= 0; step <= 1; end else if (tx_bits_remaining == 0) begin if(step == 1) begin data_out <= 0; // really should be z, not 0 step <= 2; end else if(step == 2)begin clk_out <= 1; step <= 3; end else begin step <= 0; tx_bits_remaining <= 8; if(more_bytes_idx == more_bytes) tx_state <= TX_STOP; more_bytes_idx <= more_bytes_idx + 1; end end else if(step == 1) begin data_out <= mb_in[tx_bits_remaining - 1]; step <= 2; end else if(step == 2) begin clk_out <= 1; step <= 3; end else begin // step == 3 tx_bits_remaining = tx_bits_remaining - 1; step <= 0; end end // case: TX_MORE_BYTES TX_STOP: begin if(tx_clk_divider) begin end else if(step == 0) begin clk_out <= 0; step <= 1; end else if(step == 1) begin step <= 2; end else if(step == 2) begin clk_out <= 1; step <= 3; end else begin data_out <= 1; step <= 0; tx_state <= TX_IDLE; end end endcase end endmodule // i2c_write