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}