Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Prepare for new DDR PHY

  • Loading branch information...
commit f35cd4a85bec00f364779314f7d7a8ed277cc628 1 parent 1e4e092
Sébastien Bourdeauducq authored
2  .gitignore
@@ -6,5 +6,3 @@ build/*
6 6
 tools/bin2hex
7 7
 tools/flterm
8 8
 tools/mkmmimg
9  
-verilog/s6ddrphy/*.v
10  
-verilog/s6ddrphy/.pc
2  Makefile
@@ -21,7 +21,7 @@ build/soc-routed.ncd: build/soc.ncd
21 21
 	cd build && par -ol high -w soc.ncd soc-routed.ncd
22 22
 
23 23
 build/soc.bit build/soc.bin: build/soc-routed.ncd
24  
-	cd build && bitgen -g Binary:Yes -g INIT_9K:Yes -w soc-routed.ncd soc.bit
  24
+	cd build && bitgen -g LCK_cycle:6 -g Binary:Yes -g INIT_9K:Yes -w soc-routed.ncd soc.bit
25 25
 
26 26
 load: build/soc.bit
27 27
 	jtag -n load.jtag
19  README
@@ -19,22 +19,6 @@ production version of Milkymist SoC, visit:
19 19
 First, download and install Migen from:
20 20
   https://github.com/milkymist/migen
21 21
 
22  
-Then, you will need to fetch the "Spartan-6 FPGA DDR/DDR2 SDRAM PHY core"
23  
-(PHY only solution, we do not need the NWL memory controller) from:
24  
-  http://www.xilinx.com/products/intellectual-property/1-1MFEDB.htm
25  
-Downloading it is free of charge, but it cannot be redistributed in
26  
-source form due to copyright restrictions.
27  
-
28  
-Place the Verilog source code of the PHY (contents of
29  
-phy_rtl/spartan6_soft_phy) into the verilog/s6ddrphy folder.
30  
-Then run (from verilog/s6ddrphy):
31  
-  quilt push -a
32  
-in order to apply patches that make the PHY more compliant with the DFI
33  
-specification in general, and in particular with the capability to send
34  
-multiple SDRAM commands in one system clock cycle, which our new SDRAM
35  
-controller is capable of doing.
36  
-The patches are against version 1.04 of the PHY.
37  
-
38 22
 Once this is done, build the bitstream with:
39 23
   python3 build.py
40 24
 This will generate the build/soc.bit programming file.
@@ -67,8 +51,7 @@ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
67 51
 PARTICULAR PURPOSE. See the GNU General Public License for more details.
68 52
 
69 53
 The authors grant the additional permissions that the code can be used in
70  
-conjunction with the LatticeMico32 CPU core from Lattice and the
71  
-Spartan-6 FPGA DDR/DDR2 SDRAM PHY core from Xilinx and Northwest Logic.
  54
+conjunction with the LatticeMico32 CPU core from Lattice.
72 55
 
73 56
 Unless otherwise noted, Milkymist-NG's source code is copyright (C)
74 57
 2011-2012 Sebastien Bourdeauducq. Other authors retain ownership of their
12  constraints.py
@@ -13,7 +13,6 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
13 13
 	add(crg0.ac97_rst_n, "D6")
14 14
 	add(crg0.videoin_rst_n, "W17")
15 15
 	add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8")
16  
-	add(crg0.rd_clk_lb, "K5", extra="IOSTANDARD = SSTL2_I")
17 16
 	add(crg0.trigger_reset, "AA4")
18 17
 	
19 18
 	add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
@@ -61,15 +60,8 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
61 60
 	
62 61
 	r += """
63 62
 TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%;
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;
  63
+INST "m1crg/wr_bufpll" LOC = "BUFPLL_X0Y2";
  64
+INST "m1crg/rd_bufpll" LOC = "BUFPLL_X0Y3";
73 65
 """
74 66
 	
75 67
 	return r
21  milkymist/m1crg/__init__.py
@@ -15,21 +15,15 @@ def __init__(self, infreq, outfreq1x):
15 15
 			"videoin_rst_n",
16 16
 			"flash_rst_n",
17 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"
  18
+			"clk4x_wr",
  19
+			"clk4x_wr_strb",
  20
+			"clk4x_rd",
  21
+			"clk4x_rd_strb"
26 22
 		]:
27 23
 			s = Signal(name=name)
28 24
 			setattr(self, name, s)
29 25
 			generated.append((name, s))  
30 26
 		
31  
-		self.rd_clk_lb = Signal()
32  
-		
33 27
 		ratio = Fraction(outfreq1x)/Fraction(infreq)
34 28
 		in_period = float(Fraction(1000000000)/Fraction(infreq))
35 29
 		
@@ -38,9 +32,8 @@ def __init__(self, infreq, outfreq1x):
38 32
 			[
39 33
 				("clkin", self.clkin),
40 34
 				("trigger_reset", self.trigger_reset)
41  
-			], [
42  
-				("rd_clk_lb", self.rd_clk_lb)
43  
-			], [
  35
+			],
  36
+			parameters=[
44 37
 				("in_period", in_period),
45 38
 				("f_mult", ratio.numerator),
46 39
 				("f_div", ratio.denominator)
@@ -49,4 +42,4 @@ def __init__(self, infreq, outfreq1x):
49 42
 
50 43
 	def get_fragment(self):
51 44
 		return Fragment(instances=[self._inst],
52  
-			pads={self.clkin, self.ac97_rst_n, self.videoin_rst_n, self.flash_rst_n, self.rd_clk_lb})
  45
+			pads={self.clkin, self.ac97_rst_n, self.videoin_rst_n, self.flash_rst_n})
106  milkymist/s6ddrphy/__init__.py
... ...
@@ -1,31 +1,24 @@
1 1
 from migen.fhdl.structure import *
2 2
 from migen.bus import dfi
3  
-from migen.bank.description import *
4  
-from migen.bank import csrgen
5 3
 
6 4
 class S6DDRPHY:
7  
-	def __init__(self, csr_address, a, ba, d):
  5
+	def __init__(self, a, ba, d):
8 6
 		ins = []
9 7
 		outs = []
10 8
 		inouts = []
11 9
 		
12 10
 		for name in [
13 11
 			"clk2x_90",
14  
-			"clk4x_wr_left",
15  
-			"clk4x_wr_strb_left",
16  
-			"clk4x_wr_right",
17  
-			"clk4x_wr_strb_right",
18  
-			"clk4x_rd_left",
19  
-			"clk4x_rd_strb_left",
20  
-			"clk4x_rd_right",
21  
-			"clk4x_rd_strb_right"
  12
+			"clk4x_wr",
  13
+			"clk4x_wr_strb",
  14
+			"clk4x_rd",
  15
+			"clk4x_rd_strb"
22 16
 		]:
23 17
 			s = Signal(name=name)
24 18
 			setattr(self, name, s)
25 19
 			ins.append((name, s))
26 20
 		
27 21
 		self._sd_pins = []
28  
-		sd_d = d//4
29 22
 		for name, width, l in [
30 23
 			("sd_clk_out_p", 1, outs),
31 24
 			("sd_clk_out_n", 1, outs),
@@ -36,9 +29,9 @@ def __init__(self, csr_address, a, ba, d):
36 29
 			("sd_ras_n", 1, outs),
37 30
 			("sd_cas_n", 1, outs),
38 31
 			("sd_we_n", 1, outs),
39  
-			("sd_dq", sd_d, inouts),
40  
-			("sd_dm", sd_d//8, outs),
41  
-			("sd_dqs", sd_d//8, inouts)
  32
+			("sd_dq", d//2, inouts),
  33
+			("sd_dm", d//16, outs),
  34
+			("sd_dqs", d//16, inouts)
42 35
 			
43 36
 		]:
44 37
 			s = Signal(BV(width), name=name)
@@ -46,93 +39,20 @@ def __init__(self, csr_address, a, ba, d):
46 39
 			l.append((name, s))
47 40
 			self._sd_pins.append(s)
48 41
 		
49  
-		self.dfi = dfi.Interface(a, ba, d)
  42
+		self.dfi = dfi.Interface(a, ba, d, 2)
50 43
 		ins += self.dfi.get_standard_names(True, False)
51 44
 		outs += self.dfi.get_standard_names(False, True)
52 45
 		
53  
-		ins += [
54  
-			("reset_n", BV(1)),
55  
-			
56  
-			("cfg_al", BV(3)),
57  
-			("cfg_cl", BV(3)),
58  
-			("cfg_bl", BV(2)),
59  
-			("cfg_regdimm", BV(1)),
60  
-			
61  
-			("init_done", BV(1)),
62  
-			
63  
-			("cpg_busy", BV(1)),
64  
-			
65  
-			("diag_dq_recal", BV(1)),
66  
-			("diag_io_sel", BV(9)),
67  
-			("diag_disable_cal_on_startup", BV(1)),
68  
-			("diag_cal_bits", BV(2)),
69  
-			("diag_short_cal", BV(1))
70  
-		]
71  
-		outs += [
72  
-			("phy_cal_done", BV(1)),
73  
-			
74  
-			("cpg_r_req", BV(1)),
75  
-			("cpg_w_req", BV(1)),
76  
-			("cpg_addr", BV(a)),
77  
-			("cpg_b_size", BV(4))
78  
-		]
79  
-		
80  
-		self._inst = Instance("spartan6_soft_phy",
  46
+		self._inst = Instance("s6ddrphy",
81 47
 			outs,
82 48
 			ins,
83 49
 			inouts,
84 50
 			[
85  
-				("DSIZE", d),
86 51
 				("NUM_AD", a),
87 52
 				("NUM_BA", ba),
88  
-				("ADDR_WIDTH", 31),
89  
-				("DQ_IO_LOC", Constant(2**32-1, BV(32))),
90  
-				("DM_IO_LOC", Constant(2**4-1, BV(4)))
  53
+				("NUM_D", d)
91 54
 			],
92  
-			clkport="clk")
93  
-		
94  
-		self._reset_n = Field("reset_n")
95  
-		self._init_done = Field("init_done")
96  
-		self._phy_cal_done = Field("phy_cal_done", 1, READ_ONLY, WRITE_ONLY)
97  
-		self._status = RegisterFields("status",
98  
-			[self._reset_n, self._init_done, self._phy_cal_done])
99  
-		self._req = RegisterRaw("req", 2)
100  
-		self._req_addr = RegisterField("req_addr", 8, READ_ONLY, WRITE_ONLY)
101  
-		
102  
-		self.bank = csrgen.Bank([self._status, self._req, self._req_addr],
103  
-			address=csr_address)
  55
+			clkport="sys_clk")
104 56
 
105 57
 	def get_fragment(self):
106  
-		pending_r = Signal()
107  
-		pending_w = Signal()
108  
-		cpg_busy = Signal()
109  
-		
110  
-		comb = [
111  
-			self._inst.ins["cfg_al"].eq(0),
112  
-			self._inst.ins["cfg_cl"].eq(3),
113  
-			self._inst.ins["cfg_bl"].eq(1),
114  
-			self._inst.ins["cfg_regdimm"].eq(0),
115  
-			
116  
-			self._inst.ins["diag_dq_recal"].eq(0),
117  
-			self._inst.ins["diag_io_sel"].eq(0),
118  
-			self._inst.ins["diag_disable_cal_on_startup"].eq(0),
119  
-			self._inst.ins["diag_cal_bits"].eq(0),
120  
-			self._inst.ins["diag_short_cal"].eq(0),
121  
-			
122  
-			self._inst.ins["reset_n"].eq(self._reset_n.r),
123  
-			self._inst.ins["init_done"].eq(self._init_done.r),
124  
-			self._phy_cal_done.w.eq(self._inst.outs["phy_cal_done"]),
125  
-			self._req_addr.field.w.eq(self._inst.outs["cpg_addr"][2:10]),
126  
-			
127  
-			self._req.w.eq(Cat(pending_r, pending_w)),
128  
-			cpg_busy.eq(pending_r | pending_w),
129  
-			self._inst.ins["cpg_busy"].eq(cpg_busy)
130  
-		]
131  
-		sync = [
132  
-			If(self._inst.outs["cpg_r_req"], pending_r.eq(1)),
133  
-			If(self._inst.outs["cpg_w_req"], pending_w.eq(1)),
134  
-			If(self._req.re & self._req.r[0], pending_r.eq(0)),
135  
-			If(self._req.re & self._req.r[1], pending_w.eq(0))
136  
-		]
137  
-		return Fragment(comb, sync, instances=[self._inst], pads=set(self._sd_pins)) \
138  
-			+ self.bank.get_fragment()
  58
+		return Fragment(instances=[self._inst], pads=set(self._sd_pins))
44  software/bios/ddrinit.c
@@ -17,7 +17,6 @@
17 17
 
18 18
 #include <stdio.h>
19 19
 
20  
-#include <hw/s6ddrphy.h>
21 20
 #include <hw/dfii.h>
22 21
 
23 22
 #include "ddrinit.h"
@@ -79,54 +78,11 @@ static void init_sequence(void)
79 78
 	cdelay(200);
80 79
 }
81 80
 
82  
-static void calibrate_phy(void)
83  
-{
84  
-	int requests;
85  
-	int addr;
86  
-	
87  
-	printf("Calibrating PHY...\n");
88  
-	
89  
-	CSR_DFII_WRDELAY = 4;
90  
-	CSR_DFII_WRDURATION = 1;
91  
-	CSR_DFII_RDDELAY = 7;
92  
-	CSR_DFII_RDDURATION = 1;
93  
-	
94  
-	/* Use bank 0, activate row 0 */
95  
-	CSR_DFII_BA = 0;
96  
-	setaddr(0x0000);
97  
-	CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CS;
98  
-	
99  
-	while(!(CSR_DDRPHY_STATUS & DDRPHY_STATUS_PHY_CAL_DONE)) {
100  
-		cdelay(20);
101  
-		requests = CSR_DDRPHY_REQUESTS;
102  
-		addr = CSR_DDRPHY_REQADDR;
103  
-		
104  
-		setaddr(addr << 2);
105  
-		if(requests & DDRPHY_REQUEST_READ) {
106  
-			printf("R %d\n", addr);
107  
-			CSR_DFII_COMMAND = DFII_COMMAND_RDDATA|DFII_COMMAND_CAS|DFII_COMMAND_CS;
108  
-		}
109  
-		if(requests & DDRPHY_REQUEST_WRITE) {
110  
-			printf("W %d\n", addr);
111  
-			CSR_DFII_COMMAND = DFII_COMMAND_WRDATA|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
112  
-		}
113  
-		
114  
-		CSR_DDRPHY_REQUESTS = requests;
115  
-	}
116  
-	
117  
-	/* Precharge All */
118  
-	setaddr(0x0400);
119  
-	CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
120  
-}
121  
-
122 81
 int ddrinit(void)
