rust_hdl_hls/
bridge.rs

1use crate::bus::*;
2use crate::HLSNamedPorts;
3use rust_hdl_core::prelude::*;
4use rust_hdl_widgets::prelude::*;
5
6// A simple bus bridge.  It connects to the master on the one side, and
7// then exposes a number of device ports on the other side.  Data is
8// routed based on the address selection.  Note that reset is resynchronized
9// by the bridge.  This means different "devices" will come out of reset
10// at different times as the reset de-assert propagates through the network.
11
12#[derive(LogicBlock)]
13pub struct Bridge<const D: usize, const A: usize, const N: usize> {
14    pub upstream: SoCBusResponder<D, A>,
15    pub nodes: [SoCPortController<D>; N],
16    pub clock_out: Signal<Out, Clock>,
17    address_latch: DFF<Bits<A>>,
18    _port_names: Vec<String>,
19}
20
21impl<const D: usize, const A: usize, const N: usize> Bridge<D, A, N> {
22    pub fn new(names: [&str; N]) -> Self {
23        assert!(N <= 2_usize.pow(A as u32));
24        Self {
25            upstream: Default::default(),
26            nodes: array_init::array_init(|_| Default::default()),
27            clock_out: Default::default(),
28            address_latch: Default::default(),
29            _port_names: names.iter().map(|x| x.to_string()).collect(),
30        }
31    }
32}
33
34impl<const D: usize, const A: usize, const N: usize> HLSNamedPorts for Bridge<D, A, N> {
35    fn ports(&self) -> Vec<String> {
36        self._port_names.clone()
37    }
38}
39
40impl<const D: usize, const A: usize, const N: usize> Logic for Bridge<D, A, N> {
41    #[hdl_gen]
42    fn update(&mut self) {
43        self.clock_out.next = self.upstream.clock.val();
44        self.upstream.ready.next = false;
45        self.upstream.to_controller.next = 0.into();
46        dff_setup!(self, clock_out, address_latch);
47        for i in 0..N {
48            self.nodes[i].from_controller.next = 0.into();
49            self.nodes[i].select.next = false;
50            self.nodes[i].strobe.next = false;
51            self.nodes[i].clock.next = self.upstream.clock.val();
52            if self.address_latch.q.val().index() == i {
53                self.nodes[i].from_controller.next = self.upstream.from_controller.val();
54                self.nodes[i].select.next = true;
55                self.nodes[i].strobe.next = self.upstream.strobe.val();
56                self.upstream.to_controller.next = self.nodes[i].to_controller.val();
57                self.upstream.ready.next = self.nodes[i].ready.val();
58            }
59        }
60        if self.upstream.address_strobe.val() {
61            self.address_latch.d.next = self.upstream.address.val();
62            self.upstream.ready.next = false;
63        }
64    }
65}
66
67#[test]
68fn test_bridge_is_synthesizable() {
69    let mut uut = Bridge::<16, 8, 6>::new(["a", "b", "c", "d", "e", "f"]);
70    uut.connect_all();
71    let vlog = generate_verilog(&uut);
72    yosys_validate("soc_bridge", &vlog).unwrap();
73}