Skip to content

Commit 5d1dad5

Browse files
author
Sebastien Bourdeauducq
committedFeb 17, 2012
Connect DDR PHY
Doesn't do much for the moment, just to check synthesis/P&R.
1 parent cdd58e0 commit 5d1dad5

File tree

5 files changed

+163
-11
lines changed

5 files changed

+163
-11
lines changed
 

‎build.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
# list Verilog sources before changing directory
55
verilog_sources = []
66
def add_core_dir(d):
7-
for root, subFolders, files in os.walk(os.path.join("verilog", d)):
8-
for f in files:
7+
root = os.path.join("verilog", d)
8+
files = os.listdir(root)
9+
for f in files:
10+
if f[-2:] == ".v":
911
verilog_sources.append(os.path.join(root, f))
1012
def add_core_files(d, files):
1113
for f in files:
1214
verilog_sources.append(os.path.join("verilog", d, f))
1315
add_core_dir("m1crg")
16+
add_core_dir("s6ddrphy")
1417
add_core_files("lm32", ["lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
1518
"lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
1619
"lm32_shifter.v", "lm32_multiplier_spartan6.v", "lm32_mc_arithmetic.v",
@@ -31,7 +34,9 @@ def str2file(filename, contents):
3134
str2file("soc.v", src_verilog)
3235
str2file("soc.ucf", src_ucf)
3336
verilog_sources.append("build/soc.v")
37+
3438
#raise SystemExit
39+
3540
# xst
3641
xst_prj = ""
3742
for s in verilog_sources:

‎constraints.py

+32-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
def get(ns, crg0, norflash0, uart0):
1+
def get(ns, crg0, norflash0, uart0, ddrphy0):
22
constraints = []
33
def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""):
44
constraints.append((ns.get_name(signal), vec, pin, iostandard, extra))
55
def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
6+
assert(signal.bv.width == len(pins))
67
i = 0
78
for p in pins:
89
add(signal, p, i, iostandard, extra)
@@ -12,7 +13,7 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
1213
add(crg0.ac97_rst_n, "D6")
1314
add(crg0.videoin_rst_n, "W17")
1415
add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8")
15-
add(crg0.rd_clk_lb, "K5")
16+
add(crg0.rd_clk_lb, "K5", extra="IOSTANDARD = SSTL2_I")
1617
add(crg0.trigger_reset, "AA4")
1718

1819
add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
@@ -21,14 +22,32 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
2122
extra="SLEW = FAST | DRIVE = 8")
2223
add_vec(norflash0.d, ["AA20", "U14", "U13", "AA6", "AB6", "W4", "Y4", "Y7",
2324
"AA2", "AB2", "V15", "AA18", "AB18", "Y13", "AA12", "AB12"],
24-
extra = "SLEW = FAST | DRIVE = 8 | PULLDOWN")
25+
extra="SLEW = FAST | DRIVE = 8 | PULLDOWN")
2526
add(norflash0.oe_n, "M22", extra="SLEW = FAST | DRIVE = 8")
2627
add(norflash0.we_n, "N20", extra="SLEW = FAST | DRIVE = 8")
2728
add(norflash0.ce_n, "M21", extra="SLEW = FAST | DRIVE = 8")
2829

2930
add(uart0.tx, "L17", extra="SLEW = SLOW")
3031
add(uart0.rx, "K18", extra="PULLUP")
3132

33+
ddrsettings = "IOSTANDARD = SSTL2_I"
34+
add(ddrphy0.sd_clk_out_p, "M3", extra=ddrsettings)
35+
add(ddrphy0.sd_clk_out_n, "L4", extra=ddrsettings)
36+
add_vec(ddrphy0.sd_a, ["B1", "B2", "H8", "J7", "E4", "D5", "K7", "F5",
37+
"G6", "C1", "C3", "D1", "D2"], extra=ddrsettings)
38+
add_vec(ddrphy0.sd_ba, ["A2", "E6"], extra=ddrsettings)
39+
add(ddrphy0.sd_cs_n, "F7", extra=ddrsettings)
40+
add(ddrphy0.sd_cke, "G7", extra=ddrsettings)
41+
add(ddrphy0.sd_ras_n, "E5", extra=ddrsettings)
42+
add(ddrphy0.sd_cas_n, "C4", extra=ddrsettings)
43+
add(ddrphy0.sd_we_n, "D3", extra=ddrsettings)
44+
add_vec(ddrphy0.sd_dq, ["Y2", "W3", "W1", "P8", "P7", "P6", "P5", "T4", "T3",
45+
"U4", "V3", "N6", "N7", "M7", "M8", "R4", "P4", "M6", "L6", "P3", "N4",
46+
"M5", "V2", "V1", "U3", "U1", "T2", "T1", "R3", "R1", "P2", "P1"],
47+
extra=ddrsettings)
48+
add_vec(ddrphy0.sd_dm, ["E1", "E3", "F3", "G4"], extra=ddrsettings)
49+
add_vec(ddrphy0.sd_dqs, ["F1", "F2", "H5", "H6"], extra=ddrsettings)
50+
3251
r = ""
3352
for c in constraints:
3453
r += "NET \"" + c[0]
@@ -42,6 +61,15 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
4261

