X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=i2c.v;fp=i2c.v;h=68156179eda6376324d90c5c941cc91e1db36dbb;hb=ffba35f814eda0a4c47af601206cf2d3ab6eab03;hp=0000000000000000000000000000000000000000;hpb=7f1b6bd9e0070ddc074215defc46d64abef645ac;p=clump.git diff --git a/i2c.v b/i2c.v new file mode 100644 index 0000000..6815617 --- /dev/null +++ b/i2c.v @@ -0,0 +1,144 @@ +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