rust_hdl_widgets/
accum.rs1use 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}