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_ADDRESS = 1; parameter TX_FIRST_BYTE = 2; parameter TX_MORE_BYTES = 3; parameter TX_STOP = 4; reg [10: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; 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; always @(posedge clk) begin // The clk_divider counter counts down from // the CLOCK_DIVIDE constant. Whenever it // reaches 0, 1/16 of the bit period has elapsed. // Countdown timers for the receiving and transmitting // state machines are decremented. tx_clk_divider = tx_clk_divider - 1; if (!tx_clk_divider) begin tx_clk_divider = CLOCK_DIVIDE; tx_countdown = tx_countdown - 1; end // Transmit state machine case (tx_state) TX_IDLE: begin if (transmit) begin // If the transmit flag is raised in the idle // state, save tx_byte for transmission tx_data = tx_byte; // Send the initial, low pulse of 1 bit period // to signal the start, followed by the data data_out = 0; tx_state = TX_ADDRESS; tx_bits_remaining = 8; step = 0; end end // case: TX_IDLE TX_ADDRESS: begin 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(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_STOP; 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_STOP: begin 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