1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use crate::core::prelude::*;
use crate::widgets::shot::Shot;
use crate::widgets::strobe::Strobe;
use std::time::Duration;

#[derive(LogicBlock)]
pub struct Pulser {
    pub clock: Signal<In, Clock>,
    pub enable: Signal<In, Bit>,
    pub pulse: Signal<Out, Bit>,
    strobe: Strobe<32>,
    shot: Shot<32>,
}

impl Pulser {
    pub fn new(clock_rate_hz: u64, pulse_rate_hz: f64, pulse_duration: Duration) -> Self {
        let strobe = Strobe::new(clock_rate_hz, pulse_rate_hz);
        let shot = Shot::new(clock_rate_hz, pulse_duration);
        Self {
            clock: Signal::default(),
            enable: Signal::default(),
            pulse: Signal::new_with_default(false),
            strobe,
            shot,
        }
    }
}

impl Logic for Pulser {
    #[hdl_gen]
    fn update(&mut self) {
        self.strobe.clock.next = self.clock.val();
        self.shot.clock.next = self.clock.val();
        self.strobe.enable.next = self.enable.val();
        self.shot.trigger.next = self.strobe.strobe.val();
        self.pulse.next = self.shot.active.val();
    }
}

#[test]
fn test_pulser_synthesis() {
    let mut uut = Pulser::new(1_000_000, 1.0, Duration::from_millis(100));
    uut.clock.connect();
    uut.enable.connect();
    uut.connect_all();
    let vlog = generate_verilog(&uut);
    println!("{}", vlog);
    yosys_validate("pulser", &vlog).unwrap();
}

#[test]
fn test_pulser() {
    let mut sim = Simulation::new();
    const KHZ10: u64 = 10_000;
    sim.add_clock(5, |x: &mut Box<Pulser>| x.clock.next = !x.clock.val());
    sim.add_testbench(|mut sim: Sim<Pulser>| {
        let mut x = sim.init()?;
        x.enable.next = true;
        x = sim.wait(100_000, x)?;
        sim.done(x)?;
        Ok(())
    });
    let mut uut = Pulser::new(KHZ10, 100.0, Duration::from_millis(100));
    uut.clock.connect();
    uut.enable.connect();
    uut.connect_all();
    sim.run_traced(
        Box::new(uut),
        1_000_000,
        std::fs::File::create(("/tmp/pulser.vcd")).unwrap(),
    )
    .unwrap();
}