rust_hdl_hls/
miso_wide_port.rs1use crate::bus::SoCPortResponder;
2use rust_hdl_core::prelude::*;
3use rust_hdl_widgets::prelude::*;
4
5#[derive(LogicBlock)]
6pub struct MISOWidePort<const W: usize, const D: usize> {
7 pub bus: SoCPortResponder<D>,
8 pub port_in: Signal<In, Bits<W>>,
9 pub strobe_in: Signal<In, Bit>,
10 pub clock_out: Signal<Out, Clock>,
11 accum: DFF<Bits<W>>,
12 address_active: DFF<Bit>,
13 offset: Constant<Bits<16>>,
14 shift: Constant<Bits<16>>,
15 modulo: Constant<Bits<8>>,
16 count: DFF<Bits<8>>,
17 ready: DFF<Bit>,
18}
19
20impl<const W: usize, const D: usize> Default for MISOWidePort<W, D> {
21 fn default() -> Self {
22 assert!(W > D);
23 assert_eq!(W % D, 0);
24 assert!(W / D < 256);
25 assert!(W < 65536);
26 Self {
27 bus: Default::default(),
28 port_in: Default::default(),
29 strobe_in: Default::default(),
30 clock_out: Default::default(),
31 accum: Default::default(),
32 address_active: Default::default(),
33 offset: Constant::new(D.to_bits()),
34 shift: Constant::new((W - D).to_bits()),
35 modulo: Constant::new((W / D).to_bits()),
36 count: Default::default(),
37 ready: Default::default(),
38 }
39 }
40}
41
42impl<const W: usize, const D: usize> Logic for MISOWidePort<W, D> {
43 #[hdl_gen]
44 fn update(&mut self) {
45 self.clock_out.next = self.bus.clock.val();
46 dff_setup!(self, clock_out, accum, address_active, count, ready);
47 self.address_active.d.next = self.bus.select.val();
49 self.bus.ready.next = false;
50 if self.strobe_in.val() {
52 self.accum.d.next = self.port_in.val();
53 self.count.d.next = self.modulo.val();
54 }
55 self.bus.to_controller.next = 0.into();
56 self.ready.d.next = self.count.q.val().any() & self.address_active.q.val();
57 if self.address_active.q.val() {
58 self.bus.to_controller.next =
59 self.accum.q.val().get_bits::<D>(self.shift.val().index());
60 self.bus.ready.next = self.ready.q.val() & self.count.q.val().any();
61 if self.bus.strobe.val() {
62 self.accum.d.next = self.accum.q.val() << bit_cast::<W, 16>(self.offset.val());
63 self.count.d.next = self.count.q.val() - 1;
64 }
65 }
66 }
67}
68
69#[test]
70fn test_local_in_wide_port_is_synthesizable() {
71 let mut dev = MISOWidePort::<64, 16>::default();
72 dev.connect_all();
73 let vlog = generate_verilog(&dev);
74 yosys_validate("local_wide_in", &vlog).unwrap();
75}