soc/integration/builder: export constants and memory_regions with csr_csv
[litex.git] / litex / soc / integration / sdram_init.py
1 from litex.gen import log2_int
2
3
4 def get_sdram_phy_header(sdram_phy_settings):
5 r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
6 r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
7
8 nphases = sdram_phy_settings.nphases
9 r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
10
11 r += "static void cdelay(int i);\n"
12
13 # commands_px functions
14 for n in range(nphases):
15 r += """
16 static void command_p{n}(int cmd)
17 {{
18 sdram_dfii_pi{n}_command_write(cmd);
19 sdram_dfii_pi{n}_command_issue_write(1);
20 }}""".format(n=str(n))
21 r += "\n\n"
22
23 # rd/wr access macros
24 r += """
25 #define sdram_dfii_pird_address_write(X) sdram_dfii_pi{rdphase}_address_write(X)
26 #define sdram_dfii_piwr_address_write(X) sdram_dfii_pi{wrphase}_address_write(X)
27
28 #define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi{rdphase}_baddress_write(X)
29 #define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi{wrphase}_baddress_write(X)
30
31 #define command_prd(X) command_p{rdphase}(X)
32 #define command_pwr(X) command_p{wrphase}(X)
33 """.format(rdphase=str(sdram_phy_settings.rdphase), wrphase=str(sdram_phy_settings.wrphase))
34 r += "\n"
35
36 #
37 # sdrrd/sdrwr functions utilities
38 #
39 r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n"
40 sdram_dfii_pix_wrdata_addr = []
41 for n in range(nphases):
42 sdram_dfii_pix_wrdata_addr.append("CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n))
43 r += """
44 const unsigned int sdram_dfii_pix_wrdata_addr[{n}] = {{
45 {sdram_dfii_pix_wrdata_addr}
46 }};
47 """.format(n=nphases, sdram_dfii_pix_wrdata_addr=",\n\t".join(sdram_dfii_pix_wrdata_addr))
48
49 sdram_dfii_pix_rddata_addr = []
50 for n in range(nphases):
51 sdram_dfii_pix_rddata_addr.append("CSR_SDRAM_DFII_PI{n}_RDDATA_ADDR".format(n=n))
52 r += """
53 const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
54 {sdram_dfii_pix_rddata_addr}
55 }};
56 """.format(n=nphases, sdram_dfii_pix_rddata_addr=",\n\t".join(sdram_dfii_pix_rddata_addr))
57 r += "\n"
58
59 # init sequence
60 cmds = {
61 "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
62 "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
63 "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
64 "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
65 "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
66 }
67
68 cl = sdram_phy_settings.cl
69
70 if sdram_phy_settings.memtype == "SDR":
71 bl = sdram_phy_settings.nphases
72 mr = log2_int(bl) + (cl << 4)
73 reset_dll = 1 << 8
74
75 init_sequence = [
76 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
77 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
78 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
79 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
80 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
81 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
82 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
83 ]
84
85 elif sdram_phy_settings.memtype == "DDR":
86 bl = 2*sdram_phy_settings.nphases
87 mr = log2_int(bl) + (cl << 4)
88 emr = 0
89 reset_dll = 1 << 8
90
91 init_sequence = [
92 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
93 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
94 ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
95 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
96 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
97 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
98 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
99 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
100 ]
101
102 elif sdram_phy_settings.memtype == "LPDDR":
103 bl = 2*sdram_phy_settings.nphases
104 mr = log2_int(bl) + (cl << 4)
105 emr = 0
106 reset_dll = 1 << 8
107
108 init_sequence = [
109 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
110 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
111 ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
112 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
113 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
114 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
115 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
116 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
117 ]
118
119 elif sdram_phy_settings.memtype == "DDR2":
120 bl = 2*sdram_phy_settings.nphases
121 wr = 2
122 mr = log2_int(bl) + (cl << 4) + (wr << 9)
123 emr = 0
124 emr2 = 0
125 emr3 = 0
126 reset_dll = 1 << 8
127 ocd = 7 << 7
128
129 init_sequence = [
130 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
131 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
132 ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
133 ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
134 ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
135 ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
136 ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
137 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
138 ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
139 ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
140 ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
141 ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
142 ]
143 elif sdram_phy_settings.memtype == "DDR3":
144 bl = 2*sdram_phy_settings.nphases
145
146 def format_mr0(bl, cl, wr, dll_reset):
147 bl_to_mr0 = {
148 4: 0b10,
149 8: 0b00
150 }
151 cl_to_mr0 = {
152 5: 0b0010,
153 6: 0b0100,
154 7: 0b0110,
155 8: 0b1000,
156 9: 0b1010,
157 10: 0b1100,
158 11: 0b1110,
159 12: 0b0001,
160 13: 0b0011,
161 14: 0b0101
162 }
163 wr_to_mr0 = {
164 16: 0b000,
165 5: 0b001,
166 6: 0b010,
167 7: 0b011,
168 8: 0b100,
169 10: 0b101,
170 12: 0b110,
171 14: 0b111
172 }
173 mr0 = bl_to_mr0[bl]
174 mr0 |= (cl_to_mr0[cl] & 1) << 2
175 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
176 mr0 |= dll_reset << 8
177 mr0 |= wr_to_mr0[wr] << 9
178 return mr0
179
180 def format_mr1(output_drive_strength, rtt_nom):
181 mr1 = ((output_drive_strength >> 0) & 1) << 1
182 mr1 |= ((output_drive_strength >> 1) & 1) << 5
183 mr1 |= ((rtt_nom >> 0) & 1) << 2
184 mr1 |= ((rtt_nom >> 1) & 1) << 6
185 mr1 |= ((rtt_nom >> 2) & 1) << 9
186 return mr1
187
188 def format_mr2(cwl, rtt_wr):
189 mr2 = (cwl-5) << 3
190 mr2 |= rtt_wr << 9
191 return mr2
192
193 mr0 = format_mr0(bl, cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK)
194 mr1 = format_mr1(1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm)
195 mr2 = format_mr2(sdram_phy_settings.cwl, 2) # Rtt(WR) RZQ/4
196 mr3 = 0
197
198 init_sequence = [
199 ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
200 ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
201 ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0),
202 ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
203 ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
204 ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
205 ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
206 ]
207
208 # the value of MR1 needs to be modified during write leveling
209 r += "#define DDR3_MR1 {}\n\n".format(mr1)
210 else:
211 raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype)
212
213 r += "static void init_sequence(void)\n{\n"
214 for comment, a, ba, cmd, delay in init_sequence:
215 r += "\t/* {0} */\n".format(comment)
216 r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a)
217 r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(ba)
218 if cmd[:12] == "DFII_CONTROL":
219 r += "\tsdram_dfii_control_write({0});\n".format(cmd)
220 else:
221 r += "\tcommand_p0({0});\n".format(cmd)
222 if delay:
223 r += "\tcdelay({0:d});\n".format(delay)
224 r += "\n"
225 r += "}\n"
226
227 r += "#endif\n"
228
229 return r