rust_hdl_lib_hls/
controller.rs1use crate::bus::{FIFOReadController, FIFOWriteController, SoCBusController};
2use rust_hdl_lib_core::prelude::*;
3use rust_hdl_lib_widgets::prelude::*;
4
5#[derive(LogicState, Debug, Copy, Clone, PartialEq)]
14enum BaseControllerState {
15 Idle,
16 Ping,
17 ReadLoadCount,
18 Read,
19 Write,
20 WriteLoadCount,
21 PollWait,
22 Poll,
23 StreamWait,
24 Stream,
25}
26
27#[derive(LogicBlock, Default)]
32pub struct BaseController<const A: usize> {
33 pub from_cpu: FIFOReadController<Bits<16>>, pub to_cpu: FIFOWriteController<Bits<16>>, pub clock: Signal<In, Clock>, state: DFF<BaseControllerState>,
37 pub bus: SoCBusController<16, { A }>,
38 counter: DFF<Bits<16>>,
39 opcode: Signal<Local, Bits<8>>,
40}
41
42impl<const A: usize> Logic for BaseController<A> {
43 #[hdl_gen]
44 fn update(&mut self) {
45 dff_setup!(self, clock, state, counter);
46 self.opcode.next = self.from_cpu.data.val().get_bits::<8>(8);
48 self.from_cpu.read.next = false;
50 self.to_cpu.data.next = 0.into();
51 self.to_cpu.write.next = false;
52 self.bus.clock.next = self.clock.val();
53 self.bus.from_controller.next = 0.into();
54 self.bus.strobe.next = false;
55 self.bus.address.next = 0.into();
56 self.bus.address_strobe.next = false;
57 match self.state.q.val() {
58 BaseControllerState::Idle => {
59 if !self.from_cpu.empty.val() {
60 if self.opcode.val() == 0 {
61 self.from_cpu.read.next = true;
63 } else if self.opcode.val() == 1 {
64 self.state.d.next = BaseControllerState::Ping;
65 } else if self.opcode.val() == 2 {
66 self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
68 self.bus.address_strobe.next = true;
69 self.from_cpu.read.next = true;
70 self.state.d.next = BaseControllerState::ReadLoadCount;
71 } else if self.opcode.val() == 3 {
72 self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
74 self.bus.address_strobe.next = true;
75 self.from_cpu.read.next = true;
76 self.state.d.next = BaseControllerState::WriteLoadCount;
77 } else if self.opcode.val() == 4 {
78 self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
79 self.bus.address_strobe.next = true;
80 self.from_cpu.read.next = true;
81 self.state.d.next = BaseControllerState::PollWait;
82 } else if self.opcode.val() == 5 {
83 self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
84 self.bus.address_strobe.next = true;
85 self.from_cpu.read.next = true;
86 self.state.d.next = BaseControllerState::StreamWait;
87 }
88 }
89 }
90 BaseControllerState::Ping => {
91 self.to_cpu.data.next = self.from_cpu.data.val();
92 self.to_cpu.write.next = true;
93 self.from_cpu.read.next = true;
94 self.state.d.next = BaseControllerState::Idle;
95 }
96 BaseControllerState::ReadLoadCount => {
97 if !self.from_cpu.empty.val() {
98 self.counter.d.next = self.from_cpu.data.val();
99 self.from_cpu.read.next = true;
100 self.state.d.next = BaseControllerState::Read;
101 }
102 }
103 BaseControllerState::Read => {
104 if self.bus.ready.val() & !self.to_cpu.full.val() {
105 self.to_cpu.data.next = self.bus.to_controller.val();
106 self.bus.strobe.next = true;
107 self.to_cpu.write.next = true;
108 self.counter.d.next = self.counter.q.val() - 1;
109 if self.counter.q.val() == 1 {
110 self.state.d.next = BaseControllerState::Idle;
111 }
112 }
113 }
114 BaseControllerState::WriteLoadCount => {
115 if !self.from_cpu.empty.val() {
116 self.counter.d.next = self.from_cpu.data.val();
117 self.from_cpu.read.next = true;
118 self.state.d.next = BaseControllerState::Write;
119 }
120 }
121 BaseControllerState::Write => {
122 if self.bus.ready.val() & !self.from_cpu.empty.val() {
123 self.bus.from_controller.next = self.from_cpu.data.val();
124 self.bus.strobe.next = true;
125 self.from_cpu.read.next = true;
126 self.counter.d.next = self.counter.q.val() - 1;
127 if self.counter.q.val() == 1 {
128 self.state.d.next = BaseControllerState::Idle;
129 }
130 }
131 }
132 BaseControllerState::PollWait => {
133 self.state.d.next = BaseControllerState::Poll;
134 }
135 BaseControllerState::Poll => {
136 if !self.to_cpu.full.val() {
137 self.to_cpu.data.next =
138 bits::<16>(0xFF00) | bit_cast::<16, 1>(self.bus.ready.val().into());
139 self.to_cpu.write.next = true;
140 self.state.d.next = BaseControllerState::Idle;
141 }
142 }
143 BaseControllerState::StreamWait => {
144 self.state.d.next = BaseControllerState::Stream;
145 }
146 BaseControllerState::Stream => {
147 if self.bus.ready.val() & !self.to_cpu.full.val() {
148 self.to_cpu.data.next = self.bus.to_controller.val();
149 self.bus.strobe.next = true;
150 self.to_cpu.write.next = true;
151 }
152 if !self.from_cpu.empty.val() {
153 if self.from_cpu.data.val().any() {
154 self.state.d.next = BaseControllerState::Idle;
155 }
156 self.from_cpu.read.next = true;
157 }
158 }
159 _ => {
160 self.state.d.next = BaseControllerState::Idle;
161 }
162 }
163 }
164}
165
166#[test]
167fn test_base_controller_is_synthesizable() {
168 let mut uut = BaseController::<4>::default();
169 uut.connect_all();
170 let vlog = generate_verilog(&uut);
171 yosys_validate("base_controller", &vlog).unwrap();
172}