123 82
 {
124 83
 	printf("Initializing DDR SDRAM...\n");
125 84
 	
126  
-	CSR_DDRPHY_STATUS = DDRPHY_STATUS_RESETN;
127 85
 	init_sequence();
128  
-	CSR_DDRPHY_STATUS = DDRPHY_STATUS_RESETN|DDRPHY_STATUS_INIT_DONE;
129  
-	calibrate_phy();
130 86
 	
131 87
 	return 1;
132 88
 }
16  software/include/hw/dfii.h
@@ -20,7 +20,7 @@
20 20
 
21 21
 #include <hw/common.h>
22 22
 
23  
-#define CSR_DFII_CONTROL		MMPTR(0xe0001000)
  23
+#define CSR_DFII_CONTROL		MMPTR(0xe0000800)
24 24
 
25 25
 #define DFII_CONTROL_SEL		(0x01)
26 26
 #define DFII_CONTROL_CKE		(0x02)
@@ -34,13 +34,13 @@
34 34
 #define DFII_COMMAND_RDDATA		(0x10)
35 35
 #define DFII_COMMAND_WRDATA		(0x20)
36 36
 
37  
-#define CSR_DFII_AH			MMPTR(0xe0001008)
38  
-#define CSR_DFII_AL			MMPTR(0xe000100C)
39  
-#define CSR_DFII_BA			MMPTR(0xe0001010)
  37
