1 from abc
import abstractproperty
7 __all__
= ["IntelPlatform"]
10 class IntelPlatform(TemplatedPlatform
):
18 The environment is populated by running the script specified in the environment variable
19 ``NMIGEN_ENV_Quartus``, if present.
22 * ``add_settings``: inserts commands at the end of the QSF file.
23 * ``add_constraints``: inserts commands at the end of the SDC file.
24 * ``nproc``: sets the number of cores used by all tools.
25 * ``quartus_map_opts``: adds extra options for ``quartus_map``.
26 * ``quartus_fit_opts``: adds extra options for ``quartus_fit``.
27 * ``quartus_asm_opts``: adds extra options for ``quartus_asm``.
28 * ``quartus_sta_opts``: adds extra options for ``quartus_sta``.
31 * ``*.rpt``: toolchain reports.
32 * ``{{name}}.sof``: bitstream as SRAM object file.
33 * ``{{name}}.rbf``: bitstream as raw binary file.
38 device
= abstractproperty()
39 package
= abstractproperty()
40 speed
= abstractproperty()
43 quartus_suppressed_warnings
= [
44 10264, # All case item expressions in this case statement are onehot
45 10270, # Incomplete Verilog case statement has no default case item
46 10335, # Unrecognized synthesis attribute
47 10763, # Verilog case statement has overlapping case item expressions with non-constant or don't care bits
48 10935, # Verilog casex/casez overlaps with a previous casex/vasez item expression
49 12125, # Using design file which is not specified as a design file for the current project, but contains definitions used in project
50 18236, # Number of processors not specified in QSF
51 292013, # Feature is only available with a valid subscription license
62 **TemplatedPlatform
.build_script_templates
,
63 "build_{{name}}.sh": r
"""
65 if [ -n "${{platform._toolchain_env_var}}" ]; then
66 QUARTUS_ROOTDIR=$(dirname $(dirname "${{platform._toolchain_env_var}}"))
67 # Quartus' qenv.sh does not work with `set -e`.
68 . "${{platform._toolchain_env_var}}"
70 set -e{{verbose("x")}}
71 {{emit_commands("sh")}}
74 /* {{autogenerated}} */
77 "{{name}}.debug.v": r
"""
78 /* {{autogenerated}} */
79 {{emit_debug_verilog()}}
83 {% if get_override("nproc") -%}
84 set_global_assignment -name NUM_PARALLEL_PROCESSORS {{get_override("nproc")}}
87 {% for file in platform.iter_files(".v") -%}
88 set_global_assignment -name VERILOG_FILE {{file|tcl_quote}}
90 {% for file in platform.iter_files(".sv") -%}
91 set_global_assignment -name SYSTEMVERILOG_FILE {{file|tcl_quote}}
93 {% for file in platform.iter_files(".vhd", ".vhdl") -%}
94 set_global_assignment -name VHDL_FILE {{file|tcl_quote}}
96 set_global_assignment -name VERILOG_FILE {{name}}.v
97 set_global_assignment -name TOP_LEVEL_ENTITY {{name}}
99 set_global_assignment -name DEVICE {{platform.device}}{{platform.package}}{{platform.speed}}{{platform.suffix}}
100 {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
101 set_location_assignment -to {{port_name|tcl_quote}} PIN_{{pin_name}}
102 {% for key, value in attrs.items() -%}
103 set_instance_assignment -to {{port_name|tcl_quote}} -name {{key}} {{value|tcl_quote}}
107 set_global_assignment -name GENERATE_RBF_FILE ON
109 {{get_override("add_settings")|default("# (add_settings placeholder)")}}
112 {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
113 {% if port_signal is not none -%}
114 create_clock -name {{port_signal.name|tcl_quote}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_quote}}]
116 create_clock -name {{net_signal.name|tcl_quote}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("|")|tcl_quote}}]
119 {{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
122 {% for warning in platform.quartus_suppressed_warnings %}
123 { "" "" "" "{{name}}.v" { } { } 0 {{warning}} "" 0 0 "Design Software" 0 -1 0 ""}
127 command_templates
= [
129 {{invoke_tool("quartus_map")}}
130 {{get_override("quartus_map_opts")|options}}
131 --rev={{name}} {{name}}
134 {{invoke_tool("quartus_fit")}}
135 {{get_override("quartus_fit_opts")|options}}
136 --rev={{name}} {{name}}
139 {{invoke_tool("quartus_asm")}}
140 {{get_override("quartus_asm_opts")|options}}
141 --rev={{name}} {{name}}
144 {{invoke_tool("quartus_sta")}}
145 {{get_override("quartus_sta_opts")|options}}
146 --rev={{name}} {{name}}
150 def add_clock_constraint(self
, clock
, frequency
):
151 super().add_clock_constraint(clock
, frequency
)
152 clock
.attrs
["keep"] = "true"
155 def default_clk_constraint(self
):
156 # Internal high-speed oscillator on Cyclone V devices.
157 # It is specified to not be faster than 100MHz, but the actual
158 # frequency seems to vary a lot between devices. Measurements
159 # of 78 to 84 MHz have been observed.
160 if self
.default_clk
== "cyclonev_oscillator":
161 assert self
.device
.startswith("5C")
163 # Otherwise, use the defined Clock resource.
164 return super().default_clk_constraint
166 def create_missing_domain(self
, name
):
167 if name
== "sync" and self
.default_clk
== "cyclonev_oscillator":
168 # Use the internal high-speed oscillator for Cyclone V devices
169 assert self
.device
.startswith("5C")
171 m
.domains
+= ClockDomain("sync")
172 m
.submodules
+= Instance("cyclonev_oscillator",
174 o_clkout
=ClockSignal("sync"))
177 return super().create_missing_domain(name
)
179 # The altiobuf_* and altddio_* primitives are explained in the following Intel documents:
180 # * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altiobuf.pdf
181 # * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altddio.pdf
182 # See also errata mentioned in: https://www.intel.com/content/www/us/en/programmable/support/support-resources/knowledge-base/solutions/rd11192012_735.html.
185 def _get_ireg(m
, pin
, invert
):
188 i_neg
= Signal
.like(i
, name_suffix
="_neg")
189 m
.d
.comb
+= i
.eq(~i_neg
)
195 return get_ineg(pin
.i
)
197 i_sdr
= Signal(pin
.width
, name
="{}_i_sdr")
198 m
.submodules
+= Instance("$dff",
207 i_ddr
= Signal(pin
.width
, name
="{}_i_ddr".format(pin
.name
))
208 m
.submodules
["{}_i_ddr".format(pin
.name
)] = Instance("altddio_in",
212 o_dataout_h
=get_ineg(pin
.i0
),
213 o_dataout_l
=get_ineg(pin
.i1
),
219 def _get_oreg(m
, pin
, invert
):
222 o_neg
= Signal
.like(o
, name_suffix
="_neg")
223 m
.d
.comb
+= o_neg
.eq(~o
)
229 return get_oneg(pin
.o
)
231 o_sdr
= Signal(pin
.width
, name
="{}_o_sdr".format(pin
.name
))
232 m
.submodules
+= Instance("$dff",
241 o_ddr
= Signal(pin
.width
, name
="{}_o_ddr".format(pin
.name
))
242 m
.submodules
["{}_o_ddr".format(pin
.name
)] = Instance("altddio_out",
245 i_outclock
=pin
.o_clk
,
246 i_datain_h
=get_oneg(pin
.o0
),
247 i_datain_l
=get_oneg(pin
.o1
),
253 def _get_oereg(m
, pin
):
254 # altiobuf_ requires an output enable signal for each pin, but pin.oe is 1 bit wide.
256 return Repl(pin
.oe
, pin
.width
)
257 elif pin
.xdr
in (1, 2):
258 oe_reg
= Signal(pin
.width
, name
="{}_oe_reg".format(pin
.name
))
259 oe_reg
.attrs
["useioff"] = "1"
260 m
.submodules
+= Instance("$dff",
270 def get_input(self
, pin
, port
, attrs
, invert
):
271 self
._check
_feature
("single-ended input", pin
, attrs
,
272 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
274 port
.attrs
["useioff"] = 1
277 m
.submodules
[pin
.name
] = Instance("altiobuf_in",
278 p_enable_bus_hold
="FALSE",
279 p_number_of_channels
=pin
.width
,
280 p_use_differential_mode
="FALSE",
282 o_dataout
=self
._get
_ireg
(m
, pin
, invert
)
286 def get_output(self
, pin
, port
, attrs
, invert
):
287 self
._check
_feature
("single-ended output", pin
, attrs
,
288 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
290 port
.attrs
["useioff"] = 1
293 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
294 p_enable_bus_hold
="FALSE",
295 p_number_of_channels
=pin
.width
,
296 p_use_differential_mode
="FALSE",
298 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
303 def get_tristate(self
, pin
, port
, attrs
, invert
):
304 self
._check
_feature
("single-ended tristate", pin
, attrs
,
305 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
307 port
.attrs
["useioff"] = 1
310 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
311 p_enable_bus_hold
="FALSE",
312 p_number_of_channels
=pin
.width
,
313 p_use_differential_mode
="FALSE",
315 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
317 i_oe
=self
._get
_oereg
(m
, pin
)
321 def get_input_output(self
, pin
, port
, attrs
, invert
):
322 self
._check
_feature
("single-ended input/output", pin
, attrs
,
323 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
325 port
.attrs
["useioff"] = 1
328 m
.submodules
[pin
.name
] = Instance("altiobuf_bidir",
329 p_enable_bus_hold
="FALSE",
330 p_number_of_channels
=pin
.width
,
331 p_use_differential_mode
="FALSE",
332 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
334 o_dataout
=self
._get
_ireg
(m
, pin
, invert
),
335 i_oe
=self
._get
_oereg
(m
, pin
),
339 def get_diff_input(self
, pin
, port
, attrs
, invert
):
340 self
._check
_feature
("differential input", pin
, attrs
,
341 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
343 port
.p
.attrs
["useioff"] = 1
344 port
.n
.attrs
["useioff"] = 1
347 m
.submodules
[pin
.name
] = Instance("altiobuf_in",
348 p_enable_bus_hold
="FALSE",
349 p_number_of_channels
=pin
.width
,
350 p_use_differential_mode
="TRUE",
353 o_dataout
=self
._get
_ireg
(m
, pin
, invert
)
357 def get_diff_output(self
, pin
, port
, attrs
, invert
):
358 self
._check
_feature
("differential output", pin
, attrs
,
359 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
361 port
.p
.attrs
["useioff"] = 1
362 port
.n
.attrs
["useioff"] = 1
365 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
366 p_enable_bus_hold
="FALSE",
367 p_number_of_channels
=pin
.width
,
368 p_use_differential_mode
="TRUE",
370 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
376 def get_diff_tristate(self
, pin
, port
, attrs
, invert
):
377 self
._check
_feature
("differential tristate", pin
, attrs
,
378 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
380 port
.p
.attrs
["useioff"] = 1
381 port
.n
.attrs
["useioff"] = 1
384 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
385 p_enable_bus_hold
="FALSE",
386 p_number_of_channels
=pin
.width
,
387 p_use_differential_mode
="TRUE",
389 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
392 i_oe
=self
._get
_oereg
(m
, pin
),
396 def get_diff_input_output(self
, pin
, port
, attrs
, invert
):
397 self
._check
_feature
("differential input/output", pin
, attrs
,
398 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
400 port
.p
.attrs
["useioff"] = 1
401 port
.n
.attrs
["useioff"] = 1
404 m
.submodules
[pin
.name
] = Instance("altiobuf_bidir",
405 p_enable_bus_hold
="FALSE",
406 p_number_of_channels
=pin
.width
,
407 p_use_differential_mode
="TRUE",
408 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
411 o_dataout
=self
._get
_ireg
(m
, pin
, invert
),
412 i_oe
=self
._get
_oereg
(m
, pin
),
416 # The altera_std_synchronizer{,_bundle} megafunctions embed SDC constraints that mark false
417 # paths, so use them instead of our default implementation.
419 def get_ff_sync(self
, ff_sync
):
420 return Instance("altera_std_synchronizer_bundle",
421 p_width
=len(ff_sync
.i
),
422 p_depth
=ff_sync
._stages
,
423 i_clk
=ClockSignal(ff_sync
._o
_domain
),
429 def get_async_ff_sync(self
, async_ff_sync
):
431 sync_output
= Signal()
432 if async_ff_sync
._edge
== "pos":
433 m
.submodules
+= Instance("altera_std_synchronizer",
434 p_depth
=async_ff_sync
._stages
,
435 i_clk
=ClockSignal(async_ff_sync
._o
_domain
),
436 i_reset_n
=~async_ff_sync
.i
,
441 m
.submodules
+= Instance("altera_std_synchronizer",
442 p_depth
=async_ff_sync
._stages
,
443 i_clk
=ClockSignal(async_ff_sync
._o
_domain
),
444 i_reset_n
=async_ff_sync
.i
,
448 m
.d
.comb
+= async_ff_sync
.o
.eq(~sync_output
)