rust_hdl_widgets/ramrom/
rom.rs

1use rust_hdl_core::prelude::*;
2use std::collections::BTreeMap;
3
4#[derive(LogicBlock)]
5pub struct ROM<D: Synth, const N: usize> {
6    pub address: Signal<In, Bits<N>>,
7    pub data: Signal<Out, D>,
8    _sim: Box<BTreeMap<Bits<N>, D>>,
9}
10
11impl<D: Synth, const N: usize> ROM<D, N> {
12    pub fn new(values: BTreeMap<Bits<N>, D>) -> Self {
13        Self {
14            address: Signal::default(),
15            data: Signal::new_with_default(D::default()),
16            _sim: Box::new(values),
17        }
18    }
19}
20
21pub fn make_btree_from_iterable<I: Iterator<Item = D>, D: Synth, const N: usize>(
22    v: I,
23) -> BTreeMap<Bits<N>, D> {
24    let mut values = BTreeMap::new();
25    for (index, val) in v.enumerate() {
26        let address: Bits<N> = index.to_bits();
27        values.insert(address, val);
28    }
29    values
30}
31
32impl<I: Iterator<Item = D>, D: Synth, const N: usize> From<I> for ROM<D, N> {
33    fn from(v: I) -> Self {
34        Self::new(make_btree_from_iterable(v))
35    }
36}
37
38impl<D: Synth, const N: usize> Logic for ROM<D, N> {
39    fn update(&mut self) {
40        self.data.next = *self._sim.get(&self.address.val()).unwrap_or(&D::default());
41    }
42
43    fn connect(&mut self) {
44        self.data.connect();
45    }
46
47    fn hdl(&self) -> Verilog {
48        let cases = self
49            ._sim
50            .iter()
51            .map(|x| {
52                format!(
53                    "  {}: data = {};",
54                    x.0.verilog().to_string(),
55                    x.1.verilog().to_string()
56                )
57            })
58            .collect::<Vec<_>>()
59            .join("\n");
60        Verilog::Custom(format!(
61            "\
62always @*
63case (address)
64  {cases}
65  default: data = {default};
66endcase
67        ",
68            cases = cases,
69            default = D::default().verilog().to_string()
70        ))
71    }
72}