Make it work
[clump.git] / i2c.v
diff --git a/i2c.v b/i2c.v
index 68156179eda6376324d90c5c941cc91e1db36dbb..9620ba05df43f6f6749e937555e2d01c0f8e9140 100644 (file)
--- a/i2c.v
+++ b/i2c.v
@@ -15,12 +15,13 @@ parameter CLOCK_DIVIDE = 1;
 // 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;
+parameter TX_START = 1;
+parameter TX_ADDRESS = 2;
+parameter TX_FIRST_BYTE = 3;
+parameter TX_MORE_BYTES = 4;
+parameter TX_STOP = 5;
 
-reg [10:0] tx_clk_divider = CLOCK_DIVIDE;
+reg [30:0] tx_clk_divider = CLOCK_DIVIDE;
 
 reg data_out = 1'b1;
 reg clk_out = 1'b1;
@@ -31,6 +32,7 @@ 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};
@@ -38,37 +40,37 @@ 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
-       // 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)
+   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
-                  // 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;
+                  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(step == 0) 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
@@ -97,7 +99,8 @@ always @(posedge clk) begin
         end // case: TX_ADDRESS
 
         TX_FIRST_BYTE: begin
-               if(step == 0) 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
@@ -110,7 +113,12 @@ always @(posedge clk) begin
                   end else begin
                          step <= 0;
 
-                         tx_state <= TX_STOP;
+                         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];
@@ -124,8 +132,41 @@ always @(posedge clk) begin
                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(step == 0) begin
+               if(tx_clk_divider) begin end
+               else if(step == 0) begin
                   clk_out <= 0;
                   step <= 1;
                end else if(step == 1) begin
This page took 0.011777 seconds and 4 git commands to generate.