1use crate::bridge::Bridge;
2use crate::bus::{
3 FIFOReadController, FIFOReadResponder, FIFOWriteController, FIFOWriteResponder,
4 SoCBusController, SoCPortController,
5};
6use crate::controller::BaseController;
7use crate::fifo::AsyncFIFO;
8use crate::miso_port::MISOPort;
9use crate::mosi_port::MOSIPort;
10use rand::Rng;
11use rust_hdl_core::prelude::*;
12use rust_hdl_widgets::prelude::*;
13use std::collections::BTreeMap;
14use std::f64::consts::PI;
15
16pub fn snore<const P: usize>(x: u32) -> Bits<P> {
17 let amp = (f64::exp(f64::sin(((x as f64) - 128.0 / 2.) * PI / 128.0)) - 0.36787944) * 108.0;
18 let amp = (amp.max(0.0).min(255.0).floor() / 255.0 * (1 << P) as f64) as u8;
19 amp.to_bits()
20}
21
22#[derive(LogicBlock)]
23pub struct FaderWithSyncROM {
24 pub clock: Signal<In, Clock>,
25 pub active: Signal<Out, Bit>,
26 pub enable: Signal<In, Bit>,
27 strobe: Strobe<32>,
28 pwm: PulseWidthModulator<6>,
29 rom: SyncROM<Bits<6>, 8>,
30 counter: DFF<Bits<8>>,
31}
32
33impl FaderWithSyncROM {
34 pub fn new(clock_frequency: u64, phase: u32) -> Self {
35 let rom = (0..256)
36 .map(|x| (x.to_bits(), snore(x + phase)))
37 .collect::<BTreeMap<_, _>>();
38 Self {
39 clock: Signal::default(),
40 active: Signal::new_with_default(false),
41 enable: Signal::default(),
42 strobe: Strobe::new(clock_frequency, 120.0),
43 pwm: PulseWidthModulator::default(),
44 rom: SyncROM::new(rom),
45 counter: Default::default(),
46 }
47 }
48}
49
50impl Logic for FaderWithSyncROM {
51 #[hdl_gen]
52 fn update(&mut self) {
53 clock!(self, clock, strobe, pwm, counter);
54 self.rom.clock.next = self.clock.val();
55 self.rom.address.next = self.counter.q.val();
56 self.counter.d.next = self.counter.q.val() + self.strobe.strobe.val();
57 self.strobe.enable.next = self.enable.val();
58 self.pwm.enable.next = self.enable.val();
59 self.active.next = self.pwm.active.val();
60 self.pwm.threshold.next = self.rom.data.val();
61 }
62}
63
64#[derive(LogicState, Debug, Copy, Clone, PartialEq)]
65enum FIFOFeederState {
66 Idle,
67 Running,
68 Sleeping,
69 Done,
70}
71
72#[derive(LogicBlock)]
73pub struct LazyFIFOFeeder<T: Synth, const N: usize> {
74 pub clock: Signal<In, Clock>,
75 pub bus: FIFOWriteController<T>,
76 pub done: Signal<Out, Bit>,
77 pub start: Signal<In, Bit>,
78 state: DFF<FIFOFeederState>,
79 sleep_counter: DFF<Bits<32>>,
80 index: DFF<Bits<N>>,
81 data_rom: ROM<T, N>,
82 sleep_rom: ROM<Bits<32>, N>,
83 data_len: Constant<Bits<N>>,
84}
85
86impl<T: Synth, const N: usize> LazyFIFOFeeder<T, N> {
87 pub fn new(data: &[T], sleeps: &[Bits<32>]) -> LazyFIFOFeeder<T, N> {
88 assert!(clog2(data.len()) <= N);
89 assert_eq!(data.len(), sleeps.len());
90 Self {
91 clock: Default::default(),
92 bus: Default::default(),
93 done: Default::default(),
94 start: Default::default(),
95 state: Default::default(),
96 sleep_counter: Default::default(),
97 index: Default::default(),
98 data_rom: data.to_vec().into_iter().into(),
99 sleep_rom: sleeps.to_vec().into_iter().into(),
100 data_len: Constant::new(data.len().to_bits()),
101 }
102 }
103}
104
105impl<T: Synth, const N: usize> Logic for LazyFIFOFeeder<T, N> {
106 #[hdl_gen]
107 fn update(&mut self) {
108 dff_setup!(self, clock, state, sleep_counter, index);
109 self.bus.data.next = self.data_rom.data.val();
111 self.bus.write.next = false;
112 self.sleep_rom.address.next = self.index.q.val();
114 self.data_rom.address.next = self.index.q.val();
115 self.done.next = false;
116 match self.state.q.val() {
117 FIFOFeederState::Idle => {
118 if self.start.val() {
119 self.state.d.next = FIFOFeederState::Running;
120 }
121 }
122 FIFOFeederState::Running => {
123 if !self.bus.full.val() {
124 self.bus.write.next = true;
125 if self.index.q.val() == (self.data_len.val() - 1) {
126 self.state.d.next = FIFOFeederState::Done;
127 } else if self.sleep_rom.data.val().any() {
128 self.state.d.next = FIFOFeederState::Sleeping;
129 self.sleep_counter.d.next = self.sleep_rom.data.val();
130 } else {
131 self.index.d.next = self.index.q.val() + 1;
132 }
133 }
134 }
135 FIFOFeederState::Sleeping => {
136 if self.sleep_counter.q.val() == 0 {
137 self.state.d.next = FIFOFeederState::Running;
138 self.index.d.next = self.index.q.val() + 1;
139 } else {
140 self.sleep_counter.d.next = self.sleep_counter.q.val() - 1;
141 }
142 }
143 FIFOFeederState::Done => {
144 self.done.next = true;
145 }
146 _ => {
147 self.state.d.next = FIFOFeederState::Idle;
148 }
149 }
150 }
151}
152
153#[derive(LogicBlock)]
154pub struct LazyFIFOReader<T: Synth, const N: usize> {
155 pub clock: Signal<In, Clock>,
156 pub bus: FIFOReadController<T>,
157 pub done: Signal<Out, Bit>,
158 pub start: Signal<In, Bit>,
159 pub error: Signal<Out, Bit>,
160 mismatch: DFF<Bit>,
161 state: DFF<FIFOFeederState>,
162 sleep_counter: DFF<Bits<32>>,
163 index: DFF<Bits<N>>,
164 data_rom: ROM<T, N>,
165 sleep_rom: ROM<Bits<32>, N>,
166 data_len: Constant<Bits<N>>,
167}
168
169impl<T: Synth, const N: usize> LazyFIFOReader<T, N> {
170 pub fn new(data: &[T], sleeps: &[Bits<32>]) -> LazyFIFOReader<T, N> {
171 assert!(clog2(data.len()) <= N);
172 assert_eq!(data.len(), sleeps.len());
173 Self {
174 clock: Default::default(),
175 bus: Default::default(),
176 done: Default::default(),
177 start: Default::default(),
178 error: Default::default(),
179 mismatch: Default::default(),
180 state: Default::default(),
181 sleep_counter: Default::default(),
182 index: Default::default(),
183 data_rom: data.to_vec().into_iter().into(),
184 sleep_rom: sleeps.to_vec().into_iter().into(),
185 data_len: Constant::new(data.len().to_bits()),
186 }
187 }
188}
189
190impl<T: Synth, const N: usize> Logic for LazyFIFOReader<T, N> {
191 #[hdl_gen]
192 fn update(&mut self) {
193 dff_setup!(self, clock, mismatch, state, sleep_counter, index);
194 self.bus.read.next = false;
195 self.done.next = false;
196 self.sleep_rom.address.next = self.index.q.val();
198 self.data_rom.address.next = self.index.q.val();
199 self.error.next = self.mismatch.q.val();
200 match self.state.q.val() {
201 FIFOFeederState::Idle => {
202 if self.start.val() {
203 self.state.d.next = FIFOFeederState::Running;
204 }
205 }
206 FIFOFeederState::Running => {
207 if !self.bus.empty.val() {
208 if self.bus.data.val() != self.data_rom.data.val() {
209 self.mismatch.d.next = true;
210 }
211 self.bus.read.next = true;
212 if self.index.q.val() == (self.data_len.val() - 1) {
213 self.state.d.next = FIFOFeederState::Done;
214 } else if self.sleep_rom.data.val().any() {
215 self.state.d.next = FIFOFeederState::Sleeping;
216 self.sleep_counter.d.next = self.sleep_rom.data.val();
217 } else {
218 self.index.d.next = self.index.q.val() + 1;
219 }
220 }
221 }
222 FIFOFeederState::Sleeping => {
223 if self.sleep_counter.q.val() == 0 {
224 self.state.d.next = FIFOFeederState::Running;
225 self.index.d.next = self.index.q.val() + 1;
226 } else {
227 self.sleep_counter.d.next = self.sleep_counter.q.val() - 1;
228 }
229 }
230 FIFOFeederState::Done => {
231 self.done.next = true;
232 }
233 _ => {
234 self.state.d.next = FIFOFeederState::Idle;
235 }
236 }
237 }
238}
239
240pub fn bursty_rand() -> Bits<32> {
241 if rand::thread_rng().gen::<f64>() < 0.9 {
242 Bits::from(0)
243 } else {
244 ((rand::thread_rng().gen::<f64>() * 40.0) as u32).to_bits()
245 }
246}
247
248pub fn bursty_vec(len: usize) -> Vec<Bits<32>> {
249 (0..len).map(|_| bursty_rand()).collect()
250}
251
252#[derive(LogicBlock)]
253pub struct SoCTestChip {
254 pub clock: Signal<In, Clock>,
255 pub sys_clock: Signal<In, Clock>,
256 pub from_cpu: FIFOWriteResponder<Bits<16>>,
257 pub to_cpu: FIFOReadResponder<Bits<16>>,
258 from_cpu_fifo: AsyncFIFO<Bits<16>, 8, 9, 1>,
259 to_cpu_fifo: AsyncFIFO<Bits<16>, 8, 9, 1>,
260 soc_host: BaseController<8>,
261 bridge: Bridge<16, 8, 2>,
262 mosi_port: MOSIPort<16>, miso_port: MISOPort<16>,
264 data_fifo: SynchronousFIFO<Bits<16>, 8, 9, 1>,
265}
266
267impl Default for SoCTestChip {
268 fn default() -> Self {
269 Self {
270 clock: Default::default(),
271 sys_clock: Default::default(),
272 from_cpu: Default::default(),
273 to_cpu: Default::default(),
274 from_cpu_fifo: Default::default(),
275 to_cpu_fifo: Default::default(),
276 soc_host: Default::default(),
277 bridge: Bridge::new(["mosi", "miso"]),
278 mosi_port: Default::default(),
279 miso_port: Default::default(),
280 data_fifo: Default::default(),
281 }
282 }
283}
284
285impl Logic for SoCTestChip {
286 #[hdl_gen]
287 fn update(&mut self) {
288 self.from_cpu_fifo.write_clock.next = self.clock.val();
289 self.to_cpu_fifo.read_clock.next = self.clock.val();
290 self.from_cpu_fifo.read_clock.next = self.sys_clock.val();
291 self.to_cpu_fifo.write_clock.next = self.sys_clock.val();
292 self.soc_host.clock.next = self.sys_clock.val();
293 SoCBusController::<16, 8>::join(&mut self.soc_host.bus, &mut self.bridge.upstream);
295 SoCPortController::<16>::join(&mut self.bridge.nodes[0], &mut self.mosi_port.bus);
296 SoCPortController::<16>::join(&mut self.bridge.nodes[1], &mut self.miso_port.bus);
297 clock!(self, sys_clock, data_fifo);
298 self.data_fifo.data_in.next = self.mosi_port.port_out.val() << 1;
300 self.data_fifo.write.next = self.mosi_port.strobe_out.val();
301 self.mosi_port.ready.next = !self.data_fifo.full.val();
302 self.miso_port.port_in.next = self.data_fifo.data_out.val();
304 self.data_fifo.read.next = self.miso_port.strobe_out.val();
305 self.miso_port.ready_in.next = !self.data_fifo.empty.val();
306 FIFOWriteResponder::<Bits<16>>::link(&mut self.from_cpu, &mut self.from_cpu_fifo.bus_write);
308 FIFOReadResponder::<Bits<16>>::link(&mut self.to_cpu, &mut self.to_cpu_fifo.bus_read);
309 FIFOReadResponder::<Bits<16>>::join(
310 &mut self.from_cpu_fifo.bus_read,
311 &mut self.soc_host.from_cpu,
312 );
313 FIFOWriteResponder::<Bits<16>>::join(
314 &mut self.to_cpu_fifo.bus_write,
315 &mut self.soc_host.to_cpu,
316 );
317 }
318}