+#define CSR_DFII_AH			MMPTR(0xe0000808)
  38
+#define CSR_DFII_AL			MMPTR(0xe000080C)
  39
+#define CSR_DFII_BA			MMPTR(0xe0000810)
40 40
 
41  
-#define CSR_DFII_RDDELAY		MMPTR(0xe0001014)
42  
-#define CSR_DFII_RDDURATION		MMPTR(0xe0001018)
43  
-#define CSR_DFII_WRDELAY		MMPTR(0xe000101C)
44  
-#define CSR_DFII_WRDURATION		MMPTR(0xe0001020)
  41
+#define CSR_DFII_RDDELAY		MMPTR(0xe0000814)
  42
+#define CSR_DFII_RDDURATION		MMPTR(0xe0000818)
  43
+#define CSR_DFII_WRDELAY		MMPTR(0xe000081C)
  44
+#define CSR_DFII_WRDURATION		MMPTR(0xe0000820)
45 45
 
46 46
 #endif /* __HW_DFII_H */
36  software/include/hw/s6ddrphy.h
... ...
@@ -1,36 +0,0 @@
1  
-/*
2  
- * Milkymist SoC (Software)
3  
- * Copyright (C) 2012 Sebastien Bourdeauducq
4  
- *
5  
- * This program is free software: you can redistribute it and/or modify
6  
- * it under the terms of the GNU General Public License as published by
7  
- * the Free Software Foundation, version 3 of the License.
8  
- *
9  
- * This program is distributed in the hope that it will be useful,
10  
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  
- * GNU General Public License for more details.
13  
- *
14  
- * You should have received a copy of the GNU General Public License
15  
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  
- */
17  
-
18  
-#ifndef __HW_S6DDRPHY_H
19  
-#define __HW_S6DDRPHY_H
20  
-
21  
-#include <hw/common.h>
22  
-
23  
-#define CSR_DDRPHY_STATUS		MMPTR(0xe0000800)
24  
-
25  
-#define DDRPHY_STATUS_RESETN		(0x1)
26  
-#define DDRPHY_STATUS_INIT_DONE		(0x2)
27  
-#define DDRPHY_STATUS_PHY_CAL_DONE	(0x4)
28  
-
29  
-#define CSR_DDRPHY_REQUESTS		MMPTR(0xe0000804)
30  
-
31  
-#define DDRPHY_REQUEST_READ		(0x1)
32  
-#define DDRPHY_REQUEST_WRITE		(0x2)
33  
-
34  
-#define CSR_DDRPHY_REQADDR		MMPTR(0xe0000808)
35  
-
36  
-#endif /* __HW_S6DDRPHY_H */
19  top.py
@@ -14,19 +14,15 @@
14 14
 
