rust_hdl_hls/
router_rom.rs

1use crate::bus::{SoCBusController, SoCBusResponder};
2use crate::HLSNamedPorts;
3use rust_hdl_core::prelude::*;
4use rust_hdl_widgets::prelude::*;
5use std::collections::BTreeMap;
6
7// A RouterROM allows you to connect multiple bridges to a single master
8// Each bridge is assigned a base address (they must be non-overlapping).
9// The master then sees each port on the bridge mapped to the offset
10// of it's base address.  Note that you can stack RouterROMs if needed.
11
12#[derive(LogicBlock)]
13pub struct RouterROM<const D: usize, const A: usize, const N: usize> {
14    pub upstream: SoCBusResponder<D, A>,
15    pub nodes: [SoCBusController<D, A>; N],
16    node_decode: ROM<Bits<8>, A>,
17    virtual_decode: ROM<Bits<A>, A>,
18    active: DFF<Bits<8>>,
19    virtual_address: DFF<Bits<A>>,
20    address_strobe_delay: DFF<Bit>,
21    clock: Signal<Local, Clock>,
22    _address_map: Vec<String>,
23}
24
25impl<const D: usize, const A: usize, const N: usize> HLSNamedPorts for RouterROM<D, A, N> {
26    fn ports(&self) -> Vec<String> {
27        self._address_map.clone()
28    }
29}
30
31impl<const D: usize, const A: usize, const N: usize> RouterROM<D, A, N> {
32    pub fn new(downstream_names: [&str; N], downstream_devices: [&dyn HLSNamedPorts; N]) -> Self {
33        let address_count = downstream_devices
34            .iter()
35            .map(|x| x.ports().len())
36            .collect::<Vec<_>>();
37        let mut _address_map = vec![];
38        for ndx in 0..N {
39            let prefix = downstream_names[ndx];
40            _address_map.extend(
41                downstream_devices[ndx]
42                    .ports()
43                    .iter()
44                    .map(|x| format!("{}_{}", prefix, x)),
45            );
46        }
47        // Make the node decode ROM
48        let mut offset = 0;
49        let mut node_rom = BTreeMap::new();
50        let mut base_rom = BTreeMap::new();
51        for (ndx, count) in address_count.iter().enumerate() {
52            assert_ne!(*count, 0);
53            for addr in 0..*count {
54                let address: Bits<A> = (offset + addr).to_bits();
55                let node: Bits<8> = ndx.to_bits();
56                node_rom.insert(address, node);
57                let virtual_address: Bits<A> = addr.to_bits();
58                base_rom.insert(address, virtual_address);
59            }
60            offset = offset + count;
61        }
62        Self {
63            upstream: Default::default(),
64            nodes: array_init::array_init(|_| Default::default()),
65            node_decode: ROM::new(node_rom),
66            virtual_decode: ROM::new(base_rom),
67            active: Default::default(),
68            virtual_address: Default::default(),
69            address_strobe_delay: Default::default(),
70            clock: Default::default(),
71            _address_map,
72        }
73    }
74}
75
76impl<const D: usize, const A: usize, const N: usize> Logic for RouterROM<D, A, N> {
77    #[hdl_gen]
78    fn update(&mut self) {
79        self.clock.next = self.upstream.clock.val();
80        self.upstream.ready.next = false;
81        self.upstream.to_controller.next = 0.into();
82        dff_setup!(self, clock, active, virtual_address, address_strobe_delay);
83        self.node_decode.address.next = self.upstream.address.val();
84        self.virtual_decode.address.next = self.upstream.address.val();
85        if self.upstream.address_strobe.val() {
86            self.active.d.next = self.node_decode.data.val();
87            self.virtual_address.d.next = self.virtual_decode.data.val();
88        }
89        // Delay the address strobe by 1 clock cycle to allow the virtual address
90        // calculation to be pipelined.
91        self.address_strobe_delay.d.next = self.upstream.address_strobe.val();
92        for i in 0..N {
93            self.nodes[i].from_controller.next = 0x5ea1.into();
94            self.nodes[i].address.next = 0.into();
95            self.nodes[i].address_strobe.next = false;
96            self.nodes[i].strobe.next = false;
97            self.nodes[i].clock.next = self.clock.val();
98            if self.active.q.val().index() == i {
99                self.nodes[i].from_controller.next = self.upstream.from_controller.val();
100                self.nodes[i].address.next = self.virtual_address.q.val();
101                self.nodes[i].strobe.next = self.upstream.strobe.val();
102                self.upstream.to_controller.next = self.nodes[i].to_controller.val();
103                self.upstream.ready.next = self.nodes[i].ready.val();
104                self.nodes[i].address_strobe.next = self.address_strobe_delay.q.val();
105            }
106        }
107        if self.upstream.address_strobe.val() {
108            self.upstream.ready.next = false;
109        }
110    }
111}
112
113#[test]
114fn test_router_rom_is_synthesizable() {
115    use crate::bridge::Bridge;
116    let bridge1 = Bridge::<16, 8, 4>::new(["Top", "Left", "Right", "Bottom"]);
117    let bridge2 = Bridge::<16, 8, 2>::new(["Red", "Blue"]);
118    let bridge3 =
119        Bridge::<16, 8, 6>::new(["Club", "Spades", "Diamond", "Heart", "Joker", "Instruction"]);
120    let mut router =
121        RouterROM::<16, 8, 3>::new(["Sides", "Colors", "Faces"], [&bridge1, &bridge2, &bridge3]);
122    router.connect_all();
123    let vlog = generate_verilog(&router);
124    yosys_validate("router_rom", &vlog).unwrap();
125}