Connect DDR PHY

Doesn't do much for the moment, just to check synthesis/P&R.
This commit is contained in:
Sebastien Bourdeauducq 2012-02-17 11:04:44 +01:00
parent cdd58e023b
commit 5d1dad583b
5 changed files with 163 additions and 11 deletions

View File

@ -4,13 +4,16 @@ import top
# list Verilog sources before changing directory # list Verilog sources before changing directory
verilog_sources = [] verilog_sources = []
def add_core_dir(d): def add_core_dir(d):
for root, subFolders, files in os.walk(os.path.join("verilog", d)): root = os.path.join("verilog", d)
files = os.listdir(root)
for f in files: for f in files:
if f[-2:] == ".v":
verilog_sources.append(os.path.join(root, f)) verilog_sources.append(os.path.join(root, f))
def add_core_files(d, files): def add_core_files(d, files):
for f in files: for f in files:
verilog_sources.append(os.path.join("verilog", d, f)) verilog_sources.append(os.path.join("verilog", d, f))
add_core_dir("m1crg") add_core_dir("m1crg")
add_core_dir("s6ddrphy")
add_core_files("lm32", ["lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v", 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_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", "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.v", src_verilog)
str2file("soc.ucf", src_ucf) str2file("soc.ucf", src_ucf)
verilog_sources.append("build/soc.v") verilog_sources.append("build/soc.v")
#raise SystemExit #raise SystemExit
# xst # xst
xst_prj = "" xst_prj = ""
for s in verilog_sources: for s in verilog_sources:

View File

@ -1,8 +1,9 @@
def get(ns, crg0, norflash0, uart0): def get(ns, crg0, norflash0, uart0, ddrphy0):
constraints = [] constraints = []
def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""): def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""):
constraints.append((ns.get_name(signal), vec, pin, iostandard, extra)) constraints.append((ns.get_name(signal), vec, pin, iostandard, extra))
def add_vec(signal, pins, iostandard="LVCMOS33", extra=""): def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
assert(signal.bv.width == len(pins))
i = 0 i = 0
for p in pins: for p in pins:
add(signal, p, i, iostandard, extra) add(signal, p, i, iostandard, extra)
@ -12,7 +13,7 @@ def get(ns, crg0, norflash0, uart0):
add(crg0.ac97_rst_n, "D6") add(crg0.ac97_rst_n, "D6")
add(crg0.videoin_rst_n, "W17") add(crg0.videoin_rst_n, "W17")
add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8") 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(crg0.trigger_reset, "AA4")
add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22", add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
@ -29,6 +30,24 @@ def get(ns, crg0, norflash0, uart0):
add(uart0.tx, "L17", extra="SLEW = SLOW") add(uart0.tx, "L17", extra="SLEW = SLOW")
add(uart0.rx, "K18", extra="PULLUP") 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 = "" r = ""
for c in constraints: for c in constraints:
r += "NET \"" + c[0] r += "NET \"" + c[0]
@ -42,6 +61,15 @@ def get(ns, crg0, norflash0, uart0):
r += """ r += """
TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%; 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 return r

View File

@ -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 File

@ -4,7 +4,7 @@ from migen.fhdl.structure import *
from migen.fhdl import verilog, autofragment from migen.fhdl import verilog, autofragment
from migen.bus import wishbone, asmibus, wishbone2asmi, csr, wishbone2csr 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 import constraints
MHz = 1000000 MHz = 1000000
@ -12,11 +12,26 @@ clk_freq = (83 + Fraction(1, 3))*MHz
sram_size = 4096 # in bytes sram_size = 4096 # in bytes
l2_size = 8192 # 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(): def get():
# #
# ASMI # 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 asmihub0 = asmibus.Hub(23, 128, 12) # TODO: get hub from memory controller
asmiport_wb = asmihub0.get_port() asmiport_wb = asmihub0.get_port()
asmihub0.finalize() asmihub0.finalize()
@ -67,12 +82,12 @@ def get():
# #
crg0 = m1crg.M1CRG(50*MHz, clk_freq) 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, src_verilog, vns = verilog.convert(frag,
{crg0.trigger_reset}, {crg0.trigger_reset},
name="soc", name="soc",
clk_signal=crg0.sys_clk, clk_signal=crg0.sys_clk,
rst_signal=crg0.sys_rst, rst_signal=crg0.sys_rst,
return_ns=True) 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) return (src_verilog, src_ucf)