4362
r += """
4463
TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%;
45-
"""
64+
INST "spartan6_soft_phy/datapath_s6_inst/dq_idelay_cal_inst/max_tap_drp" LOC = "IODELAY_X0Y79"; # use sd_dm[0] at E1
65+
INST "m1crg/wr_bufpll_left" LOC = "BUFPLL_X0Y2";
66+
INST "m1crg/wr_bufpll_right" LOC = "BUFPLL_X2Y2";
67+
INST "m1crg/rd_bufpll_left" LOC = "BUFPLL_X0Y3";
68+
INST "m1crg/rd_bufpll_right" LOC = "BUFPLL_X2Y3";
69+
70+
# MAP (13.4) hallucinates that this placement is unroutable. Tell it to STFU.
71+
PIN "m1crg/rd_bufpll_left.IOCLK" CLOCK_DEDICATED_ROUTE = FALSE;
72+
PIN "spartan6_soft_phy/datapath_s6_inst/dq_idelay_cal_inst/max_tap_drp.IOCLK0" CLOCK_DEDICATED_ROUTE = FALSE;
73+
"""
4674

4775
return r

‎milkymist/m1crg/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __init__(self, infreq, outfreq1x):
2323
"clk4x_rd_strb_left",
2424
"clk4x_rd_right",
2525
"clk4x_rd_strb_right"
26-
]:
26+
]:
2727
s = Signal(name=name)
2828
setattr(self, name, s)
2929
generated.append((name, s))

‎milkymist/s6ddrphy/__init__.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from migen.fhdl.structure import *
2+
from migen.bus import dfi
3+
4+
class S6DDRPHY:
5+
def __init__(self, a, ba, d):
6+
ins = []
7+
outs = []
8+
inouts = []
9+
10+
for name in [
11+
"clk2x_90",
12+
"clk4x_wr_left",
13+
"clk4x_wr_strb_left",
14+
"clk4x_wr_right",
15+
"clk4x_wr_strb_right",
16+
"clk4x_rd_left",
17+
"clk4x_rd_strb_left",
18+
"clk4x_rd_right",
19+
"clk4x_rd_strb_right",
20+
"reset_n"
21+
]:
22+
s = Signal(name=name)
23+
setattr(self, name, s)
24+
ins.append((name, s))
25+
26+
self._sd_pins = []
27+
sd_d = d//4
28+
for name, width, l in [
29+
("sd_clk_out_p", 1, outs),
30+
("sd_clk_out_n", 1, outs),
31+
("sd_a", a, outs),
32+
("sd_ba", ba, outs),
33+
("sd_cs_n", 1, outs),
34+
("sd_cke", 1, outs),
35+
("sd_ras_n", 1, outs),
36+
("sd_cas_n", 1, outs),
37+
("sd_we_n", 1, outs),
38+
("sd_dq", sd_d, inouts),
39+
("sd_dm", sd_d//8, outs),
40+
("sd_dqs", sd_d//8, inouts)
41+
42+
]:
43+
s = Signal(BV(width), name=name)
44+
setattr(self, name, s)
45+
l.append((name, s))
46+
self._sd_pins.append(s)
47+
48+
self.dfi = dfi.Interface(a, ba, d)
49+
ins += self.dfi.get_standard_names(True, False)
50+
outs += self.dfi.get_standard_names(False, True)
51+
52+
ins += [
53+
("cfg_al", BV(3)),
54+
("cfg_cl", BV(3)),
55+
("cfg_bl", BV(2)),
56+
("cfg_regdimm", BV(1)),
57+
58+
("init_done", BV(1)),
59+
60+
("cpg_busy", BV(1)),
61+
62+
("diag_dq_recal", BV(1)),
63+
("diag_io_sel", BV(9)),
64+
("diag_disable_cal_on_startup", BV(1)),
65+
("diag_cal_bits", BV(2)),
66+
("diag_short_cal", BV(1))
67+
]
68+
outs += [
69+
("phy_cal_done", BV(1)),
70+
71+
("cpg_r_req", BV(1)),
72+
("cpg_w_req", BV(1)),
73+
("cpg_addr", BV(a)),
74+
("cpg_b_size", BV(4))
75+
]
76+
77+
self._inst = Instance("spartan6_soft_phy",
78+
outs,
79+
ins,
80+
inouts,
81+
[
82+
("DSIZE", d),
83+
("NUM_AD", a),
84+
("NUM_BA", ba),
85+
("ADDR_WIDTH", 31),
86+
("DQ_IO_LOC", Constant(2**32-1, BV(32))),
87+
("DM_IO_LOC", Constant(2**4-1, BV(4)))
88+
],
89+
clkport="clk")
90+
91+
def get_fragment(self):
92+
comb = [
93+
self._inst.ins["cfg_al"].eq(0),
94+
self._inst.ins["cfg_cl"].eq(3),
95+
self._inst.ins["cfg_bl"].eq(1),
96+
self._inst.ins["cfg_regdimm"].eq(0),
97+
98+
self._inst.ins["diag_dq_recal"].eq(0),
99+
self._inst.ins["diag_io_sel"].eq(0),
100+
self._inst.ins["diag_disable_cal_on_startup"].eq(0),
101+
self._inst.ins["diag_cal_bits"].eq(0),
102+
self._inst.ins["diag_short_cal"].eq(0)
103+
]
104+
return Fragment(comb, instances=[self._inst], pads=set(self._sd_pins))

‎top.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,34 @@
44
from migen.fhdl import verilog, autofragment
55
from migen.bus import wishbone, asmibus, wishbone2asmi, csr, wishbone2csr
66

7-
from milkymist import m1crg, lm32, norflash, uart, sram#, s6ddrphy
7+
from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy
88
import constraints
99

1010
MHz = 1000000
1111
clk_freq = (83 + Fraction(1, 3))*MHz
1212
sram_size = 4096 # in bytes
1313
l2_size = 8192 # in bytes
1414

15+
def ddrphy_clocking(crg, phy):
16+
names = [
17+
"clk2x_90",
18+
"clk4x_wr_left",
19+
"clk4x_wr_strb_left",
20+
"clk4x_wr_right",
21+
"clk4x_wr_strb_right",
22+
"clk4x_rd_left",
23+
"clk4x_rd_strb_left",
24+
"clk4x_rd_right",
25+
"clk4x_rd_strb_right",
26+
]
27+
comb = [getattr(phy, name).eq(getattr(crg, name)) for name in names]
28+
return Fragment(comb)
29+
1530
def get():
1631
#
1732
# ASMI
1833
#
19-
#ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128)
34+
ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128)
2035
asmihub0 = asmibus.Hub(23, 128, 12) # TODO: get hub from memory controller
2136
asmiport_wb = asmihub0.get_port()
2237
asmihub0.finalize()
@@ -67,12 +82,12 @@ def get():
6782
#
6883
crg0 = m1crg.M1CRG(50*MHz, clk_freq)
6984

70-
frag = autofragment.from_local() + interrupts
85+
frag = autofragment.from_local() + interrupts + ddrphy_clocking(crg0, ddrphy0)
7186
src_verilog, vns = verilog.convert(frag,
7287
{crg0.trigger_reset},
7388
name="soc",
7489
clk_signal=crg0.sys_clk,
7590
rst_signal=crg0.sys_rst,
7691
return_ns=True)
77-
src_ucf = constraints.get(vns, crg0, norflash0, uart0)
92+
src_ucf = constraints.get(vns, crg0, norflash0, uart0, ddrphy0)
7893
return (src_verilog, src_ucf)

0 commit comments

Comments
 (0)
Please sign in to comment.