rust_hdl_widgets/
open_drain.rs1use rust_hdl_core::prelude::*;
2
3#[derive(LogicBlock, Default)]
4pub struct OpenDrainBuffer {
5 pub bus: Signal<InOut, Bit>,
6 pub control: OpenDrainReceiver,
7}
8
9impl Logic for OpenDrainBuffer {
10 fn update(&mut self) {
11 if self.control.drive_low.val() {
12 self.bus.next = false;
13 }
14 self.control.line_state.next = self.bus.val();
15 self.bus
16 .set_tristate_is_output(self.control.drive_low.val());
17 }
18
19 fn connect(&mut self) {
20 self.bus.connect();
21 self.control.line_state.connect();
22 }
23
24 fn hdl(&self) -> Verilog {
25 Verilog::Custom(format!(
26 "\
27 assign bus = control$drive_low ? 0 : 1'bz;
28 always @(*) control$line_state = bus;"
29 ))
30 }
31}
32
33#[test]
34fn test_opendrain_synthesizes() {
35 let mut uut = OpenDrainBuffer::default();
36 uut.connect_all();
37 let vlog = generate_verilog(&uut);
38 println!("{}", vlog);
39 yosys_validate("open_drain", &vlog).unwrap()
40}
41
42#[derive(LogicInterface, Default)]
43#[join = "OpenDrainReceiver"]
44pub struct OpenDrainDriver {
45 pub drive_low: Signal<Out, Bit>,
46 pub line_state: Signal<In, Bit>,
47}
48
49#[derive(LogicInterface, Default)]
50#[join = "OpenDrainDriver"]
51pub struct OpenDrainReceiver {
52 pub drive_low: Signal<In, Bit>,
53 pub line_state: Signal<Out, Bit>,
54}