Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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 authored February 17, 2012
9  build.py
@@ -4,13 +4,16 @@
4 4
 # list Verilog sources before changing directory
5 5
 verilog_sources = []
6 6
 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":
9 11
 			verilog_sources.append(os.path.join(root, f))
10 12
 def add_core_files(d, files):
11 13
 	for f in files:
12 14
 		verilog_sources.append(os.path.join("verilog", d, f))
13 15
 add_core_dir("m1crg")
  16
+add_core_dir("s6ddrphy")
14 17
 add_core_files("lm32", ["lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
15 18
 	"lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
16 19
 	"lm32_shifter.v", "lm32_multiplier_spartan6.v", "lm32_mc_arithmetic.v",
@@ -31,7 +34,9 @@ def str2file(filename, contents):
31 34
 str2file("soc.v", src_verilog)
32 35
 str2file("soc.ucf", src_ucf)
33 36
 verilog_sources.append("build/soc.v")
  37
+
34 38
 #raise SystemExit
  39
+
35 40
 # xst
36 41
 xst_prj = ""
37 42
 for s in verilog_sources:
36  constraints.py
... ...
@@ -1,8 +1,9 @@
1  
-def get(ns, crg0, norflash0, uart0):
  1
+def get(ns, crg0, norflash0, uart0, ddrphy0):
2 2
 	constraints = []
3 3
 	def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""):
4 4
 		constraints.append((ns.get_name(signal), vec, pin, iostandard, extra))
5 5
 	def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
  6
+		assert(signal.bv.width == len(pins))
6 7
 		i = 0
7 8
 		for p in pins:
8 9
 			add(signal, p, i, iostandard, extra)
@@ -12,7 +13,7 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
12 13
 	add(crg0.ac97_rst_n, "D6")
13 14
 	add(crg0.videoin_rst_n, "W17")
14 15
 	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")
16 17
 	add(crg0.trigger_reset, "AA4")
17 18
 	
18 19
 	add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
@@ -21,7 +22,7 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
21 22
 		extra="SLEW = FAST | DRIVE = 8")
22 23
 	add_vec(norflash0.d, ["AA20", "U14", "U13", "AA6", "AB6", "W4", "Y4", "Y7",
23 24
 		"AA2", "AB2", "V15", "AA18", "AB18", "Y13", "AA12", "AB12"],
24  
-		extra = "SLEW = FAST | DRIVE = 8 | PULLDOWN")
  25
+		extra="SLEW = FAST | DRIVE = 8 | PULLDOWN")
25 26
 	add(norflash0.oe_n, "M22", extra="SLEW = FAST | DRIVE = 8")
26 27
 	add(norflash0.we_n, "N20", extra="SLEW = FAST | DRIVE = 8")
27 28
 	add(norflash0.ce_n, "M21", extra="SLEW = FAST | DRIVE = 8")
@@ -29,6 +30,24 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
29 30
 	add(uart0.tx, "L17", extra="SLEW = SLOW")
30 31
 	add(uart0.rx, "K18", extra="PULLUP")
31 32
 	
  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
+	
32 51
 	r = ""
33 52
 	for c in constraints:
34 53
 		r += "NET \"" + c[0]
@@ -42,6 +61,15 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
42 61
 	
43 62
 	r += """
44 63
 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
+"""
46 74
 	
47 75
 	return r
2  milkymist/m1crg/__init__.py
@@ -23,7 +23,7 @@ def __init__(self, infreq, outfreq1x):
23 23
 			"clk4x_rd_strb_left",
24 24
 			"clk4x_rd_right",
25 25
 			"clk4x_rd_strb_right"
26  
-		  ]:
  26
+		]:
27 27
 			s = Signal(name=name)
28 28
 			setattr(self, name, s)
29 29
 			generated.append((name, s))  
104  milkymist/s6ddrphy/__init__.py
... ...
@@ -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))
23  top.py
@@ -4,7 +4,7 @@
4 4
 from migen.fhdl import verilog, autofragment
5 5
 from migen.bus import wishbone, asmibus, wishbone2asmi, csr, wishbone2csr
6 6
 
7  
-from milkymist import m1crg, lm32, norflash, uart, sram#, s6ddrphy
  7
+from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy
8 8
 import constraints
9 9
 
10 10
 MHz = 1000000
@@ -12,11 +12,26 @@
12 12
 sram_size = 4096 # in bytes
13 13
 l2_size = 8192 # in bytes
14 14
 
  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
+
15 30
 def get():
16 31
 	#
17 32
 	# ASMI
18 33
 	#
19  
-	#ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128)
  34
+	ddrphy0 = s6ddrphy.S6DDRPHY(13, 2, 128)
20 35
 	asmihub0 = asmibus.Hub(23, 128, 12) # TODO: get hub from memory controller
21 36
 	asmiport_wb = asmihub0.get_port()
22 37
 	asmihub0.finalize()
@@ -67,12 +82,12 @@ def get():
67 82
 	#
68 83
 	crg0 = m1crg.M1CRG(50*MHz, clk_freq)
69 84
 	
70  
-	frag = autofragment.from_local() + interrupts
  85
+	frag = autofragment.from_local() + interrupts + ddrphy_clocking(crg0, ddrphy0)
71 86
 	src_verilog, vns = verilog.convert(frag,
72 87
 		{crg0.trigger_reset},
73 88
 		name="soc",
74 89
 		clk_signal=crg0.sys_clk,
75 90
 		rst_signal=crg0.sys_rst,
76 91
 		return_ns=True)
77  
-	src_ucf = constraints.get(vns, crg0, norflash0, uart0)
  92
+	src_ucf = constraints.get(vns, crg0, norflash0, uart0, ddrphy0)
78 93
 	return (src_verilog, src_ucf)

0 notes on commit 5d1dad5

Please sign in to comment.
Something went wrong with that request. Please try again.