rust_hdl_widgets/i2c/
i2c_target.rs1use crate::prelude::*;
2use rust_hdl_core::prelude::*;
3
4#[derive(Copy, Clone, PartialEq, Debug, LogicState)]
5enum State {
6 Idle,
7 Start,
8 Reading,
9 Waiting,
10 Flag,
11 Ack,
12 AckHold,
13 WaitEndTransaction,
14 CheckStop,
15 Writing,
16 WaitSCLHigh,
17 WaitSCLLow,
18 WaitSCLHighAck,
19 CollectAck,
20}
21
22#[derive(LogicBlock, Default)]
23pub struct I2CTarget {
24 pub i2c: I2CBusDriver,
25 pub clock: Signal<In, Clock>,
26 pub from_bus: Signal<Out, Bits<8>>,
27 pub bus_write: Signal<Out, Bit>,
28 pub active: Signal<In, Bit>,
29 pub stop: Signal<Out, Bit>,
30 pub to_bus: Signal<In, Bits<8>>,
31 pub write_enable: Signal<In, Bit>,
32 pub ack: Signal<Out, Bit>,
33 pub nack: Signal<Out, Bit>,
34 pub write_ok: Signal<Out, Bit>,
35 state: DFF<State>,
36 scl_is_high: Signal<Local, Bit>,
37 sda_is_high: Signal<Local, Bit>,
38 sda_flop: DFF<Bit>,
39 clear_sda: Signal<Local, Bit>,
40 set_sda: Signal<Local, Bit>,
41 read_bit: DFF<Bit>,
42 count: DFF<Bits<4>>,
43 accum: DFF<Bits<8>>,
44}
45
46impl Logic for I2CTarget {
47 #[hdl_gen]
48 fn update(&mut self) {
49 dff_setup!(self, clock, state, sda_flop, read_bit, count, accum);
51 self.i2c.scl.drive_low.next = false;
53 self.i2c.sda.drive_low.next = self.sda_flop.q.val();
54 self.sda_is_high.next = self.i2c.sda.line_state.val();
55 self.scl_is_high.next = self.i2c.scl.line_state.val();
56 self.set_sda.next = false;
57 self.clear_sda.next = false;
58 self.from_bus.next = self.accum.q.val();
59 self.bus_write.next = false;
60 self.stop.next = false;
61 self.ack.next = false;
62 self.nack.next = false;
63 self.write_ok.next = false;
64 match self.state.q.val() {
66 State::Idle => {
67 self.set_sda.next = true;
68 self.count.d.next = 0.into();
69 if !self.sda_is_high.val() & self.scl_is_high.val() {
70 self.state.d.next = State::Start;
71 }
72 }
73 State::Start => {
74 if self.sda_is_high.val() {
75 self.state.d.next = State::Idle;
76 } else if !self.sda_is_high.val() & !self.scl_is_high.val() {
77 self.state.d.next = State::Reading;
78 }
79 }
80 State::Writing => {
81 if self.accum.q.val().get_bit(7) {
82 self.set_sda.next = true;
83 } else {
84 self.clear_sda.next = true;
85 }
86 self.count.d.next = self.count.q.val() + 1;
87 self.accum.d.next = self.accum.q.val() << 1;
88 self.state.d.next = State::WaitSCLHigh;
89 if self.count.q.val() == 8 {
90 self.state.d.next = State::WaitSCLHighAck;
91 }
92 }
93 State::WaitSCLHighAck => {
94 if self.scl_is_high.val() {
95 self.set_sda.next = true;
96 self.state.d.next = State::CollectAck;
97 }
98 }
99 State::CollectAck => {
100 if !self.scl_is_high.val() {
101 if self.sda_is_high.val() {
102 self.nack.next = true;
103 } else {
104 self.ack.next = true;
105 }
106 self.state.d.next = State::Reading;
107 }
108 }
109 State::WaitSCLHigh => {
110 if self.scl_is_high.val() {
111 self.state.d.next = State::WaitSCLLow;
112 }
113 }
114 State::WaitSCLLow => {
115 if !self.scl_is_high.val() {
116 self.state.d.next = State::Writing;
117 }
118 }
119 State::Reading => {
120 self.write_ok.next = true;
121 if self.write_enable.val() {
122 self.accum.d.next = self.to_bus.val();
123 self.count.d.next = 0.into();
124 self.state.d.next = State::Writing;
125 }
126 if self.scl_is_high.val() {
127 self.read_bit.d.next = self.sda_is_high.val();
128 self.state.d.next = State::Waiting;
129 }
130 }
131 State::Waiting => {
132 if !self.scl_is_high.val() {
133 self.accum.d.next =
134 (self.accum.q.val() << 1) | bit_cast::<8, 1>(self.read_bit.q.val().into());
135 self.count.d.next = self.count.q.val() + 1;
136 if self.count.q.val() == 7 {
137 self.state.d.next = State::Flag;
138 } else {
139 self.state.d.next = State::Reading;
140 }
141 }
142 if !self.read_bit.q.val() & self.sda_is_high.val() & self.scl_is_high.val() {
143 self.stop.next = true;
144 self.state.d.next = State::Idle;
145 }
146 if self.read_bit.q.val() & !self.sda_is_high.val() & self.scl_is_high.val() {
147 self.stop.next = true;
148 self.state.d.next = State::Idle;
149 }
150 }
151 State::Flag => {
152 self.bus_write.next = true;
153 self.accum.d.next = 0.into();
154 self.count.d.next = 0.into();
155 self.state.d.next = State::Ack;
156 }
157 State::Ack => {
158 self.clear_sda.next = self.active.val();
159 if !self.active.val() {
160 self.state.d.next = State::WaitEndTransaction;
161 }
162 if self.scl_is_high.val() {
163 self.state.d.next = State::AckHold;
164 }
165 }
166 State::AckHold => {
167 if !self.scl_is_high.val() {
168 self.set_sda.next = true;
169 self.state.d.next = State::Reading;
170 }
171 }
172 State::WaitEndTransaction => {
173 if self.scl_is_high.val() & !self.sda_is_high.val() {
177 self.state.d.next = State::CheckStop;
178 }
179 }
180 State::CheckStop => {
181 if self.scl_is_high.val() & self.sda_is_high.val() {
182 self.state.d.next = State::Idle;
183 self.stop.next = true;
184 }
185 }
186 _ => {
187 self.state.d.next = State::Idle;
188 }
189 }
190 if self.set_sda.val() {
191 self.sda_flop.d.next = false;
192 }
193 if self.clear_sda.val() {
194 self.sda_flop.d.next = true;
195 }
196 }
197}