1use rust_hdl_core::prelude::*;
2use rust_hdl_widgets::prelude::*;
3use std::time::Duration;
4
5#[derive(Copy, Clone, PartialEq, Debug, LogicState)]
6enum AD7193State {
7 Init,
8 Ready,
9 GettingCmd,
10 ReadCmd,
11 WaitSlaveIdle,
12 WriteCmd,
13 DoWrite,
14 SingleConversion,
15 SingleConversionCommit,
16}
17
18#[derive(LogicBlock)]
19pub struct AD7193Simulator {
20 pub wires: SPIWiresSlave,
22 pub clock: Signal<In, Clock>,
23 reg_width_rom: ROM<Bits<5>, 3>,
25 reg_ram: RAM<Bits<24>, 3>,
27 oneshot: Shot<32>,
29 cmd: Signal<Local, Bits<8>>,
31 reg_index: Signal<Local, Bits<3>>,
32 rw_flag: Signal<Local, Bit>,
33 spi_slave: SPISlave<64>,
35 state: DFF<AD7193State>,
37 reg_write_index: DFF<Bits<3>>,
38 conversion_counter: DFF<Bits<24>>,
40}
41
42#[derive(Clone, Copy)]
43pub struct AD7193Config {
44 pub spi: SPIConfig,
45 pub sample_time: Duration,
46}
47
48impl AD7193Config {
49 pub fn hw() -> Self {
50 Self {
51 spi: SPIConfig {
52 clock_speed: 48_000_000,
53 cs_off: true,
54 mosi_off: true,
55 speed_hz: 400_000,
56 cpha: true,
57 cpol: true,
58 },
59 sample_time: Duration::from_micros(10100),
60 }
61 }
62 pub fn sw() -> Self {
63 Self {
64 spi: SPIConfig {
65 clock_speed: 1_000_000,
66 cs_off: true,
67 mosi_off: true,
68 speed_hz: 10_000,
69 cpha: true,
70 cpol: true,
71 },
72 sample_time: Duration::from_micros(100),
73 }
74 }
75}
76
77pub const AD7193_REG_WIDTHS: [u32; 8] = [8, 24, 24, 24, 8, 8, 24, 24];
78const AD7193_REG_INITS: [u64; 8] = [0x40, 0x80060, 0x117, 0x0, 0xa2, 0x0, 0x800000, 0x5544d0];
79
80impl AD7193Simulator {
81 pub fn new(config: AD7193Config) -> Self {
82 assert!(config.spi.clock_speed > 10 * config.spi.speed_hz);
83 let reg_width_rom = AD7193_REG_WIDTHS.iter().map(|x| x.to_bits()).into();
84 let reg_ram = AD7193_REG_INITS.iter().map(|x| x.to_bits()).into();
85 Self {
86 wires: Default::default(),
87 clock: Default::default(),
88 reg_width_rom,
89 reg_ram,
90 oneshot: Shot::new(config.spi.clock_speed, config.sample_time),
91 cmd: Default::default(),
92 reg_index: Default::default(),
93 rw_flag: Default::default(),
94 spi_slave: SPISlave::new(config.spi),
95 state: Default::default(),
96 reg_write_index: Default::default(),
97 conversion_counter: Default::default(),
98 }
99 }
100}
101
102impl Logic for AD7193Simulator {
103 #[hdl_gen]
104 fn update(&mut self) {
105 SPIWiresSlave::link(&mut self.wires, &mut self.spi_slave.wires);
107 self.reg_ram.read_clock.next = self.clock.val();
109 self.reg_ram.write_clock.next = self.clock.val();
110 clock!(self, clock, oneshot, spi_slave);
111 dff_setup!(self, clock, state, reg_write_index, conversion_counter);
112 self.spi_slave.start_send.next = false;
114 self.cmd.next = self.spi_slave.data_inbound.val().get_bits::<8>(0);
115 self.reg_index.next = self.cmd.val().get_bits::<3>(3);
116 self.rw_flag.next = self.cmd.val().get_bit(6);
117 self.reg_width_rom.address.next = self.reg_index.val();
118 self.reg_ram.read_address.next = self.reg_index.val();
119 self.reg_ram.write_address.next = self.reg_index.val();
120 self.spi_slave.continued_transaction.next = false;
121 self.spi_slave.bits.next = 0.into();
122 self.spi_slave.data_outbound.next = 0.into();
123 self.reg_ram.write_enable.next = false;
124 self.reg_ram.write_data.next = 0.into();
125 self.spi_slave.disabled.next = false;
126 self.oneshot.trigger.next = false;
127 match self.state.q.val() {
128 AD7193State::Init => {
129 if self.spi_slave.transfer_done.val() {
130 self.state.d.next = AD7193State::Ready;
131 }
132 }
133 AD7193State::Ready => {
134 self.spi_slave.continued_transaction.next = true;
135 self.spi_slave.bits.next = 8.into();
136 self.spi_slave.data_outbound.next = 0xFF.into();
137 self.spi_slave.start_send.next = true;
138 self.state.d.next = AD7193State::GettingCmd;
139 }
140 AD7193State::GettingCmd => {
141 if self.spi_slave.transfer_done.val() {
142 if self.rw_flag.val() {
143 self.state.d.next = AD7193State::ReadCmd;
144 } else {
145 self.reg_write_index.d.next = self.reg_index.val();
146 self.state.d.next = AD7193State::WriteCmd;
147 }
148 }
149 }
150 AD7193State::ReadCmd => {
151 self.spi_slave.continued_transaction.next = true;
152 self.spi_slave.bits.next = bit_cast::<16, 5>(self.reg_width_rom.data.val()) + 8;
153 self.spi_slave.data_outbound.next =
154 (bit_cast::<64, 24>(self.reg_ram.read_data.val()) << 8)
155 | Bits::<64>::from(0xBA);
156 self.spi_slave.start_send.next = true;
157 self.state.d.next = AD7193State::WaitSlaveIdle;
158 }
159 AD7193State::WriteCmd => {
160 self.spi_slave.continued_transaction.next = true;
161 self.spi_slave.bits.next = bit_cast::<16, 5>(self.reg_width_rom.data.val());
162 self.spi_slave.data_outbound.next = 0xFFFF_FFFF_u64.to_bits();
163 self.spi_slave.start_send.next = true;
164 self.state.d.next = AD7193State::DoWrite;
165 }
166 AD7193State::DoWrite => {
167 if self.spi_slave.transfer_done.val() {
168 self.reg_ram.write_data.next =
169 bit_cast::<24, 64>(self.spi_slave.data_inbound.val());
170 self.reg_ram.write_enable.next = true;
171 self.reg_ram.write_address.next = self.reg_write_index.q.val();
172 self.state.d.next = AD7193State::WaitSlaveIdle;
173 if (self.reg_write_index.q.val() == 1)
174 & self.spi_slave.data_inbound.val().get_bit(21)
175 {
176 self.state.d.next = AD7193State::SingleConversion;
177 self.oneshot.trigger.next = true;
178 }
179 }
180 }
181 AD7193State::WaitSlaveIdle => {
182 if !self.spi_slave.busy.val() {
183 self.state.d.next = AD7193State::Ready;
184 }
185 }
186 AD7193State::SingleConversion => {
187 self.spi_slave.disabled.next = true;
188 if self.oneshot.fired.val() {
189 self.state.d.next = AD7193State::SingleConversionCommit;
190 }
191 }
192 AD7193State::SingleConversionCommit => {
193 self.reg_ram.write_address.next = 3.into();
194 self.reg_ram.write_data.next = self.conversion_counter.q.val();
195 self.reg_ram.write_enable.next = true;
196 self.conversion_counter.d.next = self.conversion_counter.q.val() + 0x100;
197 self.spi_slave.data_outbound.next = 0.into();
198 self.state.d.next = AD7193State::Ready;
199 }
200 _ => {
201 self.state.d.next = AD7193State::Init;
202 }
203 }
204 if self.spi_slave.transfer_done.val() & self.spi_slave.data_inbound.val().all() {
205 println!("Reset encountered");
206 self.state.d.next = AD7193State::Ready;
207 }
208 }
209}
210
211#[test]
212fn test_ad7193_synthesizes() {
213 let mut uut = AD7193Simulator::new(AD7193Config::sw());
214 uut.connect_all();
215 yosys_validate("ad7193", &generate_verilog(&uut)).unwrap();
216}
217
218#[derive(LogicBlock)]
219struct Test7193 {
220 clock: Signal<In, Clock>,
221 master: SPIMaster<64>,
222 adc: AD7193Simulator,
223}
224
225impl Logic for Test7193 {
226 #[hdl_gen]
227 fn update(&mut self) {
228 clock!(self, clock, master, adc);
229 SPIWiresMaster::join(&mut self.master.wires, &mut self.adc.wires);
230 }
231}
232
233impl Default for Test7193 {
234 fn default() -> Self {
235 Self {
236 clock: Default::default(),
237 master: SPIMaster::new(AD7193Config::sw().spi),
238 adc: AD7193Simulator::new(AD7193Config::sw()),
239 }
240 }
241}
242
243#[cfg(test)]
244fn reg_read(
245 reg_index: u32,
246 x: Box<Test7193>,
247 sim: &mut Sim<Test7193>,
248) -> Result<(Bits<64>, Box<Test7193>), SimError> {
249 let cmd = (((1 << 6) | (reg_index << 3)) << 24).into();
250 let result = do_spi_txn(32, cmd, false, x, sim)?;
251 let width = AD7193_REG_WIDTHS[reg_index as usize];
252 let reg_val = if width == 8 {
253 (result.0 >> 16) & 0xFF
254 } else {
255 result.0 & 0xFFFFFF
256 };
257 Ok((reg_val, result.1))
258}
259
260#[cfg(test)]
261fn reg_write(
262 reg_index: u32,
263 reg_value: u64,
264 x: Box<Test7193>,
265 sim: &mut Sim<Test7193>,
266) -> Result<Box<Test7193>, SimError> {
267 let mut cmd = (((0 << 6) | (reg_index << 3)) << 24).into();
268 if AD7193_REG_WIDTHS[reg_index as usize] == 8 {
269 cmd = cmd | reg_value << 16;
270 } else {
271 cmd = cmd | reg_value;
272 }
273 let ret = do_spi_txn(32, cmd, false, x, sim)?;
274 Ok(ret.1)
275}
276
277#[cfg(test)]
278fn do_spi_txn(
279 bits: u16,
280 value: u64,
281 continued: bool,
282 mut x: Box<Test7193>,
283 sim: &mut Sim<Test7193>,
284) -> Result<(Bits<64>, Box<Test7193>), SimError> {
285 wait_clock_true!(sim, clock, x);
286 x.master.data_outbound.next = value.to_bits();
287 x.master.bits_outbound.next = bits.to_bits();
288 x.master.continued_transaction.next = continued;
289 x.master.start_send.next = true;
290 wait_clock_cycle!(sim, clock, x);
291 x.master.start_send.next = false;
292 x = sim
293 .watch(|x| x.master.transfer_done.val().into(), x)
294 .unwrap();
295 let ret = x.master.data_inbound.val();
296 for _ in 0..50 {
297 wait_clock_cycle!(sim, clock, x);
298 }
299 Ok((ret, x))
300}
301
302#[cfg(test)]
303fn mk_test7193() -> Test7193 {
304 let mut uut = Test7193::default();
305 uut.clock.connect();
306 uut.master.continued_transaction.connect();
307 uut.master.start_send.connect();
308 uut.master.data_outbound.connect();
309 uut.master.bits_outbound.connect();
310 uut.connect_all();
311 uut
312}
313
314#[test]
315fn test_yosys_validate_test_fixture() {
316 let uut = mk_test7193();
317 yosys_validate("7193_1", &generate_verilog(&uut)).unwrap();
318}
319
320#[test]
321fn test_reg_reads() {
322 let uut = mk_test7193();
323 let mut sim = Simulation::new();
324 sim.add_clock(5, |x: &mut Box<Test7193>| x.clock.next = !x.clock.val());
325 sim.add_testbench(move |mut sim: Sim<Test7193>| {
326 let mut x = sim.init()?;
327 wait_clock_cycles!(sim, clock, x, 20);
329 let result = do_spi_txn(32, 0xFFFFFFFF, false, x, &mut sim)?;
331 x = result.1;
332 for ndx in 0..8 {
333 println!("Reading register index {}", ndx);
334 let result = reg_read(ndx, x, &mut sim)?;
335 x = result.1;
336 println!("Value {} -> {:x}", ndx, result.0);
337 sim_assert!(
338 sim,
339 result.0 == Bits::<64>::from(AD7193_REG_INITS[ndx as usize]),
340 x
341 );
342 wait_clock_true!(sim, clock, x);
343 }
344 sim.done(x)
345 });
346 sim.run(Box::new(uut), 1_000_000).unwrap();
347}
348
349#[test]
350fn test_reg_writes() {
351 let uut = mk_test7193();
352 let mut sim = Simulation::new();
353 sim.add_clock(5, |x: &mut Box<Test7193>| x.clock.next = !x.clock.val());
354 sim.add_testbench(move |mut sim: Sim<Test7193>| {
355 let mut x = sim.init()?;
356
357 wait_clock_cycles!(sim, clock, x, 20);
359 let result = do_spi_txn(32, 0xFFFFFFFF, false, x, &mut sim)?;
361 x = result.1;
362 for ndx in 0..8 {
363 let result = reg_read(ndx, x, &mut sim)?;
364 x = result.1;
365 sim_assert!(
366 sim,
367 result.0 == Bits::<64>::from(AD7193_REG_INITS[ndx as usize]),
368 x
369 );
370 x = reg_write(ndx, AD7193_REG_INITS[ndx as usize] + 1, x, &mut sim)?;
371 let result = reg_read(ndx, x, &mut sim)?;
372 x = result.1;
373 sim_assert!(
374 sim,
375 result.0 == Bits::<64>::from(AD7193_REG_INITS[ndx as usize] + 1),
376 x
377 );
378 }
379 sim.done(x)
380 });
381 sim.run(Box::new(uut), 1_000_000).unwrap();
382}
383
384#[test]
385fn test_single_conversion() {
386 let uut = mk_test7193();
387 let mut sim = Simulation::new();
388 sim.add_clock(5, |x: &mut Box<Test7193>| x.clock.next = !x.clock.val());
389 sim.add_testbench(move |mut sim: Sim<Test7193>| {
390 let mut x = sim.init()?;
391
392 wait_clock_cycles!(sim, clock, x, 20);
394 let result = do_spi_txn(32, 0xFFFFFFFF, false, x, &mut sim)?;
396 x = result.1;
397 for n in 0..3 {
398 wait_clock_cycle!(sim, clock, x, 100);
399 let result = do_spi_txn(32, 0x8382006, true, x, &mut sim)?;
400 x = result.1;
401 wait_clock_cycle!(sim, clock, x, 100);
402 sim_assert!(sim, x.master.wires.miso.val(), x);
403 x = sim.watch(|x| !x.master.wires.miso.val(), x)?;
404 wait_clock_cycle!(sim, clock, x, 100);
405 let result = reg_read(3, x, &mut sim)?;
406 println!("Conversion {} -> {:x}", n, result.0);
407 x = result.1;
408 sim_assert!(sim, result.0 == Bits::<64>::from(n * 0x100), x);
409 println!("Conversion {} completed", n);
410 }
411 sim.done(x)
412 });
413 sim.run(Box::new(uut), 10_000_000).unwrap();
414}