rust_hdl_lib_hls/
cross_fifo.rs

1use crate::bus::{FIFOReadResponder, FIFOWriteResponder};
2use rust_hdl_lib_core::prelude::*;
3use rust_hdl_lib_widgets::prelude::*;
4
5#[derive(LogicBlock, Default)]
6pub struct CrossWiden<
7    const DN: usize,
8    const NN: usize,
9    const NNP1: usize,
10    const DW: usize,
11    const WN: usize,
12    const WNP1: usize,
13> {
14    pub narrow_bus: FIFOWriteResponder<Bits<DN>>,
15    pub narrow_clock: Signal<In, Clock>,
16    pub wide_bus: FIFOReadResponder<Bits<DW>>,
17    pub wide_clock: Signal<In, Clock>,
18    widen: CrossWidenFIFO<DN, NN, NNP1, DW, WN, WNP1>,
19}
20
21impl<
22        const DN: usize,
23        const NN: usize,
24        const NNP1: usize,
25        const DW: usize,
26        const WN: usize,
27        const WNP1: usize,
28    > CrossWiden<DN, NN, NNP1, DW, WN, WNP1>
29{
30    pub fn new(order: WordOrder) -> Self {
31        Self {
32            narrow_bus: Default::default(),
33            narrow_clock: Default::default(),
34            wide_bus: Default::default(),
35            wide_clock: Default::default(),
36            widen: CrossWidenFIFO::new(order),
37        }
38    }
39}
40
41impl<
42        const DN: usize,
43        const NN: usize,
44        const NNP1: usize,
45        const DW: usize,
46        const WN: usize,
47        const WNP1: usize,
48    > Logic for CrossWiden<DN, NN, NNP1, DW, WN, WNP1>
49{
50    #[hdl_gen]
51    fn update(&mut self) {
52        // Wire up the input side
53        self.widen.data_in.next = self.narrow_bus.data.val();
54        self.widen.write.next = self.narrow_bus.write.val();
55        self.narrow_bus.full.next = self.widen.full.val();
56        self.narrow_bus.almost_full.next = self.widen.full.val();
57        self.widen.write_clock.next = self.narrow_clock.val();
58        // Wire up the output side
59        self.wide_bus.data.next = self.widen.data_out.val();
60        self.wide_bus.empty.next = self.widen.empty.val();
61        self.wide_bus.almost_empty.next = self.widen.empty.val();
62        self.widen.read.next = self.wide_bus.read.val();
63        self.widen.read_clock.next = self.wide_clock.val();
64    }
65}
66
67#[test]
68fn test_hsl_cross_fifo_synthesizes() {
69    let mut uut: CrossWiden<4, 5, 6, 16, 3, 4> = CrossWiden::new(WordOrder::LeastSignificantFirst);
70    uut.connect_all();
71    let vlog = generate_verilog(&uut);
72    yosys_validate("hsl_cross_fifo", &vlog).unwrap();
73}
74
75#[derive(LogicBlock, Default)]
76pub struct CrossNarrow<
77    const DW: usize,
78    const WN: usize,
79    const WNP1: usize,
80    const DN: usize,
81    const NN: usize,
82    const NNP1: usize,
83> {
84    pub wide_bus: FIFOWriteResponder<Bits<DW>>,
85    pub wide_clock: Signal<In, Clock>,
86    pub narrow_bus: FIFOReadResponder<Bits<DN>>,
87    pub narrow_clock: Signal<In, Clock>,
88    narrow: CrossNarrowFIFO<DW, WN, WNP1, DN, NN, NNP1>,
89}
90
91impl<
92        const DW: usize,
93        const WN: usize,
94        const WNP1: usize,
95        const DN: usize,
96        const NN: usize,
97        const NNP1: usize,
98    > CrossNarrow<DW, WN, WNP1, DN, NN, NNP1>
99{
100    pub fn new(order: WordOrder) -> Self {
101        Self {
102            wide_bus: Default::default(),
103            wide_clock: Default::default(),
104            narrow_bus: Default::default(),
105            narrow_clock: Default::default(),
106            narrow: CrossNarrowFIFO::new(order),
107        }
108    }
109}
110
111impl<
112        const DW: usize,
113        const WN: usize,
114        const WNP1: usize,
115        const DN: usize,
116        const NN: usize,
117        const NNP1: usize,
118    > Logic for CrossNarrow<DW, WN, WNP1, DN, NN, NNP1>
119{
120    #[hdl_gen]
121    fn update(&mut self) {
122        self.narrow.data_in.next = self.wide_bus.data.val();
123        self.narrow.write.next = self.wide_bus.write.val();
124        self.wide_bus.full.next = self.narrow.full.val();
125        self.wide_bus.almost_full.next = self.narrow.full.val();
126        self.narrow.write_clock.next = self.wide_clock.val();
127        self.narrow_bus.data.next = self.narrow.data_out.val();
128        self.narrow_bus.empty.next = self.narrow.empty.val();
129        self.narrow_bus.almost_empty.next = self.narrow.empty.val();
130        self.narrow.read.next = self.narrow_bus.read.val();
131        self.narrow.read_clock.next = self.narrow_clock.val();
132    }
133}
134
135#[test]
136fn test_hsl_cross_narrow_synthesizes() {
137    let mut uut: CrossNarrow<16, 3, 4, 4, 5, 6> =
138        CrossNarrow::new(WordOrder::LeastSignificantFirst);
139    uut.connect_all();
140    let vlog = generate_verilog(&uut);
141    yosys_validate("hsl_cross_narrow_fifo", &vlog).unwrap();
142}