From c387ce7ce5d25abaa982f76724ed04409669954b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 17 Feb 2012 17:34:59 +0100 Subject: [PATCH] Map DDR PHY controls in CSR --- milkymist/s6ddrphy/__init__.py | 44 ++++++++++++++++++++++++++++++---- software/include/hw/s6ddrphy.h | 36 ++++++++++++++++++++++++++++ software/include/hw/uart.h | 2 +- top.py | 7 ++++-- 4 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 software/include/hw/s6ddrphy.h diff --git a/milkymist/s6ddrphy/__init__.py b/milkymist/s6ddrphy/__init__.py index 3e3b94db7..6b2697031 100644 --- a/milkymist/s6ddrphy/__init__.py +++ b/milkymist/s6ddrphy/__init__.py @@ -1,8 +1,10 @@ from migen.fhdl.structure import * from migen.bus import dfi +from migen.bank.description import * +from migen.bank import csrgen class S6DDRPHY: - def __init__(self, a, ba, d): + def __init__(self, csr_address, a, ba, d): ins = [] outs = [] inouts = [] @@ -16,8 +18,7 @@ class S6DDRPHY: "clk4x_rd_left", "clk4x_rd_strb_left", "clk4x_rd_right", - "clk4x_rd_strb_right", - "reset_n" + "clk4x_rd_strb_right" ]: s = Signal(name=name) setattr(self, name, s) @@ -50,6 +51,8 @@ class S6DDRPHY: outs += self.dfi.get_standard_names(False, True) ins += [ + ("reset_n", BV(1)), + ("cfg_al", BV(3)), ("cfg_cl", BV(3)), ("cfg_bl", BV(2)), @@ -87,8 +90,23 @@ class S6DDRPHY: ("DM_IO_LOC", Constant(2**4-1, BV(4))) ], clkport="clk") + + self._reset_n = Field("reset_n") + self._init_done = Field("init_done") + self._phy_cal_done = Field("phy_cal_done", 1, READ_ONLY, WRITE_ONLY) + self._status = RegisterFields("status", + [self._reset_n, self._init_done, self._phy_cal_done]) + self._req = RegisterRaw("req", 2) + self._req_addr = RegisterField("req_addr", 8, READ_ONLY, WRITE_ONLY) + + self.bank = csrgen.Bank([self._status, self._req, self._req_addr], + address=csr_address) def get_fragment(self): + pending_r = Signal() + pending_w = Signal() + cpg_busy = Signal() + comb = [ self._inst.ins["cfg_al"].eq(0), self._inst.ins["cfg_cl"].eq(3), @@ -99,6 +117,22 @@ class S6DDRPHY: self._inst.ins["diag_io_sel"].eq(0), self._inst.ins["diag_disable_cal_on_startup"].eq(0), self._inst.ins["diag_cal_bits"].eq(0), - self._inst.ins["diag_short_cal"].eq(0) + self._inst.ins["diag_short_cal"].eq(0), + + self._inst.ins["reset_n"].eq(self._reset_n.r), + self._inst.ins["init_done"].eq(self._init_done.r), + self._phy_cal_done.w.eq(self._inst.outs["phy_cal_done"]), + self._req_addr.field.w.eq(self._inst.outs["cpg_addr"][2:10]), + + self._req.w.eq(Cat(pending_r, pending_w)), + cpg_busy.eq(pending_r | pending_w), + self._inst.ins["cpg_busy"].eq(cpg_busy) ] - return Fragment(comb, instances=[self._inst], pads=set(self._sd_pins)) + sync = [ + If(self._inst.outs["cpg_r_req"], pending_r.eq(1)), + If(self._inst.outs["cpg_w_req"], pending_w.eq(1)), + If(self._req.re & self._req.r[0], pending_r.eq(0)), + If(self._req.re & self._req.r[1], pending_w.eq(0)) + ] + return Fragment(comb, sync, instances=[self._inst], pads=set(self._sd_pins)) \ + + self.bank.get_fragment() diff --git a/software/include/hw/s6ddrphy.h b/software/include/hw/s6ddrphy.h new file mode 100644 index 000000000..a139c4c84 --- /dev/null +++ b/software/include/hw/s6ddrphy.h @@ -0,0 +1,36 @@ +/* + * Milkymist SoC (Software) + * Copyright (C) 2012 Sebastien Bourdeauducq + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __HW_S6DDRPHY_H +#define __HW_S6DDRPHY_H + +#include + +#define CSR_DDRPHY_STATUS MMPTR(0xe0000800) + +#define DDRPHY_STATUS_RESETN (0x1) +#define DDRPHY_STATUS_INIT_DONE (0x2) +#define DDRPHY_STATUS_PHY_CAL_DONE (0x4) + +#define CSR_DDRPHY_REQUESTS MMPTR(0xe0000804) + +#define DDRPHY_REQUEST_READ (0x1) +#define DDRPHY_REQUEST_WRITE (0x2) + +#define CSR_DDRPHY_REQADDR MMPTR(0xe0000808) + +#endif /* __HW_S6DDRPHY_H */ diff --git a/software/include/hw/uart.h b/software/include/hw/uart.h index c9e1e194b..d472e5d72 100644 --- a/software/include/hw/uart.h +++ b/software/include/hw/uart.h @@ -20,7 +20,7 @@ #include -#define CSR_UART_RXTX MMPTR(0xe0000000) +#define CSR_UART_RXTX MMPTR(0xe0000000) #define CSR_UART_DIVISORH MMPTR(0xe0000004) #define CSR_UART_DIVISORL MMPTR(0xe0000008) diff --git a/top.py b/top.py index dbf67dfc5..9452f7a46 100644 --- a/top.py +++ b/top.py @@ -31,7 +31,7 @@ def get(): # # ASMI # - ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128) + ddrphy0 = s6ddrphy.S6DDRPHY(1, 13, 2, 128) asmihub0 = asmibus.Hub(23, 128, 12) # TODO: get hub from memory controller asmiport_wb = asmihub0.get_port() asmihub0.finalize() @@ -68,7 +68,10 @@ def get(): # CSR # uart0 = uart.UART(0, clk_freq, baud=115200) - csrcon0 = csr.Interconnect(wishbone2csr0.csr, [uart0.bank.interface]) + csrcon0 = csr.Interconnect(wishbone2csr0.csr, [ + uart0.bank.interface, + ddrphy0.bank.interface + ]) # # Interrupts