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 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 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 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 Signal::<InOut, T>::link(&mut self.bus.sig_inout, &mut self.bus_buffer.bus);
133 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 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 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}