15 15
 dfi_a = 13
16 16
 dfi_ba = 2
17  
-dfi_d = 128 # TODO -> 64
  17
+dfi_d = 64
18 18
 
19 19
 def ddrphy_clocking(crg, phy):
20 20
 	names = [
21 21
 		"clk2x_90",
22  
-		"clk4x_wr_left",
23  
-		"clk4x_wr_strb_left",
24  
-		"clk4x_wr_right",
25  
-		"clk4x_wr_strb_right",
26  
-		"clk4x_rd_left",
27  
-		"clk4x_rd_strb_left",
28  
-		"clk4x_rd_right",
29  
-		"clk4x_rd_strb_right",
  22
+		"clk4x_wr",
  23
+		"clk4x_wr_strb",
  24
+		"clk4x_rd",
  25
+		"clk4x_rd_strb"
30 26
 	]
31 27
 	comb = [getattr(phy, name).eq(getattr(crg, name)) for name in names]
32 28
 	return Fragment(comb)
@@ -42,8 +38,8 @@ def get():
42 38
 	#
43 39
 	# DFI
44 40
 	#
45  
-	ddrphy0 = s6ddrphy.S6DDRPHY(1, dfi_a, dfi_ba, dfi_d)
46  
-	dfii0 = dfii.DFIInjector(2, dfi_a, dfi_ba, dfi_d, 1)
  41
+	ddrphy0 = s6ddrphy.S6DDRPHY(dfi_a, dfi_ba, dfi_d)
  42
+	dfii0 = dfii.DFIInjector(1, dfi_a, dfi_ba, dfi_d, 2)
47 43
 	dficon0 = dfi.Interconnect(dfii0.master, ddrphy0.dfi)
48 44
 
49 45
 	#
@@ -80,7 +76,6 @@ def get():
80 76
 	uart0 = uart.UART(0, clk_freq, baud=115200)
81 77
 	csrcon0 = csr.Interconnect(wishbone2csr0.csr, [
82 78
 		uart0.bank.interface,
83  
-		ddrphy0.bank.interface,
84 79
 		dfii0.bank.interface
85 80
 	])
86 81
 	
317  verilog/m1crg/m1crg.v
@@ -32,37 +32,25 @@ module m1crg #(
32 32
 	output videoin_rst_n,
33 33
 	output flash_rst_n,
34 34
 	
35  
-	/* DDR PHY clocks and reset */
  35
+	/* DDR PHY clocks */
36 36
 	output clk2x_90,
37  
-	output clk4x_wr_left,
38  
-	output clk4x_wr_strb_left,
39  
-	output clk4x_wr_right,
40  
-	output clk4x_wr_strb_right,
41  
-	output clk4x_rd_left,
42  
-	output clk4x_rd_strb_left,
43  
-	output clk4x_rd_right,
44  
-	output clk4x_rd_strb_right,
45  
-	inout rd_clk_lb /* < unconnected clock pin for read clock PLL loopback */
  37
+	output clk4x_wr,
  38
+	output clk4x_wr_strb,
  39
+	output clk4x_rd,
  40
+	output clk4x_rd_strb
46 41
 );
