]>
Commit | Line | Data |
---|---|---|
ffba35f8 MG |
1 | module 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 | ||
12 | parameter 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] | |
17 | parameter TX_IDLE = 0; | |
46a95fd3 MG |
18 | parameter TX_START = 1; |
19 | parameter TX_ADDRESS = 2; | |
20 | parameter TX_FIRST_BYTE = 3; | |
21 | parameter TX_MORE_BYTES = 4; | |
22 | parameter TX_STOP = 5; | |
ffba35f8 | 23 | |
46a95fd3 | 24 | reg [30:0] tx_clk_divider = CLOCK_DIVIDE; |
ffba35f8 MG |
25 | |
26 | reg data_out = 1'b1; | |
27 | reg clk_out = 1'b1; | |
28 | ||
29 | reg [3:0] tx_state = TX_IDLE; | |
30 | reg [5:0] tx_countdown; | |
31 | reg [3:0] tx_bits_remaining; | |
32 | reg [7:0] tx_data; | |
33 | ||
34 | reg [3:0] step = 0; | |
46a95fd3 | 35 | reg [5:0] more_bytes_idx = 0; |
ffba35f8 MG |
36 | |
37 | wire [7:0] address = {7'h70, 1'b0}; // address 0x70, write | |
38 | wire [15:0] address_data = {address, tx_data}; | |
39 | ||
40 | assign sda = data_out; | |
41 | assign scl = clk_out; | |
42 | assign is_transmitting = tx_state != TX_IDLE; | |
46a95fd3 | 43 | assign mb_addr = more_bytes_idx; |
ffba35f8 MG |
44 | |
45 | always @(posedge clk) begin | |
46a95fd3 MG |
46 | if(tx_clk_divider) begin |
47 | tx_clk_divider <= tx_clk_divider - 1; | |
48 | end else begin | |
49 | tx_clk_divider <= CLOCK_DIVIDE - 1; | |
50 | end | |
51 | ||
52 | case (tx_state) | |
ffba35f8 MG |
53 | TX_IDLE: begin |
54 | if (transmit) begin | |
ffba35f8 | 55 | tx_data = tx_byte; |
ffba35f8 MG |
56 | tx_bits_remaining = 8; |
57 | step = 0; | |
46a95fd3 MG |
58 | tx_state = TX_START; |
59 | tx_clk_divider <= CLOCK_DIVIDE - 1; | |
ffba35f8 MG |
60 | end |
61 | end // case: TX_IDLE | |
62 | ||
46a95fd3 MG |
63 | TX_START: begin |
64 | if(tx_clk_divider) begin end | |
65 | else begin | |
66 | data_out = 0; | |
67 | tx_state = TX_ADDRESS; | |
68 | end | |
69 | end | |
70 | ||
ffba35f8 | 71 | TX_ADDRESS: begin |
46a95fd3 MG |
72 | if(tx_clk_divider) begin end |
73 | else if(step == 0) begin | |
ffba35f8 MG |
74 | clk_out <= 0; |
75 | step <= 1; | |
76 | end else if (tx_bits_remaining == 0) begin | |
77 | if(step == 1) begin | |
78 | data_out <= 0; // really should be z, not 0 | |
79 | step <= 2; | |
80 | end else if(step == 2)begin | |
81 | clk_out <= 1; | |
82 | step <= 3; | |
83 | end else begin | |
84 | step <= 0; | |
85 | ||
86 | tx_state <= TX_FIRST_BYTE; | |
87 | tx_bits_remaining <= 8; | |
88 | end | |
89 | end else if(step == 1) begin | |
90 | data_out <= address[tx_bits_remaining - 1]; | |
91 | step <= 2; | |
92 | end else if(step == 2) begin | |
93 | clk_out <= 1; | |
94 | step <= 3; | |
95 | end else begin // step == 3 | |
96 | tx_bits_remaining = tx_bits_remaining - 1; | |
97 | step <= 0; | |
98 | end | |
99 | end // case: TX_ADDRESS | |
100 | ||
101 | TX_FIRST_BYTE: begin | |
46a95fd3 MG |
102 | if(tx_clk_divider) begin end |
103 | else if(step == 0) begin | |
ffba35f8 MG |
104 | clk_out <= 0; |
105 | step <= 1; | |
106 | end else if (tx_bits_remaining == 0) begin | |
107 | if(step == 1) begin | |
108 | data_out <= 0; // really should be z, not 0 | |
109 | step <= 2; | |
110 | end else if(step == 2)begin | |
111 | clk_out <= 1; | |
112 | step <= 3; | |
113 | end else begin | |
114 | step <= 0; | |
115 | ||
46a95fd3 MG |
116 | if(more_bytes) |
117 | tx_state <= TX_MORE_BYTES; | |
118 | else | |
119 | tx_state <= TX_STOP; | |
120 | tx_bits_remaining <= 8; | |
121 | more_bytes_idx <= 0; | |
ffba35f8 MG |
122 | end |
123 | end else if(step == 1) begin | |
124 | data_out <= tx_data[tx_bits_remaining - 1]; | |
125 | step <= 2; | |
126 | end else if(step == 2) begin | |
127 | clk_out <= 1; | |
128 | step <= 3; | |
129 | end else begin // step == 3 | |
130 | tx_bits_remaining = tx_bits_remaining - 1; | |
131 | step <= 0; | |
132 | end | |
133 | end // case: TX_FIRST_BYTE | |
134 | ||
46a95fd3 MG |
135 | TX_MORE_BYTES: begin |
136 | if(tx_clk_divider) begin end | |
137 | else if(step == 0) begin | |
138 | clk_out <= 0; | |
139 | step <= 1; | |
140 | end else if (tx_bits_remaining == 0) begin | |
141 | if(step == 1) begin | |
142 | data_out <= 0; // really should be z, not 0 | |
143 | step <= 2; | |
144 | end else if(step == 2)begin | |
145 | clk_out <= 1; | |
146 | step <= 3; | |
147 | end else begin | |
148 | step <= 0; | |
149 | tx_bits_remaining <= 8; | |
150 | ||
151 | if(more_bytes_idx == more_bytes) | |
152 | tx_state <= TX_STOP; | |
153 | more_bytes_idx <= more_bytes_idx + 1; | |
154 | end | |
155 | end else if(step == 1) begin | |
156 | data_out <= mb_in[tx_bits_remaining - 1]; | |
157 | step <= 2; | |
158 | end else if(step == 2) begin | |
159 | clk_out <= 1; | |
160 | step <= 3; | |
161 | end else begin // step == 3 | |
162 | tx_bits_remaining = tx_bits_remaining - 1; | |
163 | step <= 0; | |
164 | end | |
165 | end // case: TX_MORE_BYTES | |
166 | ||
ffba35f8 | 167 | TX_STOP: begin |
46a95fd3 MG |
168 | if(tx_clk_divider) begin end |
169 | else if(step == 0) begin | |
ffba35f8 MG |
170 | clk_out <= 0; |
171 | step <= 1; | |
172 | end else if(step == 1) begin | |
173 | step <= 2; | |
174 | end else if(step == 2) begin | |
175 | clk_out <= 1; | |
176 | step <= 3; | |
177 | end else begin | |
178 | data_out <= 1; | |
179 | step <= 0; | |
180 | tx_state <= TX_IDLE; | |
181 | end | |
182 | end | |
183 | endcase | |
184 | end | |
185 | endmodule // i2c_write |