rust_hdl_core/
clock.rs

1use std::fmt::Debug;
2
3/// Fundamentally a Clock signal in RustHDL is simply a transparent wrapper around a boolean
4/// valued signal.  So it could be thought of as a simple 1-bit wide signal.  However, semantically,
5/// clocks are rarely treated like other signals, and typically connect only to dedicated clock
6/// ports on synchronous logic (like [DFF] or [RAM]).
7#[repr(transparent)]
8#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Debug)]
9pub struct Clock {
10    /// The clock signal itself.  Available using this field of the struct.
11    pub clk: bool,
12}
13
14/// The number of nanoseconds per femtosecond.
15pub const NANOS_PER_FEMTO: f64 = 1_000_000.0;
16
17/// Convert a frequency in Hz to a period in femtoseconds.
18pub fn freq_hz_to_period_femto(freq: f64) -> f64 {
19    (1.0e15 / freq).round()
20}
21
22#[test]
23fn test_freq_to_period_mapping() {
24    assert_eq!(freq_hz_to_period_femto(1.0), 1.0e15)
25}
26
27impl std::ops::Not for Clock {
28    type Output = Clock;
29
30    fn not(self) -> Self::Output {
31        Clock { clk: !self.clk }
32    }
33}
34
35impl From<bool> for Clock {
36    fn from(x: bool) -> Clock {
37        Clock { clk: x }
38    }
39}
40
41/// The [clock!] macro is used to connect a set of devices to a common clock.
42/// The macro takes a variable number of arguments:
43///  * `self` - the struct containing the items to connect, normally just `self`
44///  * `clock` - the name of the field of the struct that holds the clock source
45///  * `subs` - the set of fields that should be clocked with `clock`.
46/// Note that the macro assumes that the sub-circuits being clocked all have clock inputs
47/// named `clock`.
48///
49/// For example:
50/// ```
51/// use rust_hdl_core::prelude::*;
52///
53/// #[derive(LogicBlock)]
54/// pub struct SubWidget {
55///    pub clock: Signal<In, Clock>,
56/// }
57///
58/// # impl Logic for SubWidget {
59/// #   #[hdl_gen]
60/// #   fn update(&mut self) {}
61/// # }
62///
63/// #[derive(LogicBlock)]
64/// pub struct Widget {
65///    pub clock: Signal<In, Clock>,
66///    pub dff_1: SubWidget,
67///    pub dff_2: SubWidget,
68/// }
69///
70/// impl Logic for Widget {
71///    #[hdl_gen]
72///    fn update(&mut self) {
73///        // This is equivalent to:
74///        // self.dff_1.clock.next = self.clock.val();
75///        // self.dff_2.clock.next = self.clock.val();
76///        clock!(self, clock, dff_1, dff_2);
77///    }
78/// }
79/// ```
80///
81/// When you have many [DFF]s or several complex sub-circuits, the `clock!` macro can make it
82/// easier to read the source code.
83#[macro_export]
84macro_rules! clock {
85    ($self: ident, $clock: ident, $($subs: ident), +) => {
86        $($self.$subs.clock.next = $self.$clock.val());+;
87    }
88}