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; | |
18 | parameter TX_ADDRESS = 1; | |
19 | parameter TX_FIRST_BYTE = 2; | |
20 | parameter TX_MORE_BYTES = 3; | |
21 | parameter TX_STOP = 4; | |
22 | ||
23 | reg [10:0] tx_clk_divider = CLOCK_DIVIDE; | |
24 | ||
25 | reg data_out = 1'b1; | |
26 | reg clk_out = 1'b1; | |
27 | ||
28 | reg [3:0] tx_state = TX_IDLE; | |
29 | reg [5:0] tx_countdown; | |
30 | reg [3:0] tx_bits_remaining; | |
31 | reg [7:0] tx_data; | |
32 | ||
33 | reg [3:0] step = 0; | |
34 | ||
35 | wire [7:0] address = {7'h70, 1'b0}; // address 0x70, write | |
36 | wire [15:0] address_data = {address, tx_data}; | |
37 | ||
38 | assign sda = data_out; | |
39 | assign scl = clk_out; | |
40 | assign is_transmitting = tx_state != TX_IDLE; | |
41 | ||
42 | always @(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 | |
143 | end | |
144 | endmodule // i2c_write |