use rust_hdl::prelude::*;
#[derive(LogicBlock)]
struct HostSDRAMControllerTest {
pc_to_host: SyncFIFO<Bits<8>, 3, 4, 1>,
host_to_pc: SyncFIFO<Bits<8>, 3, 4, 1>,
bidi_dev: BidiSimulatedDevice<Bits<8>>,
host: Host<8>,
core: SDRAMController<5, 5>,
buffer: SDRAMOnChipBuffer<16>,
chip: SDRAMSimulator<5, 5, 10, 16>,
pub bidi_clock: Signal<In, Clock>,
pub sys_clock: Signal<In, Clock>,
}
impl Logic for HostSDRAMControllerTest {
#[hdl_gen]
fn update(&mut self) {
FIFOReadController::<Bits<8>>::join(
&mut self.bidi_dev.data_to_bus,
&mut self.pc_to_host.bus_read,
);
FIFOWriteController::<Bits<8>>::join(
&mut self.bidi_dev.data_from_bus,
&mut self.host_to_pc.bus_write,
);
clock!(self, bidi_clock, host_to_pc, pc_to_host);
self.bidi_dev.clock.next = self.bidi_clock.val();
BidiBusD::<Bits<8>>::join(&mut self.bidi_dev.bus, &mut self.host.bidi_bus);
self.host.bidi_clock.next = self.bidi_clock.val();
self.host.sys_clock.next = self.sys_clock.val();
SoCBusController::<16, 8>::join(&mut self.host.bus, &mut self.core.upstream);
SDRAMDriver::<16>::join(&mut self.core.dram, &mut self.buffer.buf_in);
SDRAMDriver::<16>::join(&mut self.buffer.buf_out, &mut self.chip.sdram);
}
}
impl Default for HostSDRAMControllerTest {
fn default() -> Self {
let timings = MemoryTimings::fast_boot_sim(100e6);
Self {
pc_to_host: Default::default(),
host_to_pc: Default::default(),
bidi_dev: Default::default(),
host: Default::default(),
core: SDRAMController::new(3, timings, OutputBuffer::DelayTwo),
buffer: Default::default(),
chip: SDRAMSimulator::new(timings),
bidi_clock: Default::default(),
sys_clock: Default::default(),
}
}
}
#[cfg(test)]
fn make_sdram_test() -> HostSDRAMControllerTest {
let mut uut = HostSDRAMControllerTest::default();
uut.pc_to_host.bus_write.data.connect();
uut.pc_to_host.bus_write.write.connect();
uut.host_to_pc.bus_read.read.connect();
uut.connect_all();
uut
}
#[test]
fn test_sdram_test_synthesizes() {
let uut = make_sdram_test();
let vlog = generate_verilog(&uut);
yosys_validate("sdram_test", &vlog).unwrap();
}
#[test]
fn test_sdram_controller_boots() {
let uut = make_sdram_test();
let mut sim = Simulation::new();
sim.add_clock(5_000, |x: &mut Box<HostSDRAMControllerTest>| {
x.sys_clock.next = !x.sys_clock.val();
});
sim.add_clock(10_000, |x: &mut Box<HostSDRAMControllerTest>| {
x.bidi_clock.next = !x.bidi_clock.val();
});
sim.add_testbench(move |mut sim: Sim<HostSDRAMControllerTest>| {
let mut x = sim.init()?;
wait_clock_cycles!(sim, bidi_clock, x, 20); wait_clock_true!(sim, bidi_clock, x);
hls_host_ping!(sim, bidi_clock, x, pc_to_host, 0x67);
let reply = hls_host_get_word!(sim, bidi_clock, x, host_to_pc);
sim_assert_eq!(sim, reply, 0x167, x);
hls_host_write!(
sim,
bidi_clock,
x,
pc_to_host,
0,
[0x1234, 0x5678, 0xDEAD, 0xBEEF]
);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 1, [0x0000, 0x0000]);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 2, [0x0001]);
hls_host_write!(
sim,
bidi_clock,
x,
pc_to_host,
0,
[0xCAFE, 0xBABE, 0xEFFE, 0x5EA1]
);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 1, [0x0000, 0x0004]);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 2, [0x0001]);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 1, [0x0000, 0x0000]);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 2, [0x0000]);
hls_host_issue_read!(sim, bidi_clock, x, pc_to_host, 3, 0x0004);
let vals = hls_host_get_words!(sim, bidi_clock, x, host_to_pc, 4);
sim_assert_eq!(sim, vals, [0x1234, 0x5678, 0xdead, 0xbeef], x);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 1, [0x0000, 0x0002]);
hls_host_write!(sim, bidi_clock, x, pc_to_host, 2, [0x0000]);
hls_host_issue_read!(sim, bidi_clock, x, pc_to_host, 3, 0x0004);
let vals = hls_host_get_words!(sim, bidi_clock, x, host_to_pc, 4);
sim_assert_eq!(sim, vals, [0xeffe, 0x5ea1, 0x1234, 0x5678], x);
wait_clock_cycles!(sim, bidi_clock, x, 100);
sim.done(x)
});
sim.run_to_file(
Box::new(uut),
10_000_000,
&vcd_path!("hls_sdram_controller.vcd"),
)
.unwrap();
}