use rust_hdl::prelude::*; #[derive(LogicBlock)] struct ExpanderTest { pub clock: Signal, pub fifo_in: SynchronousFIFO, 8, 9, 1>, pub fifo_out: SynchronousFIFO, 4, 5, 1>, pub xpand: FIFOExpanderN<4, 32>, } impl Logic for ExpanderTest { #[hdl_gen] fn update(&mut self) { clock!(self, clock, fifo_in, fifo_out, xpand); self.xpand.empty.next = self.fifo_in.empty.val(); self.xpand.data_in.next = self.fifo_in.data_out.val(); self.fifo_in.read.next = self.xpand.read.val(); self.xpand.full.next = self.fifo_out.full.val(); self.fifo_out.data_in.next = self.xpand.data_out.val(); self.fifo_out.write.next = self.xpand.write.val(); } } impl ExpanderTest { pub fn new(word_order: WordOrder) -> Self { Self { clock: Default::default(), fifo_in: Default::default(), fifo_out: Default::default(), xpand: FIFOExpanderN::new(word_order), } } } #[test] fn test_expander_works() { let mut uut = ExpanderTest::new(WordOrder::MostSignificantFirst); uut.fifo_in.data_in.connect(); uut.fifo_in.write.connect(); uut.fifo_out.read.connect(); uut.connect_all(); let mut sim = Simulation::new(); sim.add_clock(5, |x: &mut Box| x.clock.next = !x.clock.val()); sim.add_testbench(move |mut sim: Sim| { let mut x = sim.init()?; wait_clock_true!(sim, clock, x); for datum in [ 0xD, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF, 0xC, 0xA, 0xF, 0xE, 0xB, 0xA, 0xB, 0xE, ] { x = sim.watch(|x| !x.fifo_in.full.val(), x)?; x.fifo_in.data_in.next = datum.into(); x.fifo_in.write.next = true; wait_clock_cycle!(sim, clock, x); x.fifo_in.write.next = false; } sim.done(x) }); sim.add_testbench(move |mut sim: Sim| { let mut x = sim.init()?; wait_clock_true!(sim, clock, x); for datum in [0xDEADBEEF, 0xCAFEBABE] { x = sim.watch(|x| !x.fifo_out.empty.val(), x)?; sim_assert!(sim, x.fifo_out.data_out.val() == Bits::<32>::from(datum), x); x.fifo_out.read.next = true; wait_clock_cycle!(sim, clock, x); x.fifo_out.read.next = false; } sim.done(x) }); sim.run_traced( Box::new(uut), 100_000, std::fs::File::create(vcd_path!("expandern.vcd")).unwrap(), ) .unwrap() } #[test] fn test_expander_works_with_lsw_first() { let mut uut = ExpanderTest::new(WordOrder::LeastSignificantFirst); uut.fifo_in.data_in.connect(); uut.fifo_in.write.connect(); uut.fifo_out.read.connect(); uut.connect_all(); let mut sim = Simulation::new(); sim.add_clock(5, |x: &mut Box| x.clock.next = !x.clock.val()); sim.add_testbench(move |mut sim: Sim| { let mut x = sim.init()?; wait_clock_true!(sim, clock, x); for datum in [ 0xD, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF, 0xC, 0xA, 0xF, 0xE, 0xB, 0xA, 0xB, 0xE, ] { x = sim.watch(|x| !x.fifo_in.full.val(), x)?; x.fifo_in.data_in.next = datum.into(); x.fifo_in.write.next = true; wait_clock_cycle!(sim, clock, x); x.fifo_in.write.next = false; } sim.done(x) }); sim.add_testbench(move |mut sim: Sim| { let mut x = sim.init()?; wait_clock_true!(sim, clock, x); for datum in [0xFEEBDAED, 0xEBABEFAC] { x = sim.watch(|x| !x.fifo_out.empty.val(), x)?; sim_assert!(sim, x.fifo_out.data_out.val() == Bits::<32>::from(datum), x); x.fifo_out.read.next = true; wait_clock_cycle!(sim, clock, x); x.fifo_out.read.next = false; } sim.done(x) }); sim.run_traced( Box::new(uut), 100_000, std::fs::File::create(vcd_path!("expandern_lsw.vcd")).unwrap(), ) .unwrap() } declare_expanding_fifo!(Fatten, 4, 256, 32, 16); #[derive(LogicBlock)] struct FattenTest { pub clock: Signal, pub fifo: Fatten, } impl Logic for FattenTest { #[hdl_gen] fn update(&mut self) { self.fifo.read_clock.next = self.clock.val(); self.fifo.write_clock.next = self.clock.val(); } } impl FattenTest { pub fn new(word_order: WordOrder) -> Self { Self { clock: Default::default(), fifo: Fatten::new(word_order), } } } #[test] fn test_fatten_works() { let mut uut = FattenTest::new(WordOrder::MostSignificantFirst); uut.fifo.data_in.connect(); uut.fifo.write.connect(); uut.fifo.read.connect(); uut.connect_all(); let mut sim = Simulation::new(); sim.add_clock(5, |x: &mut Box| x.clock.next = !x.clock.val()); sim.add_testbench(move |mut sim: Sim| { let mut x = sim.init()?; wait_clock_true!(sim, clock, x); for datum in [ 0xD, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF, 0xC, 0xA, 0xF, 0xE, 0xB, 0xA, 0xB, 0xE, ] { x = sim.watch(|x| !x.fifo.full.val(), x)?; x.fifo.data_in.next = datum.into(); x.fifo.write.next = true; wait_clock_cycle!(sim, clock, x); x.fifo.write.next = false; } sim.done(x) }); sim.add_testbench(move |mut sim: Sim| { let mut x = sim.init()?; wait_clock_true!(sim, clock, x); for datum in [0xDEADBEEF, 0xCAFEBABE] { x = sim.watch(|x| !x.fifo.empty.val(), x)?; sim_assert!(sim, x.fifo.data_out.val() == Bits::<32>::from(datum), x); x.fifo.read.next = true; wait_clock_cycle!(sim, clock, x); x.fifo.read.next = false; } sim.done(x) }); sim.run_traced( Box::new(uut), 100_000, std::fs::File::create(vcd_path!("fattenn.vcd")).unwrap(), ) .unwrap() }