rust_hdl_widgets/
accum.rs

1use rust_hdl_core::prelude::*;
2
3use crate::dff::DFF;
4
5#[derive(Clone, Debug, LogicBlock)]
6pub struct Accum<const N: usize, const M: usize, const P: usize> {
7    pub clock: Signal<In, Clock>,
8    pub strobe_in: Signal<In, Bit>,
9    pub data_in: Signal<In, Bits<N>>,
10    pub strobe_out: Signal<Out, Bit>,
11    pub data_out: Signal<Out, Bits<M>>,
12    accum: DFF<Bits<M>>,
13    counter: DFF<Bits<P>>,
14    max_count: Constant<Bits<P>>,
15}
16
17impl<const N: usize, const M: usize, const P: usize> Logic for Accum<N, M, P> {
18    fn update(&mut self) {
19        self.accum.clock.next = self.clock.val();
20        self.counter.clock.next = self.clock.val();
21        self.strobe_out.next = false;
22        self.data_out.next = self.accum.q.val();
23        self.accum.d.next = self.accum.q.val();
24        if self.strobe_in.val() {
25            self.accum.d.next = self.accum.q.val() + bit_cast::<M, N>(self.data_in.val());
26            self.counter.d.next = self.counter.q.val() + 1;
27        }
28        if self.counter.q.val() == self.max_count.val() {
29            self.strobe_out.next = true;
30            self.counter.d.next = 0.into();
31            self.accum.d.next = 0.into();
32        }
33    }
34}
35
36impl<const N: usize, const M: usize, const P: usize> Accum<N, M, P> {
37    pub fn new(count: usize) -> Self {
38        assert!(P >= clog2(count));
39        assert!(M >= N + P);
40        Self {
41            clock: Default::default(),
42            strobe_in: Default::default(),
43            data_in: Default::default(),
44            strobe_out: Default::default(),
45            accum: DFF::default(),
46            counter: DFF::default(),
47            max_count: Constant::new(count.to_bits()),
48            data_out: Default::default(),
49        }
50    }
51}
52
53#[test]
54fn test_accum_synthesizes() {
55    let _p = TopWrap::new(Accum::<32, 40, 6>::new(50));
56}