1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use crate::core::prelude::*;
use crate::widgets::fifo_logic::{FIFOReadLogic, FIFOWriteLogic};
use crate::widgets::ram::RAM;
#[macro_export]
macro_rules! declare_sync_fifo {
($name: ident, $kind: ty, $count: expr, $block: expr) => {
pub type $name = SynchronousFIFO<$kind, { clog2($count) }, { clog2($count) + 1 }, $block>;
};
}
#[derive(LogicBlock, Default)]
pub struct SynchronousFIFO<D: Synth, const N: usize, const NP1: usize, const BLOCK_SIZE: u32> {
pub clock: Signal<In, Clock>,
pub read: Signal<In, Bit>,
pub data_out: Signal<Out, D>,
pub empty: Signal<Out, Bit>,
pub almost_empty: Signal<Out, Bit>,
pub underflow: Signal<Out, Bit>,
pub write: Signal<In, Bit>,
pub data_in: Signal<In, D>,
pub full: Signal<Out, Bit>,
pub almost_full: Signal<Out, Bit>,
pub overflow: Signal<Out, Bit>,
ram: RAM<D, N>,
read_logic: FIFOReadLogic<D, N, NP1, BLOCK_SIZE>,
write_logic: FIFOWriteLogic<D, N, NP1, BLOCK_SIZE>,
}
impl<D: Synth, const N: usize, const NP1: usize, const BLOCK_SIZE: u32> Logic
for SynchronousFIFO<D, N, NP1, BLOCK_SIZE>
{
#[hdl_gen]
fn update(&mut self) {
self.read_logic.clock.next = self.clock.val();
self.read_logic.read.next = self.read.val();
self.empty.next = self.read_logic.empty.val();
self.almost_empty.next = self.read_logic.almost_empty.val();
self.data_out.next = self.read_logic.data_out.val();
self.underflow.next = self.read_logic.underflow.val();
self.write_logic.clock.next = self.clock.val();
self.overflow.next = self.write_logic.overflow.val();
self.almost_full.next = self.write_logic.almost_full.val();
self.full.next = self.write_logic.full.val();
self.write_logic.write.next = self.write.val();
self.write_logic.data_in.next = self.data_in.val();
self.ram.write_clock.next = self.clock.val();
self.ram.write_enable.next = self.write_logic.ram_write_enable.val();
self.ram.write_address.next = self.write_logic.ram_write_address.val();
self.ram.write_data.next = self.write_logic.ram_write_data.val();
self.ram.read_clock.next = self.clock.val();
self.ram.read_address.next = self.read_logic.ram_read_address.val();
self.read_logic.ram_read_data.next = self.ram.read_data.val();
self.read_logic.write_address_delayed.next = self.write_logic.write_address_delayed.val();
self.write_logic.read_address.next = self.read_logic.read_address_out.val();
}
}
#[test]
fn component_fifo_is_synthesizable() {
top_wrap!(SynchronousFIFO<Bits<8>, 4, 5, 1>, Wrapper);
let mut dev: Wrapper = Default::default();
dev.uut.clock.connect();
dev.uut.read.connect();
dev.uut.write.connect();
dev.uut.data_in.connect();
dev.connect_all();
yosys_validate("fifo", &generate_verilog(&dev)).unwrap();
println!("{}", generate_verilog(&dev));
}
#[test]
fn test_fifo_macro() {
declare_sync_fifo!(FIFOTest, Bits<8>, 32, 1);
let _dev = FIFOTest::default();
}