rust_hdl_hls/
mosi_port.rs

1use crate::bus::SoCPortResponder;
2use rust_hdl_core::prelude::*;
3use rust_hdl_widgets::prelude::*;
4
5// An output port simply stores the value written to that memory location
6// by the master.  The value is latched.
7// The strobe from the master is also forwarded.  This allows you to
8// build logic that knows when the value was changed, or treat the
9// strobe like a trigger.
10#[derive(LogicBlock, Default)]
11pub struct MOSIPort<const D: usize> {
12    pub bus: SoCPortResponder<D>,
13    pub port_out: Signal<Out, Bits<D>>,
14    pub strobe_out: Signal<Out, Bit>,
15    pub ready: Signal<In, Bit>,
16    pub clock_out: Signal<Out, Clock>,
17    state: DFF<Bits<D>>,
18    address_active: DFF<Bit>,
19    strobe: DFF<Bit>,
20}
21
22impl<const D: usize> Logic for MOSIPort<D> {
23    #[hdl_gen]
24    fn update(&mut self) {
25        self.clock_out.next = self.bus.clock.val();
26        dff_setup!(self, clock_out, state, address_active, strobe);
27        self.port_out.next = self.state.q.val();
28        self.address_active.d.next = self.bus.select.val();
29        self.bus.ready.next = false;
30        self.strobe_out.next = self.strobe.q.val();
31        self.strobe.d.next = false;
32        if self.address_active.q.val() {
33            self.bus.ready.next = self.ready.val() & self.bus.select.val();
34            if self.bus.strobe.val() {
35                self.state.d.next = self.bus.from_controller.val();
36            }
37            self.strobe.d.next = self.bus.strobe.val() & self.ready.val();
38        }
39        self.bus.to_controller.next = 0.into();
40    }
41}
42
43#[test]
44fn test_local_out_port_is_synthesizable() {
45    let mut dev = MOSIPort::<16>::default();
46    dev.connect_all();
47    let vlog = generate_verilog(&dev);
48    yosys_validate("localout", &vlog).unwrap();
49}