Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Connect DDR PHY

Doesn't do much for the moment, just to check synthesis/P&R.
  • Loading branch information...
commit 5d1dad583b1ab8be6cd0b7b0c85df50e19b8c484 1 parent cdd58e0
Sébastien Bourdeauducq sbourdeauducq authored
9 build.py
View
@@ -4,13 +4,16 @@
# list Verilog sources before changing directory
verilog_sources = []
def add_core_dir(d):
- for root, subFolders, files in os.walk(os.path.join("verilog", d)):
- for f in files:
+ root = os.path.join("verilog", d)
+ files = os.listdir(root)
+ for f in files:
+ if f[-2:] == ".v":
verilog_sources.append(os.path.join(root, f))
def add_core_files(d, files):
for f in files:
verilog_sources.append(os.path.join("verilog", d, f))
add_core_dir("m1crg")
+add_core_dir("s6ddrphy")
add_core_files("lm32", ["lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
"lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
"lm32_shifter.v", "lm32_multiplier_spartan6.v", "lm32_mc_arithmetic.v",
@@ -31,7 +34,9 @@ def str2file(filename, contents):
str2file("soc.v", src_verilog)
str2file("soc.ucf", src_ucf)
verilog_sources.append("build/soc.v")
+
#raise SystemExit
+
# xst
xst_prj = ""
for s in verilog_sources:
36 constraints.py
View
@@ -1,8 +1,9 @@
-def get(ns, crg0, norflash0, uart0):
+def get(ns, crg0, norflash0, uart0, ddrphy0):
constraints = []
def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""):
constraints.append((ns.get_name(signal), vec, pin, iostandard, extra))
def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
+ assert(signal.bv.width == len(pins))
i = 0
for p in pins:
add(signal, p, i, iostandard, extra)
@@ -12,7 +13,7 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
add(crg0.ac97_rst_n, "D6")
add(crg0.videoin_rst_n, "W17")
add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8")
- add(crg0.rd_clk_lb, "K5")
+ add(crg0.rd_clk_lb, "K5", extra="IOSTANDARD = SSTL2_I")
add(crg0.trigger_reset, "AA4")
add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
@@ -21,7 +22,7 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
extra="SLEW = FAST | DRIVE = 8")
add_vec(norflash0.d, ["AA20", "U14", "U13", "AA6", "AB6", "W4", "Y4", "Y7",
"AA2", "AB2", "V15", "AA18", "AB18", "Y13", "AA12", "AB12"],
- extra = "SLEW = FAST | DRIVE = 8 | PULLDOWN")
+ extra="SLEW = FAST | DRIVE = 8 | PULLDOWN")
add(norflash0.oe_n, "M22", extra="SLEW = FAST | DRIVE = 8")
add(norflash0.we_n, "N20", extra="SLEW = FAST | DRIVE = 8")
add(norflash0.ce_n, "M21", extra="SLEW = FAST | DRIVE = 8")
@@ -29,6 +30,24 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
add(uart0.tx, "L17", extra="SLEW = SLOW")
add(uart0.rx, "K18", extra="PULLUP")
+ ddrsettings = "IOSTANDARD = SSTL2_I"
+ add(ddrphy0.sd_clk_out_p, "M3", extra=ddrsettings)
+ add(ddrphy0.sd_clk_out_n, "L4", extra=ddrsettings)
+ add_vec(ddrphy0.sd_a, ["B1", "B2", "H8", "J7", "E4", "D5", "K7", "F5",
+ "G6", "C1", "C3", "D1", "D2"], extra=ddrsettings)
+ add_vec(ddrphy0.sd_ba, ["A2", "E6"], extra=ddrsettings)
+ add(ddrphy0.sd_cs_n, "F7", extra=ddrsettings)
+ add(ddrphy0.sd_cke, "G7", extra=ddrsettings)
+ add(ddrphy0.sd_ras_n, "E5", extra=ddrsettings)
+ add(ddrphy0.sd_cas_n, "C4", extra=ddrsettings)
+ add(ddrphy0.sd_we_n, "D3", extra=ddrsettings)
+ add_vec(ddrphy0.sd_dq, ["Y2", "W3", "W1", "P8", "P7", "P6", "P5", "T4", "T3",
+ "U4", "V3", "N6", "N7", "M7", "M8", "R4", "P4", "M6", "L6", "P3", "N4",
+ "M5", "V2", "V1", "U3", "U1", "T2", "T1", "R3", "R1", "P2", "P1"],
+ extra=ddrsettings)
+ add_vec(ddrphy0.sd_dm, ["E1", "E3", "F3", "G4"], extra=ddrsettings)
+ add_vec(ddrphy0.sd_dqs, ["F1", "F2", "H5", "H6"], extra=ddrsettings)
+
r = ""
for c in constraints:
r += "NET \"" + c[0]
@@ -42,6 +61,15 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
r += """
TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%;
- """
+INST "spartan6_soft_phy/datapath_s6_inst/dq_idelay_cal_inst/max_tap_drp" LOC = "IODELAY_X0Y79"; # use sd_dm[0] at E1
+INST "m1crg/wr_bufpll_left" LOC = "BUFPLL_X0Y2";
+INST "m1crg/wr_bufpll_right" LOC = "BUFPLL_X2Y2";
+INST "m1crg/rd_bufpll_left" LOC = "BUFPLL_X0Y3";
+INST "m1crg/rd_bufpll_right" LOC = "BUFPLL_X2Y3";
+
+# MAP (13.4) hallucinates that this placement is unroutable. Tell it to STFU.
+PIN "m1crg/rd_bufpll_left.IOCLK" CLOCK_DEDICATED_ROUTE = FALSE;
+PIN "spartan6_soft_phy/datapath_s6_inst/dq_idelay_cal_inst/max_tap_drp.IOCLK0" CLOCK_DEDICATED_ROUTE = FALSE;
+"""
return r
2  milkymist/m1crg/__init__.py
View
@@ -23,7 +23,7 @@ def __init__(self, infreq, outfreq1x):
"clk4x_rd_strb_left",
"clk4x_rd_right",
"clk4x_rd_strb_right"
- ]:
+ ]:
s = Signal(name=name)
setattr(self, name, s)
generated.append((name, s))
104 milkymist/s6ddrphy/__init__.py
View
@@ -0,0 +1,104 @@
+from migen.fhdl.structure import *
+from migen.bus import dfi
+
+class S6DDRPHY:
+ def __init__(self, a, ba, d):
+ ins = []
+ outs = []
+ inouts = []
+
+ for name in [
+ "clk2x_90",
+ "clk4x_wr_left",
+ "clk4x_wr_strb_left",
+ "clk4x_wr_right",
+ "clk4x_wr_strb_right",
+ "clk4x_rd_left",
+ "clk4x_rd_strb_left",
+ "clk4x_rd_right",
+ "clk4x_rd_strb_right",
+ "reset_n"
+ ]:
+ s = Signal(name=name)
+ setattr(self, name, s)
+ ins.append((name, s))
+
+ self._sd_pins = []
+ sd_d = d//4
+ for name, width, l in [
+ ("sd_clk_out_p", 1, outs),
+ ("sd_clk_out_n", 1, outs),
+ ("sd_a", a, outs),
+ ("sd_ba", ba, outs),
+ ("sd_cs_n", 1, outs),
+ ("sd_cke", 1, outs),
+ ("sd_ras_n", 1, outs),
+ ("sd_cas_n", 1, outs),
+ ("sd_we_n", 1, outs),
+ ("sd_dq", sd_d, inouts),
+ ("sd_dm", sd_d//8, outs),
+ ("sd_dqs", sd_d//8, inouts)
+
+ ]:
+ s = Signal(BV(width), name=name)
+ setattr(self, name, s)
+ l.append((name, s))
+ self._sd_pins.append(s)
+
+ self.dfi = dfi.Interface(a, ba, d)
+ ins += self.dfi.get_standard_names(True, False)
+ outs += self.dfi.get_standard_names(False, True)
+
+ ins += [
+ ("cfg_al", BV(3)),
+ ("cfg_cl", BV(3)),
+ ("cfg_bl", BV(2)),
+ ("cfg_regdimm", BV(1)),
+
+ ("init_done", BV(1)),
+
+ ("cpg_busy", BV(1)),
+
+ ("diag_dq_recal", BV(1)),
+ ("diag_io_sel", BV(9)),
+ ("diag_disable_cal_on_startup", BV(1)),
+ ("diag_cal_bits", BV(2)),
+ ("diag_short_cal", BV(1))
+ ]
+ outs += [
+ ("phy_cal_done", BV(1)),
+
+ ("cpg_r_req", BV(1)),
+ ("cpg_w_req", BV(1)),
+ ("cpg_addr", BV(a)),
+ ("cpg_b_size", BV(4))
+ ]
+
+ self._inst = Instance("spartan6_soft_phy",
+ outs,
+ ins,
+ inouts,
+ [
+ ("DSIZE", d),
+ ("NUM_AD", a),
+ ("NUM_BA", ba),
+ ("ADDR_WIDTH", 31),
+ ("DQ_IO_LOC", Constant(2**32-1, BV(32))),
+ ("DM_IO_LOC", Constant(2**4-1, BV(4)))
+ ],
+ clkport="clk")
+
+ def get_fragment(self):
+ comb = [
+ self._inst.ins["cfg_al"].eq(0),
+ self._inst.ins["cfg_cl"].eq(3),
+ self._inst.ins["cfg_bl"].eq(1),
+ self._inst.ins["cfg_regdimm"].eq(0),
+
+ self._inst.ins["diag_dq_recal"].eq(0),
+ 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)
+ ]
+ return Fragment(comb, instances=[self._inst], pads=set(self._sd_pins))
23 top.py
View
@@ -4,7 +4,7 @@
from migen.fhdl import verilog, autofragment
from migen.bus import wishbone, asmibus, wishbone2asmi, csr, wishbone2csr
-from milkymist import m1crg, lm32, norflash, uart, sram#, s6ddrphy
+from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy
import constraints
MHz = 1000000
@@ -12,11 +12,26 @@
sram_size = 4096 # in bytes
l2_size = 8192 # in bytes
+def ddrphy_clocking(crg, phy):
+ names = [
+ "clk2x_90",
+ "clk4x_wr_left",
+ "clk4x_wr_strb_left",
+ "clk4x_wr_right",
+ "clk4x_wr_strb_right",
+ "clk4x_rd_left",
+ "clk4x_rd_strb_left",
+ "clk4x_rd_right",
+ "clk4x_rd_strb_right",
+ ]
+ comb = [getattr(phy, name).eq(getattr(crg, name)) for name in names]
+ return Fragment(comb)
+
def get():
#
# ASMI
#
- #ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128)
+ ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128)
asmihub0 = asmibus.Hub(23, 128, 12) # TODO: get hub from memory controller
asmiport_wb = asmihub0.get_port()
asmihub0.finalize()
@@ -67,12 +82,12 @@ def get():
#
crg0 = m1crg.M1CRG(50*MHz, clk_freq)
- frag = autofragment.from_local() + interrupts
+ frag = autofragment.from_local() + interrupts + ddrphy_clocking(crg0, ddrphy0)
src_verilog, vns = verilog.convert(frag,
{crg0.trigger_reset},
name="soc",
clk_signal=crg0.sys_clk,
rst_signal=crg0.sys_rst,
return_ns=True)
- src_ucf = constraints.get(vns, crg0, norflash0, uart0)
+ src_ucf = constraints.get(vns, crg0, norflash0, uart0, ddrphy0)
return (src_verilog, src_ucf)
Please sign in to comment.
Something went wrong with that request. Please try again.