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 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 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}