rust_hdl_fpga_support/lattice/ecp5/
io_delay.rs1use rust_hdl_core::prelude::*;
2
3#[derive(Clone, Debug, LogicBlock)]
4pub struct IODelay<T: Synth> {
5 pub a: Signal<In, T>,
6 pub z: Signal<Out, T>,
7 _delay: u8,
8}
9
10impl<T: Synth> IODelay<T> {
11 pub fn new(delay: u8) -> Self {
12 Self {
13 a: Default::default(),
14 z: Default::default(),
15 _delay: delay,
16 }
17 }
18}
19
20fn wrapper_once(delay: u8) -> String {
21 format!(
22 r##"
23defparam udel_dataini0.DEL_VALUE = {delay} ;
24defparam udel_dataini0.DEL_MODE = "USER_DEFINED" ;
25DELAYG udel_dataini0 (.A(buf_dataini0), .Z(dataini_t0));
26 "##,
27 delay = delay
28 )
29}
30
31fn wrapper_multiple(count: usize, delay: u8) -> String {
32 (0..count)
33 .map(|x| {
34 format!(
35 r##"
36defparam udel_datain_{x}.DEL_VALUE = {delay} ;
37defparam udel_datain_{x}.DEL_MODE = "USER_DEFINED" ;
38DELAYG udel_datain_{x} (.A(a[{x}]), .Z(z[{x}]));
39 "##,
40 x = x,
41 delay = delay
42 )
43 })
44 .collect::<Vec<_>>()
45 .join("\n")
46}
47
48impl<T: Synth> Logic for IODelay<T> {
49 fn update(&mut self) {
50 self.z.next = self.a.val();
51 }
52 fn connect(&mut self) {
53 self.z.connect();
54 }
55 fn hdl(&self) -> Verilog {
56 Verilog::Wrapper(Wrapper {
57 code: if T::BITS == 1 {
58 wrapper_once(self._delay)
59 } else {
60 wrapper_multiple(T::BITS, self._delay)
61 },
62 cores: r##"
63(* blackbox *)
64module DELAYG(input A, output Z);
65parameter DEL_MODE = "USER_DEFINED";
66parameter DEL_VALUE = 0;
67endmodule
68 "##
69 .to_string(),
70 })
71 }
72}
73
74#[test]
75fn test_iodelay_synthesizes() {
76 let mut uut = IODelay::<Bits<8>>::new(25);
77 uut.connect_all();
78 yosys_validate("iodelay", &generate_verilog(&uut)).unwrap();
79}