rust_hdl_hls/
sdram_controller.rs

1use crate::bridge::Bridge;
2use crate::bus::{SoCBusResponder, SoCPortController};
3use crate::miso_wide_port::MISOWidePort;
4use crate::mosi_port::MOSIPort;
5use crate::mosi_wide_port::MOSIWidePort;
6use crate::HLSNamedPorts;
7use rust_hdl_core::prelude::*;
8use rust_hdl_widgets::prelude::*;
9
10#[derive(LogicBlock)]
11pub struct SDRAMController<const R: usize, const C: usize> {
12    pub dram: SDRAMDriver<16>,
13    pub upstream: SoCBusResponder<16, 8>,
14    local_bridge: Bridge<16, 8, 4>,
15    data_in: MOSIWidePort<64, 16>,
16    address: MOSIWidePort<32, 16>,
17    cmd: MOSIPort<16>,
18    data_out: MISOWidePort<64, 16>,
19    controller: SDRAMBaseController<R, C, 64, 16>,
20}
21
22impl<const R: usize, const C: usize> SDRAMController<R, C> {
23    pub fn new(
24        cas_delay: u32,
25        timings: MemoryTimings,
26        buffer: OutputBuffer,
27    ) -> SDRAMController<R, C> {
28        Self {
29            dram: Default::default(),
30            upstream: Default::default(),
31            local_bridge: Bridge::new(["data_in", "address", "cmd", "data_out"]),
32            data_in: Default::default(),
33            address: Default::default(),
34            cmd: Default::default(),
35            data_out: Default::default(),
36            controller: SDRAMBaseController::new(cas_delay, timings, buffer),
37        }
38    }
39}
40
41impl<const R: usize, const C: usize> HLSNamedPorts for SDRAMController<R, C> {
42    fn ports(&self) -> Vec<String> {
43        self.local_bridge.ports()
44    }
45}
46
47impl<const R: usize, const C: usize> Logic for SDRAMController<R, C> {
48    #[hdl_gen]
49    fn update(&mut self) {
50        SoCBusResponder::<16, 8>::link(&mut self.upstream, &mut self.local_bridge.upstream);
51        SDRAMDriver::<16>::link(&mut self.dram, &mut self.controller.sdram);
52        self.controller.clock.next = self.upstream.clock.val();
53        SoCPortController::<16>::join(&mut self.local_bridge.nodes[0], &mut self.data_in.bus);
54        SoCPortController::<16>::join(&mut self.local_bridge.nodes[1], &mut self.address.bus);
55        SoCPortController::<16>::join(&mut self.local_bridge.nodes[2], &mut self.cmd.bus);
56        SoCPortController::<16>::join(&mut self.local_bridge.nodes[3], &mut self.data_out.bus);
57        self.data_out.port_in.next = self.controller.data_out.val();
58        self.data_out.strobe_in.next = self.controller.data_valid.val();
59        self.controller.data_in.next = self.data_in.port_out.val();
60        self.controller.cmd_address.next = self.address.port_out.val();
61        self.controller.write_not_read.next = self.cmd.port_out.val().any();
62        self.controller.cmd_strobe.next = self.cmd.strobe_out.val();
63        self.cmd.ready.next = !self.controller.busy.val();
64    }
65}
66
67#[test]
68fn test_sdram_controller_synthesizes() {
69    let mut uut =
70        SDRAMController::<6, 4>::new(3, MemoryTimings::fast_boot_sim(100e6), OutputBuffer::Wired);
71    uut.connect_all();
72    yosys_validate("sdram_controller_hls", &generate_verilog(&uut)).unwrap();
73}