47 42
 
48 43
 /*
49 44
  * Reset
50 45
  */
51 46
 
52  
-wire reset_n;
53  
-
54 47
 reg [19:0] rst_debounce;
55  
-always @(posedge sys_clk, negedge reset_n) begin
56  
-	if(~reset_n) begin
  48
+always @(posedge sys_clk) begin
  49
+	if(trigger_reset)
57 50
 		rst_debounce <= 20'hFFFFF;
58  
-		sys_rst <= 1'b1;
59  
-	end else begin
60  
-		if(trigger_reset)
61  
-			rst_debounce <= 20'hFFFFF;
62  
-		else if(rst_debounce != 20'd0)
63  
-			rst_debounce <= rst_debounce - 20'd1;
64  
-		sys_rst <= rst_debounce != 20'd0;
65  
-	end
  51
+	else if(rst_debounce != 20'd0)
  52
+		rst_debounce <= rst_debounce - 20'd1;
  53
+	sys_rst <= rst_debounce != 20'd0;
66 54
 end
67 55
 
68 56
 assign ac97_rst_n = ~sys_rst;
@@ -79,23 +67,19 @@ assign videoin_rst_n = ~sys_rst;
79 67
 
80 68
 reg [7:0] flash_rstcounter;
81 69
 
82  
-always @(posedge sys_clk, negedge reset_n) begin
83  
-	if(~reset_n) begin
  70
+always @(posedge sys_clk) begin
  71
+	if(trigger_reset)
84 72
 		flash_rstcounter <= 8'd0;
85  
-	end else begin
86  
-		if(trigger_reset)
87  
-			flash_rstcounter <= 8'd0;
88  
-		else if(~flash_rstcounter[7])
89  
-			flash_rstcounter <= flash_rstcounter + 8'd1;
90  
-	end
  73
+	else if(~flash_rstcounter[7])
  74
+		flash_rstcounter <= flash_rstcounter + 8'd1;
91 75
 end
92 76
 
93 77
 assign flash_rst_n = flash_rstcounter[7];
94 78
 
95 79
 /*
96  
- * Clock management. Largely taken from the NWL reference design.
  80
+ * Clock management. Inspired by the NWL reference design.
97 81
  */
98  
- 
  82
+
99 83
 wire sdr_clkin;
100 84
 wire clkdiv;
101 85
 
@@ -117,12 +101,12 @@ BUFIO2 #(
117 101
 	.SERDESSTROBE()
118 102
 );
119 103
 
120  
-wire pll1_lckd;
121  
-wire buf_pll1_fb_out;
122  
-wire pll1out0;
123  
-wire pll1out1;
124  
-wire pll1out2;
125  
-wire pll1out3;
  104
+wire pll_lckd;
  105
+wire buf_pll_fb_out;
  106
+wire pllout0;
  107
+wire pllout1;
  108
+wire pllout2;
  109
+wire pllout3;
126 110
 
127 111
 PLL_ADV #(
128 112
 	.BANDWIDTH("OPTIMIZED"),
@@ -136,12 +120,12 @@ PLL_ADV #(
136 120
 	.CLKOUT1_DIVIDE(f_div),
137 121
 	.CLKOUT1_DUTY_CYCLE(0.5),
138 122
 	.CLKOUT1_PHASE(0),
139  
-	.CLKOUT2_DIVIDE(4*f_div),
  123
+	.CLKOUT2_DIVIDE(2*f_div),
140 124
 	.CLKOUT2_DUTY_CYCLE(0.5),
141  
-	.CLKOUT2_PHASE(0.0),
142  
-	.CLKOUT3_DIVIDE(2*f_div),
  125
+	.CLKOUT2_PHASE(90.0),
  126
+	.CLKOUT3_DIVIDE(4*f_div),
143 127
 	.CLKOUT3_DUTY_CYCLE(0.5),
144  
-	.CLKOUT3_PHASE(90),
  128
+	.CLKOUT3_PHASE(0.0),
145 129
 	.CLKOUT4_DIVIDE(7),
146 130
 	.CLKOUT4_DUTY_CYCLE(0.5),
147 131
 	.CLKOUT4_PHASE(0),
@@ -153,13 +137,13 @@ PLL_ADV #(
153 137
 	.REF_JITTER(0.100),
154 138
 	.CLK_FEEDBACK("CLKFBOUT"),
155 139
 	.SIM_DEVICE("SPARTAN6")
156  
-) pll1 (
  140
+) pll (
157 141
 	.CLKFBDCM(),
158  
-	.CLKFBOUT(buf_pll1_fb_out),
159  
-	.CLKOUT0(pll1out0), /* < x4 180 clock for transmitter */
160  
-	.CLKOUT1(pll1out1), /* < x4 180 clock for transmitter */
161  
-	.CLKOUT2(pll1out2), /* < x1 clock for memory controller */
162  
-	.CLKOUT3(pll1out3), /* < x2 90 clock to generate memory clock, clock DQS and memory address and control signals. */
  142
+	.CLKFBOUT(buf_pll_fb_out),
  143
+	.CLKOUT0(pllout0), /* < x4 clock for writes */
  144
+	.CLKOUT1(pllout1), /* < x4 clock for reads */
  145
+	.CLKOUT2(pllout2), /* < x2 90 clock to generate memory clock, clock DQS and memory address and control signals. */
  146
+	.CLKOUT3(pllout3), /* < x1 clock for system and memory controller */
163 147
 	.CLKOUT4(),
164 148
 	.CLKOUT5(),
165 149
 	.CLKOUTDCM0(),
@@ -170,8 +154,8 @@ PLL_ADV #(
170 154
 	.CLKOUTDCM5(),
171 155
 	.DO(),
172 156
 	.DRDY(),
173  
-	.LOCKED(pll1_lckd),
174  
-	.CLKFBIN(buf_pll1_fb_out),
  157
+	.LOCKED(pll_lckd),
  158
+	.CLKFBIN(buf_pll_fb_out),
175 159
 	.CLKIN1(clkdiv),
176 160
 	.CLKIN2(1'b0),
177 161
 	.CLKINSEL(1'b1),
@@ -186,239 +170,34 @@ PLL_ADV #(
186 170
 
187 171
 BUFPLL #(
188 172
 	.DIVIDE(4)
189  
-) wr_bufpll_left (
190  
-	.PLLIN(pll1out0),
  173
+) wr_bufpll (
  174
+	.PLLIN(pllout0),
191 175
 	.GCLK(sys_clk),
192  
-	.LOCKED(pll1_lckd),
193  
-	.IOCLK(clk4x_wr_left),
  176
+	.LOCKED(pll_lckd),
  177
+	.IOCLK(clk4x_wr),
194 178
 	.LOCK(),
195  
-	.SERDESSTROBE(clk4x_wr_strb_left)
  179
+	.SERDESSTROBE(clk4x_wr_strb)
196 180
 );
197 181
 
198 182
 BUFPLL #(
199 183
 	.DIVIDE(4)
200  
-) wr_bufpll_right (
201  
-	.PLLIN(pll1out1),
  184
+) rd_bufpll (
  185
+	.PLLIN(pllout1),
202 186
 	.GCLK(sys_clk),
203  
-	.LOCKED(pll1_lckd),
204  
-	.IOCLK(clk4x_wr_right),
  187
+	.LOCKED(pll_lckd),
  188
+	.IOCLK(clk4x_rd),
205 189
 	.LOCK(),
206  
-	.SERDESSTROBE(clk4x_wr_strb_right)
207  
-);
208  
-
209  
-BUFG bufg_x1(
210  
-	.I(pll1out2),
211  
-	.O(sys_clk)
  190
+	.SERDESSTROBE(clk4x_rd_strb)
212 191
 );
213 192
 
214 193
 BUFG bufg_x2_2(
215  
-	.I(pll1out3),
  194
+	.I(pllout2),
216 195
 	.O(clk2x_90)
217 196
 );
218 197
 
219  
-/*
220  
- * Generate clk4x_rd. This clock is sourced from clk2x_90.
221  
- * An IODELAY2 element is included in the path of this clock so that 
222  
- * any variation in IDELAY element's base delay is compensated when this clock 
223  
- * is used to capture read data which also goes through IDELAY element.
224  
- */
225  
-
226  
-wire rd_clk_out;
227  
-
228  
-ODDR2 #(
229  
-	.DDR_ALIGNMENT("C0"),
230  
-	.INIT(1'b0),
231  
-	.SRTYPE("ASYNC")
232  
-) rd_clk_out_inst (
233  
-	.Q(rd_clk_out),
234  
-	.C0(clk2x_90),
235  
-	.C1(~clk2x_90),
236  
-	.CE(1'b1),
237  
-	.D0(1'b1),
238  
-	.D1(1'b0),
239  
-	.R(1'b0),
240  
-	.S(1'b0)
241  
-);
242  
-
243  
-wire rd_clk_out_oe_n;
244  
-
245  
-ODDR2 #(
246  
-	.DDR_ALIGNMENT("C0"),
247  
-	.INIT(1'b0),
248  
-	.SRTYPE("ASYNC")
249  
-) rd_clk_out_oe_inst (
250  
-	.Q(rd_clk_out_oe_n),
251  
-	.C0(clk2x_90),
252  
-	.C1(~clk2x_90),
253  
-	.CE(1'b1),
254  
-	.D0(1'b0),
255  
-	.D1(1'b0),
256  
-	.R(1'b0),
257  
-	.S(1'b0)
258  
-);
259  
-
260  
-wire rd_clk_fb;
261  
-
262  
-/* Dummy pin used for calibration */
263  
-IOBUF rd_clk_loop_back_inst(
264  
-	.O(rd_clk_fb),
265  
-	.IO(rd_clk_lb),
266  
-	.I(rd_clk_out),
267  
-	.T(rd_clk_out_oe_n)
268  
-);
269  
-
270  
-wire rd_clk_fb_dly;
271  
-
272  
-IODELAY2 #(
273  
-	.DATA_RATE("DDR"),
274  
-	.IDELAY_VALUE(0),
275  
-	.IDELAY2_VALUE(0),
276  
-	.IDELAY_MODE("NORMAL"),
277  
-	.ODELAY_VALUE(0),
278  
-	.IDELAY_TYPE("FIXED"),
279  
-	.COUNTER_WRAPAROUND("STAY_AT_LIMIT"),
280  
-	.DELAY_SRC("IDATAIN"),
281  
-	.SERDES_MODE("NONE"),
282  
-	.SIM_TAPDELAY_VALUE(49)
283  
-) iodelay_cm (
284  
-	.IDATAIN(rd_clk_fb),
285  
-	.TOUT(),
286  
-	.DOUT(),
287  
-	.T(1'b1),
288  
-	.ODATAIN(1'b0),
289  
-	.DATAOUT(rd_clk_fb_dly),
290  
-	.DATAOUT2(),
291  
-	.IOCLK0(1'b0),
292  
-	.IOCLK1(1'b0),
293  
-	.CLK(1'b0),
294  
-	.CAL(1'b0),
295  
-	.INC(1'b0),
296  
-	.CE(1'b0),
297  
-	.RST(1'b0),
298  
-	.BUSY()
299  
-);
300  
-
301  
-wire rd_clk_fb_dly_bufio;
302  
-
303  
-BUFIO2 #(
304  
-	.DIVIDE(1),
305  
-	.DIVIDE_BYPASS("FALSE"),
306  
-	.I_INVERT("FALSE")
307  
-) bufio2_inst (
308  
-	.I(rd_clk_fb_dly),
309  
-	.IOCLK(),
310  
-	.DIVCLK(rd_clk_fb_dly_bufio),
311  
-	.SERDESSTROBE()
312  
-);
313  
-
314  
-wire pll2_lckd;
315  
-wire buf_pll2_fb_out;
316  
-wire pll2out0;
317  
-wire pll2out1;
318  
-
319  
-PLL_ADV #(
320  
-	.BANDWIDTH("OPTIMIZED"),
321  
-	.CLKFBOUT_MULT(4),
322  
-	.CLKFBOUT_PHASE(0.0),
323  
-	.CLKIN1_PERIOD(clk2x_period),
324  
-	.CLKIN2_PERIOD(clk2x_period),
325  
-	.CLKOUT0_DIVIDE(2),
326  
-	.CLKOUT0_DUTY_CYCLE(0.5),
327  
-	.CLKOUT0_PHASE(0.0),
328  
-	.CLKOUT1_DIVIDE(2),
329  
-	.CLKOUT1_DUTY_CYCLE(0.5),
330  
-	.CLKOUT1_PHASE(0.0),
331  
-	.CLKOUT2_DIVIDE(7),
332  
-	.CLKOUT2_DUTY_CYCLE(0.5),
333  
-	.CLKOUT2_PHASE(0.0),
334  
-	.CLKOUT3_DIVIDE(7),
335  
-	.CLKOUT3_DUTY_CYCLE(0.5),
336  
-	.CLKOUT3_PHASE(0.0),
337  
-	.CLKOUT4_DIVIDE(7),
338  
-	.CLKOUT4_DUTY_CYCLE(0.5),
339  
-	.CLKOUT4_PHASE(0.0),
340  
-	.CLKOUT5_DIVIDE(7),
341  
-	.CLKOUT5_DUTY_CYCLE (0.5),
342  
-	.CLKOUT5_PHASE(0.0),
343  
-	.COMPENSATION("INTERNAL"),
344  
-	.DIVCLK_DIVIDE(1),
345  
-	.REF_JITTER(0.100),
346  
-	.CLK_FEEDBACK("CLKFBOUT"),
347  
-	.SIM_DEVICE("SPARTAN6")
348  
-) pll2 (
349  
-	.CLKFBDCM(),
350  
-	.CLKFBOUT(buf_pll2_fb_out),
351  
-	.CLKOUT0(pll2out0), /* < x4 clock to capture read data */
352  
-	.CLKOUT1(pll2out1), /* < x4 clock to capture read data */
353  
-	.CLKOUT2(),
354  
-	.CLKOUT3(),
355  
-	.CLKOUT4(),
356  
-	.CLKOUT5(),
357  
-	.CLKOUTDCM0(),
358  
-	.CLKOUTDCM1(),
359  
-	.CLKOUTDCM2(),
360  
-	.CLKOUTDCM3(),
361  
-	.CLKOUTDCM4(),
362  
-	.CLKOUTDCM5(),
363  
-	.DO(),
364  
-	.DRDY(),
365  
-	.LOCKED(pll2_lckd),
366  
-	.CLKFBIN(buf_pll2_fb_out),
367  
-	.CLKIN1(rd_clk_fb_dly_bufio),
368  
-	.CLKIN2(1'b0),
369  
-	.CLKINSEL(1'b1),
370  
-	.DADDR(5'b00000),
371  
-	.DCLK(1'b0),
372  
-	.DEN(1'b0),
373  
-	.DI(16'h0000),
374  
-	.DWE(1'b0),
375  
-	.RST(~pll1_lckd),
376  
-	.REL(1'b0)
377  
-);
378  
-
379  
-BUFPLL #(
380  
-	.DIVIDE(4)
381  
-) rd_bufpll_left (
382  
-	.PLLIN(pll2out0),
383  
-	.GCLK(sys_clk),
384  
-	.LOCKED(pll2_lckd),
385  
-	.IOCLK(clk4x_rd_left),
386  
-	.LOCK(),
387  
-	.SERDESSTROBE(clk4x_rd_strb_left)
388  
-);
389  
-
390  
-BUFPLL #(
391  
-	.DIVIDE(4)
392  
-) rd_bufpll_right (
393  
-	.PLLIN(pll2out1),
394  
-	.GCLK(sys_clk),
395  
-	.LOCKED(pll2_lckd),
396  
-	.IOCLK(clk4x_rd_right),
397  
-	.LOCK(),
398  
-	.SERDESSTROBE(clk4x_rd_strb_right)
399  
-);
400  
-
401  
-wire sdram_sys_clk_lock_d16;
402  
-reg sdram_sys_clk_lock_d17;
403  
-
404  
-/*
405  
- * Async reset generation
406  
- * The reset is de-asserted 16 clocks after both internal clocks are locked.
407  
- */
408  
-
409  
-SRL16 reset_delay_sr(
410  
-	.CLK(sys_clk),
411  
-	.D(pll1_lckd & pll2_lckd),
412  
-	.A0(1'b1),
413  
-	.A1(1'b1),
414  
-	.A2(1'b1),
415  
-	.A3(1'b1),
416  
-	.Q(sdram_sys_clk_lock_d16)
  198
+BUFG bufg_x1(
  199
+	.I(pllout3),
  200
+	.O(sys_clk)
417 201
 );
418  
-
419  
-always @(posedge sys_clk)
420  
-	sdram_sys_clk_lock_d17 <= sdram_sys_clk_lock_d16;
421  
-
422  
-assign reset_n = sdram_sys_clk_lock_d17;
423 202
  
424 203
 endmodule
1  verilog/s6ddrphy/README
... ...
@@ -1 +0,0 @@
1  
-The Verilog files of the Spartan-6 DDR PHY from Xilinx/Northwest Logic go here.
27  verilog/s6ddrphy/patches/s6ddrphy.diff
... ...
@@ -1,27 +0,0 @@
1  
-Index: s6ddrphy/spartan6_soft_phy.v
2  
-===================================================================
3  
---- s6ddrphy.orig/spartan6_soft_phy.v
4  
-+++ s6ddrphy/spartan6_soft_phy.v
5  
-@@ -116,7 +116,6 @@ module spartan6_soft_phy # (
6  
-     inout  [NUM_DQ-1:0]                         sd_dq,                          // Data in from SDRAM device
7  
-     output [NUM_DQS-1:0]                        sd_dm,                          // Data mask to SDRAM devices
8  
-     inout  [NUM_DQS-1:0]                        sd_dqs,                         // DQS
9  
--    inout  [NUM_DQS-1:0]                        sd_dqs_n,                       // complimentary DQS
10  
- 
11  
-     // configuration ports
12  
-     input  [2:0]                                cfg_al,                         // Posted CAS additive latency
13  
-@@ -300,12 +299,11 @@ genvar j;
14  
- generate
15  
-     for (j = 0; j < NUM_DQ/8*(NIBBLE_DEVICES+1) ; j = j + 1)
16  
-     begin:dqs_iob
17  
--        IOBUFDS iobufds (
18  
-+        IOBUF iobufds (
19  
-             .O              (sd_dqs_in[j]),
20  
-             .I              (sd_dqs_out[j]),
21  
-             .T              (sd_dqs_oe_n[j]),
22  
--            .IO             (sd_dqs[j]),
23  
--            .IOB            (sd_dqs_n[j])
24  
-+            .IO             (sd_dqs[j])
25  
-             );
26  
-     end
27  
- endgenerate
1  verilog/s6ddrphy/patches/series
... ...
@@ -1 +0,0 @@
1  
-s6ddrphy.diff
59  verilog/s6ddrphy/s6ddrphy.v
... ...
@@ -0,0 +1,59 @@
  1
+module s6ddrphy #(
  2
+	parameter NUM_AD = 0,
  3
+	parameter NUM_BA = 0,
  4
+	parameter NUM_D = 0 /* < number of data lines per DFI phase */
  5
+) (
  6
+	/* Clocks */
  7
+	input sys_clk,
  8
+	input clk2x_90,
  9
+	input clk4x_wr,
  10
+	input clk4x_wr_strb,
  11
+	input clk4x_rd,
  12
+	input clk4x_rd_strb,
  13
+	
  14
+	/* DFI phase 0 */
  15
+	input [NUM_AD-1:0] dfi_address_p0,
  16
+	input [NUM_BA-1:0] dfi_bank_p0,
  17
+	input dfi_cs_n_p0,
  18
+	input dfi_cke_p0,
  19
+	input dfi_ras_n_p0,
  20
+	input dfi_cas_n_p0,
  21
+	input dfi_we_n_p0,
  22
+	input dfi_wrdata_en_p0,
  23
+	input [NUM_D/8-1:0] dfi_wrdata_mask_p0,
  24
+	input [NUM_D-1:0] dfi_wrdata_p0,
  25
+	input dfi_rddata_en_p0,
  26
+	output [NUM_D-1:0] dfi_rddata_w0,
  27
+	output dfi_rddata_valid_w0,
  28
+	
  29
+	/* DFI phase 1 */
  30
+	input [NUM_AD-1:0] dfi_address_p1,
  31
+	input [NUM_BA-1:0] dfi_bank_p1,
  32
+	input dfi_cs_n_p1,
  33
+	input dfi_cke_p1,
  34
+	input dfi_ras_n_p1,
  35
+	input dfi_cas_n_p1,
  36
+	input dfi_we_n_p1,
  37
+	input dfi_wrdata_en_p1,
  38
+	input [NUM_D/8-1:0] dfi_wrdata_mask_p1,
  39
+	input [NUM_D-1:0] dfi_wrdata_p1,
  40
+	input dfi_rddata_en_p1,
  41
+	output [NUM_D-1:0] dfi_rddata_w1,
  42
+	output dfi_rddata_valid_w1,
  43
+	
  44
+	/* DDR SDRAM pads */
  45
+	output sd_clk_out_p,
  46
+	output sd_clk_out_n,
  47
+	output [NUM_AD-1:0] sd_a,
  48
+	output [NUM_BA-1:0] sd_ba,
  49
+	output sd_cs_n,
  50
+	output sd_cke,
  51
+	output sd_ras_n,
  52
+	output sd_cas_n,
  53
+	output sd_we_n,
  54
+	inout [NUM_D/2-1:0] sd_dq,
  55
+	output [NUM_D/16-1:0] sd_dm,
  56
+	inout [NUM_D/16-1:0] sd_dqs
  57
+);
  58
+
  59
+endmodule

0 notes on commit f35cd4a

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