rust_hdl_hls/
mosi_wide_port.rs

1use crate::bus::SoCPortResponder;
2use rust_hdl_core::prelude::*;
3use rust_hdl_widgets::prelude::*;
4
5#[derive(LogicBlock)]
6pub struct MOSIWidePort<const W: usize, const D: usize> {
7    pub bus: SoCPortResponder<D>,
8    pub clock_out: Signal<Out, Clock>,
9    pub port_out: Signal<Out, Bits<W>>,
10    pub strobe_out: Signal<Out, Bit>,
11    accum: DFF<Bits<W>>,
12    state: DFF<Bits<W>>,
13    address_active: DFF<Bit>,
14    offset: Constant<Bits<W>>,
15    modulo: Constant<Bits<8>>,
16    count: DFF<Bits<8>>,
17    strobe: DFF<Bit>,
18}
19
20impl<const W: usize, const D: usize> Default for MOSIWidePort<W, D> {
21    fn default() -> Self {
22        assert!(W > D);
23        assert_eq!(W % D, 0);
24        assert!(W / D < 256);
25        Self {
26            bus: Default::default(),
27            clock_out: Default::default(),
28            port_out: Default::default(),
29            strobe_out: Default::default(),
30            accum: Default::default(),
31            state: Default::default(),
32            address_active: Default::default(),
33            offset: Constant::new(D.to_bits()),
34            modulo: Constant::new((W / D - 1).to_bits()),
35            count: Default::default(),
36            strobe: Default::default(),
37        }
38    }
39}
40
41impl<const W: usize, const D: usize> Logic for MOSIWidePort<W, D> {
42    #[hdl_gen]
43    fn update(&mut self) {
44        self.clock_out.next = self.bus.clock.val();
45        dff_setup!(self, clock_out, accum, state, address_active, count, strobe);
46        // Compute the select/enable flag
47        self.address_active.d.next = self.bus.select.val();
48        self.bus.ready.next = false;
49        self.strobe_out.next = self.strobe.q.val();
50        self.strobe.d.next = false;
51        if self.address_active.q.val() {
52            self.bus.ready.next = true;
53            if self.bus.strobe.val() {
54                self.accum.d.next = (self.accum.q.val() << self.offset.val())
55                    | bit_cast::<W, D>(self.bus.from_controller.val());
56                self.count.d.next = self.count.q.val() + 1;
57                if self.count.q.val() == self.modulo.val() {
58                    self.count.d.next = 0.into();
59                    self.state.d.next = self.accum.q.val();
60                    self.strobe.d.next = true;
61                }
62            }
63        }
64        self.port_out.next = self.accum.q.val();
65        self.bus.to_controller.next = 0.into();
66    }
67}