From f81e4fedcd519a83719eb8df9496917b8e66437c Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Sat, 29 Jan 2022 11:23:23 +0100 Subject: [PATCH] oups, forgotten files for DDR3 hardware initializer based on gist 529a4d9994f0cc95e45382e4eb253b09-3c8bb9c1f4528ccb0c0ef603d66f05b1470e8056 --- sbus-to-ztex-gateware-migen/sdram_init.py | 153 ++++++++++++++++++++++ sbus-to-ztex-gateware-migen/wb_master.py | 108 +++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 sbus-to-ztex-gateware-migen/sdram_init.py create mode 100644 sbus-to-ztex-gateware-migen/wb_master.py diff --git a/sbus-to-ztex-gateware-migen/sdram_init.py b/sbus-to-ztex-gateware-migen/sdram_init.py new file mode 100644 index 0000000..42f9378 --- /dev/null +++ b/sbus-to-ztex-gateware-migen/sdram_init.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +from migen import * + +from wb_master import * +from wb_master import _WRITE_CMD, _WAIT_CMD, _DONE_CMD + + +dfii_control_sel = 0x01 +dfii_control_cke = 0x02 +dfii_control_odt = 0x04 +dfii_control_reset_n = 0x08 + +dfii_command_cs = 0x01 +dfii_command_we = 0x02 +dfii_command_cas = 0x04 +dfii_command_ras = 0x08 +dfii_command_wrdata = 0x10 +dfii_command_rddata = 0x20 + +# /!\ keep up to date with csr /!\ +sdram_dfii_base = 0x00043000 +sdram_dfii_control = sdram_dfii_base + 0x000 +sdram_dfii_pi0_command = sdram_dfii_base + 0x004 +sdram_dfii_pi0_command_issue = sdram_dfii_base + 0x008 +sdram_dfii_pi0_address = sdram_dfii_base + 0x00c +sdram_dfii_pi0_baddress = sdram_dfii_base + 0x010 + +# /!\ keep up to date with csr /!\ +ddrphy_base = 0x00041000 +ddrphy_rst = ddrphy_base + 0x000 +ddrphy_dly_sel = ddrphy_base + 0x010 +ddrphy_rdly_dq_rst = ddrphy_base + 0x014 +ddrphy_rdly_dq_inc = ddrphy_base + 0x018 +ddrphy_rdly_dq_bitslip_rst = ddrphy_base + 0x01c +ddrphy_rdly_dq_bitslip = ddrphy_base + 0x020 +ddrphy_wdly_dq_bitslip_rst = ddrphy_base + 0x024 +ddrphy_wdly_dq_bitslip = ddrphy_base + 0x028 +ddrphy_rdphase = ddrphy_base + 0x02c +ddrphy_wdphase = ddrphy_base + 0x030 + + +def period_to_cycles(sys_clk_freq, period): + return int(period*sys_clk_freq) + +def ddr3_init_instructions(sys_clk_freq): + return [ + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001), + # phase + _WRITE_CMD, ddrphy_rdphase, 2, + _WRITE_CMD, ddrphy_wdphase, 3, + + # software control + _WRITE_CMD, sdram_dfii_control, dfii_control_reset_n | dfii_control_odt | dfii_control_cke, + + # reset + _WRITE_CMD, ddrphy_rst, 1, + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001), + _WRITE_CMD, ddrphy_rst, 0, + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001), + + # release reset + _WRITE_CMD, sdram_dfii_pi0_address, 0x0, + _WRITE_CMD, sdram_dfii_pi0_baddress, 0, + _WRITE_CMD, sdram_dfii_control, dfii_control_odt|dfii_control_reset_n, + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.005), + + # bring cke high + _WRITE_CMD, sdram_dfii_pi0_address, 0x0, + _WRITE_CMD, sdram_dfii_pi0_baddress, 0, + _WRITE_CMD, sdram_dfii_control, dfii_control_cke|dfii_control_odt|dfii_control_reset_n, + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001), + + # load mode register 2, CWL = 5 + _WRITE_CMD, sdram_dfii_pi0_address, 0x200, + _WRITE_CMD, sdram_dfii_pi0_baddress, 2, + _WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, + _WRITE_CMD, sdram_dfii_pi0_command_issue, 1, + + # load mode register 3 + _WRITE_CMD, sdram_dfii_pi0_address, 0x0, + _WRITE_CMD, sdram_dfii_pi0_baddress, 3, + _WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, + _WRITE_CMD, sdram_dfii_pi0_command_issue, 1, + + # load mode register 1 + _WRITE_CMD, sdram_dfii_pi0_address, 0x6, + _WRITE_CMD, sdram_dfii_pi0_baddress, 1, + _WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, + _WRITE_CMD, sdram_dfii_pi0_command_issue, 1, + + # load mode register 0, CL=6, BL=8 + _WRITE_CMD, sdram_dfii_pi0_address, 0x920, + _WRITE_CMD, sdram_dfii_pi0_baddress, 0, + _WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs, + _WRITE_CMD, sdram_dfii_pi0_command_issue, 1, + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.0002), + + # zq calibration + _WRITE_CMD, sdram_dfii_pi0_address, 0x400, + _WRITE_CMD, sdram_dfii_pi0_baddress, 0, + _WRITE_CMD, sdram_dfii_pi0_command, dfii_command_we|dfii_command_cs, + _WRITE_CMD, sdram_dfii_pi0_command_issue, 1, + _WAIT_CMD | period_to_cycles(sys_clk_freq, 0.0002), + + # hardware control + _WRITE_CMD, sdram_dfii_control, dfii_control_sel, +] + + +def ddr3_config_instructions(bitslip, delay): + r = [] + for module in range(2): + r += [_WRITE_CMD, ddrphy_dly_sel, 1<> 28) + + +class WishboneMaster(Module): + def __init__(self, instructions): + self.bus = bus = wishbone.Interface() + + self.run = Signal() + self.done = Signal() + self.error = Signal() + + # # # + mem = Memory(32, len(instructions), init=instructions) + port = mem.get_port(async_read=True) + self.specials += mem, port + + wait_counter = Signal(32) + + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + fsm.act("IDLE", + self.run.eq(1), + NextState("CMD") + ) + fsm.act("CMD", + self.run.eq(1), + If(cmd_decoder(port.dat_r, _WRITE_CMD), + NextValue(port.adr, port.adr + 1), + NextState("WRITE_ADR") + ).Elif(cmd_decoder(port.dat_r, _WAIT_CMD), + NextValue(wait_counter, port.dat_r[:28]), + NextState("WAIT") + ).Elif(cmd_decoder(port.dat_r, _DONE_CMD), + NextState("DONE") + ).Else( + NextState("ERROR") + ) + ) + fsm.act("WAIT", + self.run.eq(1), + NextValue(wait_counter, wait_counter - 1), + If(wait_counter == 0, + NextValue(port.adr, port.adr + 1), + NextState("CMD") + ) + ) + fsm.act("WRITE_ADR", + self.run.eq(1), + NextValue(bus.adr, port.dat_r[2:]), + NextValue(port.adr, port.adr + 1), + NextState("WRITE_DATA") + ) + fsm.act("WRITE_DATA", + self.run.eq(1), + NextValue(bus.dat_w, port.dat_r), + NextValue(port.adr, port.adr + 1), + NextState("WRITE") + ) + fsm.act("WRITE", + self.run.eq(1), + bus.stb.eq(1), + bus.cyc.eq(1), + bus.we.eq(1), + bus.sel.eq(0xf), + If(bus.ack, + If(bus.err, + NextState("ERROR"), + ).Else( + NextState("CMD") + ) + ) + ) + fsm.act("ERROR", self.error.eq(1)) + fsm.act("DONE", self.done.eq(1)) + + +if __name__ == "__main__": + instructions = [ + _WRITE_CMD, + 0x12340000, + 0x0000A5A5, + _WAIT_CMD | 0x20, + _WRITE_CMD, + 0x00001234, + 0xDEADBEEF, + _DONE_CMD + ] + + dut = WishboneMaster(instructions) + + def dut_tb(dut): + yield dut.bus.ack.eq(1) + for i in range(1024): + yield + + run_simulation(dut, dut_tb(dut), vcd_name="wb_master.vcd") +