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 * ``nproc``: sets the number of cores used by all tools.
23 * ``quartus_map_opts``: adds extra options for ``quartus_map``.
24 * ``quartus_fit_opts``: adds extra options for ``quartus_fit``.
25 * ``quartus_asm_opts``: adds extra options for ``quartus_asm``.
26 * ``quartus_sta_opts``: adds extra options for ``quartus_sta``.
29 * ``*.rpt``: toolchain reports.
30 * ``{{name}}.sof``: bitstream as SRAM object file.
31 * ``{{name}}.rbf``: bitstream as raw binary file.
36 device
= abstractproperty()
37 package
= abstractproperty()
38 speed
= abstractproperty()
41 quartus_suppressed_warnings
= [
42 10264, # All case item expressions in this case statement are onehot
43 10270, # Incomplete Verilog case statement has no default case item
44 10335, # Unrecognized synthesis attribute
45 10763, # Verilog case statement has overlapping case item expressions with non-constant or don't care bits
46 10935, # Verilog casex/casez overlaps with a previous casex/vasez item expression
47 12125, # Using design file which is not specified as a design file for the current project, but contains definitions used in project
48 18236, # Number of processors not specified in QSF
49 292013, # Feature is only available with a valid subscription license
60 **TemplatedPlatform
.build_script_templates
,
61 "build_{{name}}.sh": r
"""
63 if [ -n "${{platform._toolchain_env_var}}" ]; then
64 QUARTUS_ROOTDIR=$(dirname $(dirname "${{platform._toolchain_env_var}}"))
65 # Quartus' qenv.sh does not work with `set -e`.
66 . "${{platform._toolchain_env_var}}"
68 set -e{{verbose("x")}}
69 {{emit_commands("sh")}}
72 /* {{autogenerated}} */
75 "{{name}}.debug.v": r
"""
76 /* {{autogenerated}} */
77 {{emit_debug_verilog()}}
81 {% if get_override("nproc") -%}
82 set_global_assignment -name NUM_PARALLEL_PROCESSORS {{get_override("nproc")}}
85 {% for file in platform.iter_extra_files(".v") -%}
86 set_global_assignment -name VERILOG_FILE {{file|tcl_quote}}
88 {% for file in platform.iter_extra_files(".sv") -%}
89 set_global_assignment -name SYSTEMVERILOG_FILE {{file|tcl_quote}}
91 {% for file in platform.iter_extra_files(".vhd", ".vhdl") -%}
92 set_global_assignment -name VHDL_FILE {{file|tcl_quote}}
94 set_global_assignment -name VERILOG_FILE {{name}}.v
95 set_global_assignment -name TOP_LEVEL_ENTITY {{name}}
97 set_global_assignment -name DEVICE {{platform.device}}{{platform.package}}{{platform.speed}}{{platform.suffix}}
98 {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
99 set_location_assignment -to {{port_name|tcl_quote}} PIN_{{pin_name}}
100 {% for key, value in attrs.items() -%}
101 set_instance_assignment -to {{port_name|tcl_quote}} -name {{key}} {{value|tcl_quote}}
105 set_global_assignment -name GENERATE_RBF_FILE ON
108 {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
109 {% if port_signal is not none -%}
110 create_clock -name {{port_signal.name|tcl_quote}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_quote}}]
112 create_clock -name {{net_signal.name|tcl_quote}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("|")|tcl_quote}}]
117 {% for warning in platform.quartus_suppressed_warnings %}
118 { "" "" "" "{{name}}.v" { } { } 0 {{warning}} "" 0 0 "Design Software" 0 -1 0 ""}
122 command_templates
= [
124 {{invoke_tool("quartus_map")}}
125 {{get_override("quartus_map_opts")|options}}
126 --rev={{name}} {{name}}
129 {{invoke_tool("quartus_fit")}}
130 {{get_override("quartus_fit_opts")|options}}
131 --rev={{name}} {{name}}
134 {{invoke_tool("quartus_asm")}}
135 {{get_override("quartus_asm_opts")|options}}
136 --rev={{name}} {{name}}
139 {{invoke_tool("quartus_sta")}}
140 {{get_override("quartus_sta_opts")|options}}
141 --rev={{name}} {{name}}
145 def add_clock_constraint(self
, clock
, frequency
):
146 super().add_clock_constraint(clock
, frequency
)
147 clock
.attrs
["keep"] = "true"
149 # The altiobuf_* and altddio_* primitives are explained in the following Intel documents:
150 # * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altiobuf.pdf
151 # * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altddio.pdf
152 # See also errata mentioned in: https://www.intel.com/content/www/us/en/programmable/support/support-resources/knowledge-base/solutions/rd11192012_735.html.
155 def _get_ireg(m
, pin
, invert
):
158 i_neg
= Signal
.like(i
, name_suffix
="_neg")
159 m
.d
.comb
+= i
.eq(~i_neg
)
165 return get_ineg(pin
.i
)
167 i_sdr
= Signal(pin
.width
, name
="{}_i_sdr")
168 m
.submodules
+= Instance("$dff",
177 i_ddr
= Signal(pin
.width
, name
="{}_i_ddr".format(pin
.name
))
178 m
.submodules
["{}_i_ddr".format(pin
.name
)] = Instance("altddio_in",
182 o_dataout_h
=get_ineg(pin
.i0
),
183 o_dataout_l
=get_ineg(pin
.i1
),
189 def _get_oreg(m
, pin
, invert
):
192 o_neg
= Signal
.like(o
, name_suffix
="_neg")
193 m
.d
.comb
+= o_neg
.eq(~o
)
199 return get_oneg(pin
.o
)
201 o_sdr
= Signal(pin
.width
, name
="{}_o_sdr".format(pin
.name
))
202 m
.submodules
+= Instance("$dff",
211 o_ddr
= Signal(pin
.width
, name
="{}_o_ddr".format(pin
.name
))
212 m
.submodules
["{}_o_ddr".format(pin
.name
)] = Instance("altddio_out",
215 i_outclock
=pin
.o_clk
,
216 i_datain_h
=get_oneg(pin
.o0
),
217 i_datain_l
=get_oneg(pin
.o1
),
223 def _get_oereg(m
, pin
):
224 # altiobuf_ requires an output enable signal for each pin, but pin.oe is 1 bit wide.
226 return Repl(pin
.oe
, pin
.width
)
227 elif pin
.xdr
in (1, 2):
228 oe_reg
= Signal(pin
.width
, name
="{}_oe_reg".format(pin
.name
))
229 oe_reg
.attrs
["useioff"] = "1"
230 m
.submodules
+= Instance("$dff",
240 def get_input(self
, pin
, port
, attrs
, invert
):
241 self
._check
_feature
("single-ended input", pin
, attrs
,
242 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
244 port
.attrs
["useioff"] = 1
247 m
.submodules
[pin
.name
] = Instance("altiobuf_in",
248 p_enable_bus_hold
="FALSE",
249 p_number_of_channels
=pin
.width
,
250 p_use_differential_mode
="FALSE",
252 o_dataout
=self
._get
_ireg
(m
, pin
, invert
)
256 def get_output(self
, pin
, port
, attrs
, invert
):
257 self
._check
_feature
("single-ended output", pin
, attrs
,
258 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
260 port
.attrs
["useioff"] = 1
263 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
264 p_enable_bus_hold
="FALSE",
265 p_number_of_channels
=pin
.width
,
266 p_use_differential_mode
="FALSE",
268 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
273 def get_tristate(self
, pin
, port
, attrs
, invert
):
274 self
._check
_feature
("single-ended tristate", pin
, attrs
,
275 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
277 port
.attrs
["useioff"] = 1
280 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
281 p_enable_bus_hold
="FALSE",
282 p_number_of_channels
=pin
.width
,
283 p_use_differential_mode
="FALSE",
285 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
287 i_oe
=self
._get
_oereg
(m
, pin
)
291 def get_input_output(self
, pin
, port
, attrs
, invert
):
292 self
._check
_feature
("single-ended input/output", pin
, attrs
,
293 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
295 port
.attrs
["useioff"] = 1
298 m
.submodules
[pin
.name
] = Instance("altiobuf_bidir",
299 p_enable_bus_hold
="FALSE",
300 p_number_of_channels
=pin
.width
,
301 p_use_differential_mode
="FALSE",
302 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
304 o_dataout
=self
._get
_ireg
(m
, pin
, invert
),
305 i_oe
=self
._get
_oereg
(m
, pin
),
309 def get_diff_input(self
, pin
, port
, attrs
, invert
):
310 self
._check
_feature
("differential input", pin
, attrs
,
311 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
313 port
.p
.attrs
["useioff"] = 1
314 port
.n
.attrs
["useioff"] = 1
317 m
.submodules
[pin
.name
] = Instance("altiobuf_in",
318 p_enable_bus_hold
="FALSE",
319 p_number_of_channels
=pin
.width
,
320 p_use_differential_mode
="TRUE",
323 o_dataout
=self
._get
_ireg
(m
, pin
, invert
)
327 def get_diff_output(self
, pin
, port
, attrs
, invert
):
328 self
._check
_feature
("differential output", pin
, attrs
,
329 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
331 port
.p
.attrs
["useioff"] = 1
332 port
.n
.attrs
["useioff"] = 1
335 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
336 p_enable_bus_hold
="FALSE",
337 p_number_of_channels
=pin
.width
,
338 p_use_differential_mode
="TRUE",
340 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
346 def get_diff_tristate(self
, pin
, port
, attrs
, invert
):
347 self
._check
_feature
("differential tristate", pin
, attrs
,
348 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
350 port
.p
.attrs
["useioff"] = 1
351 port
.n
.attrs
["useioff"] = 1
354 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
355 p_enable_bus_hold
="FALSE",
356 p_number_of_channels
=pin
.width
,
357 p_use_differential_mode
="TRUE",
359 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
362 i_oe
=self
._get
_oereg
(m
, pin
),
366 def get_diff_input_output(self
, pin
, port
, attrs
, invert
):
367 self
._check
_feature
("differential input/output", pin
, attrs
,
368 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
370 port
.p
.attrs
["useioff"] = 1
371 port
.n
.attrs
["useioff"] = 1
374 m
.submodules
[pin
.name
] = Instance("altiobuf_bidir",
375 p_enable_bus_hold
="FALSE",
376 p_number_of_channels
=pin
.width
,
377 p_use_differential_mode
="TRUE",
378 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
381 o_dataout
=self
._get
_ireg
(m
, pin
, invert
),
382 i_oe
=self
._get
_oereg
(m
, pin
),
386 # The altera_std_synchronizer{,_bundle} megafunctions embed SDC constraints that mark false
387 # paths, so use them instead of our default implementation.
389 def get_ff_sync(self
, ff_sync
):
390 return Instance("altera_std_synchronizer_bundle",
391 p_width
=len(ff_sync
.i
),
392 p_depth
=ff_sync
._stages
,
393 i_clk
=ClockSignal(ff_sync
._o
_domain
),
399 def get_async_ff_sync(self
, async_ff_sync
):
401 sync_output
= Signal()
402 if async_ff_sync
._edge
== "pos":
403 m
.submodules
+= Instance("altera_std_synchronizer",
404 p_depth
=async_ff_sync
._stages
,
405 i_clk
=ClockSignal(async_ff_sync
._domain
),
406 i_reset_n
=~async_ff_sync
.i
,
411 m
.submodules
+= Instance("altera_std_synchronizer",
412 p_depth
=async_ff_sync
._stages
,
413 i_clk
=ClockSignal(async_ff_sync
._domain
),
414 i_reset_n
=async_ff_sync
.i
,
418 m
.d
.comb
+= async_ff_sync
.o
.eq(~sync_output
)