rust_hdl_widgets/
open_drain.rs

1use 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}