Implement a tiny part of i2c
[clump.git] / i2c.v
CommitLineData
ffba35f8
MG
1module i2c_write (
2 input clk,
3 output scl,
4 output sda,
5 input [7:0] tx_byte,
6 input transmit,
7 input [5:0] more_bytes, /* 0 or 1 or 16 are reasonable */
8 input [7:0] mb_in,
9 output [5:0] mb_addr,
10 output is_transmitting);
11
12parameter CLOCK_DIVIDE = 1;
13
14// States for the transmitting state machine.
15// We transmit a START, then the address (constant 0xE1), then
16// [tx_byte], then [more_bytes] bytes from [mb_in]
17parameter TX_IDLE = 0;
18parameter TX_ADDRESS = 1;
19parameter TX_FIRST_BYTE = 2;
20parameter TX_MORE_BYTES = 3;
21parameter TX_STOP = 4;
22
23reg [10:0] tx_clk_divider = CLOCK_DIVIDE;
24
25reg data_out = 1'b1;
26reg clk_out = 1'b1;
27
28reg [3:0] tx_state = TX_IDLE;
29reg [5:0] tx_countdown;
30reg [3:0] tx_bits_remaining;
31reg [7:0] tx_data;
32
33reg [3:0] step = 0;
34
35wire [7:0] address = {7'h70, 1'b0}; // address 0x70, write
36wire [15:0] address_data = {address, tx_data};
37
38assign sda = data_out;
39assign scl = clk_out;
40assign is_transmitting = tx_state != TX_IDLE;
41
42always @(posedge clk) begin
43 // The clk_divider counter counts down from
44 // the CLOCK_DIVIDE constant. Whenever it
45 // reaches 0, 1/16 of the bit period has elapsed.
46 // Countdown timers for the receiving and transmitting
47 // state machines are decremented.
48 tx_clk_divider = tx_clk_divider - 1;
49 if (!tx_clk_divider) begin
50 tx_clk_divider = CLOCK_DIVIDE;
51 tx_countdown = tx_countdown - 1;
52 end
53
54 // Transmit state machine
55 case (tx_state)
56 TX_IDLE: begin
57 if (transmit) begin
58 // If the transmit flag is raised in the idle
59 // state, save tx_byte for transmission
60 tx_data = tx_byte;
61 // Send the initial, low pulse of 1 bit period
62 // to signal the start, followed by the data
63 data_out = 0;
64 tx_state = TX_ADDRESS;
65 tx_bits_remaining = 8;
66 step = 0;
67 end
68 end // case: TX_IDLE
69
70 TX_ADDRESS: begin
71 if(step == 0) begin
72 clk_out <= 0;
73 step <= 1;
74 end else if (tx_bits_remaining == 0) begin
75 if(step == 1) begin
76 data_out <= 0; // really should be z, not 0
77 step <= 2;
78 end else if(step == 2)begin
79 clk_out <= 1;
80 step <= 3;
81 end else begin
82 step <= 0;
83
84 tx_state <= TX_FIRST_BYTE;
85 tx_bits_remaining <= 8;
86 end
87 end else if(step == 1) begin
88 data_out <= address[tx_bits_remaining - 1];
89 step <= 2;
90 end else if(step == 2) begin
91 clk_out <= 1;
92 step <= 3;
93 end else begin // step == 3
94 tx_bits_remaining = tx_bits_remaining - 1;
95 step <= 0;
96 end
97 end // case: TX_ADDRESS
98
99 TX_FIRST_BYTE: begin
100 if(step == 0) begin
101 clk_out <= 0;
102 step <= 1;
103 end else if (tx_bits_remaining == 0) begin
104 if(step == 1) begin
105 data_out <= 0; // really should be z, not 0
106 step <= 2;
107 end else if(step == 2)begin
108 clk_out <= 1;
109 step <= 3;
110 end else begin
111 step <= 0;
112
113 tx_state <= TX_STOP;
114 end
115 end else if(step == 1) begin
116 data_out <= tx_data[tx_bits_remaining - 1];
117 step <= 2;
118 end else if(step == 2) begin
119 clk_out <= 1;
120 step <= 3;
121 end else begin // step == 3
122 tx_bits_remaining = tx_bits_remaining - 1;
123 step <= 0;
124 end
125 end // case: TX_FIRST_BYTE
126
127 TX_STOP: begin
128 if(step == 0) begin
129 clk_out <= 0;
130 step <= 1;
131 end else if(step == 1) begin
132 step <= 2;
133 end else if(step == 2) begin
134 clk_out <= 1;
135 step <= 3;
136 end else begin
137 data_out <= 1;
138 step <= 0;
139 tx_state <= TX_IDLE;
140 end
141 end
142 endcase
143end
144endmodule // i2c_write
This page took 0.01875 seconds and 4 git commands to generate.