rust_hdl_hls/
bidi.rs

1use crate::bus::{FIFOReadController, FIFOWriteController};
2use rust_hdl_core::prelude::*;
3use rust_hdl_widgets::prelude::*;
4
5#[derive(Clone, Debug, Default, LogicInterface)]
6#[join = "BidiBusD"]
7pub struct BidiBusM<T: Synth> {
8    pub sig_inout: Signal<InOut, T>,
9    pub sig_empty: Signal<In, Bit>,
10    pub sig_full: Signal<In, Bit>,
11    pub sig_not_read: Signal<Out, Bit>,
12    pub sig_not_write: Signal<Out, Bit>,
13    pub sig_master: Signal<Out, Bit>,
14}
15
16#[derive(Clone, Debug, Default, LogicInterface)]
17#[join = "BidiBusM"]
18pub struct BidiBusD<T: Synth> {
19    pub sig_inout: Signal<InOut, T>,
20    pub sig_empty: Signal<Out, Bit>,
21    pub sig_full: Signal<Out, Bit>,
22    pub sig_not_read: Signal<In, Bit>,
23    pub sig_not_write: Signal<In, Bit>,
24    pub sig_master: Signal<In, Bit>,
25}
26
27#[derive(LogicBlock, Default)]
28pub struct BidiMaster<T: Synth> {
29    pub bus: BidiBusM<T>,
30    pub clock: Signal<In, Clock>,
31    bus_buffer: TristateBuffer<T>,
32    pub data_to_bus: FIFOReadController<T>,
33    pub data_from_bus: FIFOWriteController<T>,
34    state: DFF<BidiState>,
35    can_send_to_bus: Signal<Local, Bit>,
36    can_read_from_bus: Signal<Local, Bit>,
37}
38
39impl<T: Synth> Logic for BidiMaster<T> {
40    #[hdl_gen]
41    fn update(&mut self) {
42        dff_setup!(self, clock, state);
43        self.bus_buffer.write_enable.next = false;
44        self.bus.sig_not_read.next = true;
45        self.bus.sig_not_write.next = true;
46        // Wire up the tristate buffer
47        Signal::<InOut, T>::link(&mut self.bus.sig_inout, &mut self.bus_buffer.bus);
48        self.bus_buffer.write_data.next = self.data_to_bus.data.val();
49        self.data_from_bus.data.next = self.bus_buffer.read_data.val();
50        // Now we do the FSM logic
51        self.bus.sig_master.next = true;
52        self.can_send_to_bus.next = !self.data_to_bus.empty.val() & !self.bus.sig_full.val();
53        self.can_read_from_bus.next = !self.data_from_bus.full.val() & !self.bus.sig_empty.val();
54        // Default values for the FIFO controllers
55        self.data_to_bus.read.next = false;
56        self.data_from_bus.write.next = false;
57        match self.state.q.val() {
58            BidiState::Idle => {
59                if self.can_send_to_bus.val() {
60                    self.state.d.next = BidiState::Claiming;
61                }
62                if self.can_read_from_bus.val() {
63                    self.state.d.next = BidiState::Turnaround;
64                    self.bus.sig_master.next = false;
65                }
66            }
67            BidiState::Claiming => {
68                self.bus_buffer.write_enable.next = true;
69                self.state.d.next = BidiState::Sending;
70            }
71            BidiState::Sending => {
72                self.bus_buffer.write_enable.next = true;
73                self.data_to_bus.read.next = self.can_send_to_bus.val();
74                self.bus.sig_not_write.next = !self.can_send_to_bus.val();
75                if !self.can_send_to_bus.val() {
76                    self.state.d.next = BidiState::Idle;
77                }
78            }
79            BidiState::Receiving => {
80                self.bus.sig_master.next = false;
81                self.data_from_bus.write.next = self.can_read_from_bus.val();
82                self.bus.sig_not_read.next = !self.can_read_from_bus.val();
83                if !self.can_read_from_bus.val() {
84                    self.state.d.next = BidiState::Release;
85                }
86            }
87            BidiState::Turnaround => {
88                self.bus.sig_master.next = false;
89                self.state.d.next = BidiState::Receiving;
90            }
91            BidiState::Release => {
92                self.state.d.next = BidiState::Idle;
93            }
94            _ => {
95                self.state.d.next = BidiState::Idle;
96            }
97        }
98    }
99}
100
101#[derive(LogicState, Debug, Copy, Clone, PartialEq)]
102enum BidiState {
103    Idle,
104    Claiming,
105    Sending,
106    Receiving,
107    Turnaround,
108    Release,
109}
110
111#[test]
112fn test_bidi_master2_synthesizable() {
113    let mut uut = BidiMaster::<Bits<8>>::default();
114    uut.connect_all();
115    let vlog = generate_verilog(&uut);
116    yosys_validate("bidi_master2", &vlog).unwrap();
117}
118
119#[derive(LogicBlock, Default)]
120pub struct BidiSimulatedDevice<T: Synth> {
121    pub bus: BidiBusD<T>,
122    pub clock: Signal<In, Clock>,
123    bus_buffer: TristateBuffer<T>,
124    pub data_to_bus: FIFOReadController<T>,
125    pub data_from_bus: FIFOWriteController<T>,
126}
127
128impl<T: Synth> Logic for BidiSimulatedDevice<T> {
129    #[hdl_gen]
130    fn update(&mut self) {
131        // Wire up the tristate buffer
132        Signal::<InOut, T>::link(&mut self.bus.sig_inout, &mut self.bus_buffer.bus);
133        // The bus interfaces
134        self.data_to_bus.read.next = !self.bus.sig_not_read.val();
135        self.bus.sig_empty.next = self.data_to_bus.empty.val();
136        self.bus_buffer.write_data.next = self.data_to_bus.data.val();
137        // The bus interfaces
138        self.data_from_bus.data.next = self.bus_buffer.read_data.val();
139        self.data_from_bus.write.next = !self.bus.sig_not_write.val();
140        self.bus.sig_full.next = self.data_from_bus.full.val();
141        // Connect the write enable line
142        self.bus_buffer.write_enable.next = !self.bus.sig_master.val();
143    }
144}
145
146#[test]
147fn test_bidi_device_synthesizable() {
148    let mut uut = BidiSimulatedDevice::<Bits<8>>::default();
149    uut.connect_all();
150    let vlog = generate_verilog(&uut);
151    yosys_validate("bidi_device", &vlog).unwrap();
152}