1use rust_hdl_core::prelude::*;
2use std::time::Duration;
3
4use crate::{dff::DFF, dff_setup};
5
6#[derive(Clone, Debug, LogicBlock)]
7pub struct Shot<const N: usize> {
8 pub trigger: Signal<In, Bit>,
9 pub active: Signal<Out, Bit>,
10 pub clock: Signal<In, Clock>,
11 pub fired: Signal<Out, Bit>,
12 duration: Constant<Bits<N>>,
13 counter: DFF<Bits<N>>,
14 state: DFF<Bit>,
15}
16
17impl<const N: usize> Shot<N> {
18 pub fn new(frequency: u64, duration: Duration) -> Self {
19 let duration_nanos = duration.as_nanos() as f64 * NANOS_PER_FEMTO; let clock_period_nanos = freq_hz_to_period_femto(frequency as f64);
21 let clocks = (duration_nanos / clock_period_nanos).floor() as u64;
22 assert!(clocks < (1_u64 << N));
23 Self {
24 trigger: Signal::default(),
25 active: Signal::new_with_default(false),
26 clock: Signal::default(),
27 fired: Default::default(),
28 duration: Constant::new(clocks.into()),
29 counter: Default::default(),
30 state: Default::default(),
31 }
32 }
33}
34
35impl<const N: usize> Logic for Shot<N> {
36 #[hdl_gen]
37 fn update(&mut self) {
38 dff_setup!(self, clock, counter, state);
39 if self.state.q.val() {
40 self.counter.d.next = self.counter.q.val() + 1;
41 }
42 self.fired.next = false;
43 if self.state.q.val() && (self.counter.q.val() == self.duration.val()) {
44 self.state.d.next = false;
45 self.fired.next = true;
46 }
47 self.active.next = self.state.q.val();
48 if self.trigger.val() {
49 self.state.d.next = true;
50 self.counter.d.next = 0.into();
51 }
52 }
53}