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_files(".v") -%}
86 set_global_assignment -name VERILOG_FILE {{file|tcl_quote}}
88 {% for file in platform.iter_files(".sv") -%}
89 set_global_assignment -name SYSTEMVERILOG_FILE {{file|tcl_quote}}
91 {% for file in platform.iter_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"
150 def default_clk_constraint(self
):
151 # Internal high-speed oscillator on Cyclone V devices.
152 # It is specified to not be faster than 100MHz, but the actual
153 # frequency seems to vary a lot between devices. Measurements
154 # of 78 to 84 MHz have been observed.
155 if self
.default_clk
== "cyclonev_oscillator":
156 assert self
.device
.startswith("5C")
158 # Otherwise, use the defined Clock resource.
159 return super().default_clk_constraint
161 def create_missing_domain(self
, name
):
162 if name
== "sync" and self
.default_clk
== "cyclonev_oscillator":
163 # Use the internal high-speed oscillator for Cyclone V devices
164 assert self
.device
.startswith("5C")
166 m
.domains
+= ClockDomain("sync")
167 m
.submodules
+= Instance("cyclonev_oscillator",
169 o_clkout
=ClockSignal("sync"))
172 return super().create_missing_domain(name
)
174 # The altiobuf_* and altddio_* primitives are explained in the following Intel documents:
175 # * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altiobuf.pdf
176 # * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_altddio.pdf
177 # See also errata mentioned in: https://www.intel.com/content/www/us/en/programmable/support/support-resources/knowledge-base/solutions/rd11192012_735.html.
180 def _get_ireg(m
, pin
, invert
):
183 i_neg
= Signal
.like(i
, name_suffix
="_neg")
184 m
.d
.comb
+= i
.eq(~i_neg
)
190 return get_ineg(pin
.i
)
192 i_sdr
= Signal(pin
.width
, name
="{}_i_sdr")
193 m
.submodules
+= Instance("$dff",
202 i_ddr
= Signal(pin
.width
, name
="{}_i_ddr".format(pin
.name
))
203 m
.submodules
["{}_i_ddr".format(pin
.name
)] = Instance("altddio_in",
207 o_dataout_h
=get_ineg(pin
.i0
),
208 o_dataout_l
=get_ineg(pin
.i1
),
214 def _get_oreg(m
, pin
, invert
):
217 o_neg
= Signal
.like(o
, name_suffix
="_neg")
218 m
.d
.comb
+= o_neg
.eq(~o
)
224 return get_oneg(pin
.o
)
226 o_sdr
= Signal(pin
.width
, name
="{}_o_sdr".format(pin
.name
))
227 m
.submodules
+= Instance("$dff",
236 o_ddr
= Signal(pin
.width
, name
="{}_o_ddr".format(pin
.name
))
237 m
.submodules
["{}_o_ddr".format(pin
.name
)] = Instance("altddio_out",
240 i_outclock
=pin
.o_clk
,
241 i_datain_h
=get_oneg(pin
.o0
),
242 i_datain_l
=get_oneg(pin
.o1
),
248 def _get_oereg(m
, pin
):
249 # altiobuf_ requires an output enable signal for each pin, but pin.oe is 1 bit wide.
251 return Repl(pin
.oe
, pin
.width
)
252 elif pin
.xdr
in (1, 2):
253 oe_reg
= Signal(pin
.width
, name
="{}_oe_reg".format(pin
.name
))
254 oe_reg
.attrs
["useioff"] = "1"
255 m
.submodules
+= Instance("$dff",
265 def get_input(self
, pin
, port
, attrs
, invert
):
266 self
._check
_feature
("single-ended input", pin
, attrs
,
267 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
269 port
.attrs
["useioff"] = 1
272 m
.submodules
[pin
.name
] = Instance("altiobuf_in",
273 p_enable_bus_hold
="FALSE",
274 p_number_of_channels
=pin
.width
,
275 p_use_differential_mode
="FALSE",
277 o_dataout
=self
._get
_ireg
(m
, pin
, invert
)
281 def get_output(self
, pin
, port
, attrs
, invert
):
282 self
._check
_feature
("single-ended output", pin
, attrs
,
283 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
285 port
.attrs
["useioff"] = 1
288 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
289 p_enable_bus_hold
="FALSE",
290 p_number_of_channels
=pin
.width
,
291 p_use_differential_mode
="FALSE",
293 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
298 def get_tristate(self
, pin
, port
, attrs
, invert
):
299 self
._check
_feature
("single-ended tristate", pin
, attrs
,
300 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
302 port
.attrs
["useioff"] = 1
305 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
306 p_enable_bus_hold
="FALSE",
307 p_number_of_channels
=pin
.width
,
308 p_use_differential_mode
="FALSE",
310 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
312 i_oe
=self
._get
_oereg
(m
, pin
)
316 def get_input_output(self
, pin
, port
, attrs
, invert
):
317 self
._check
_feature
("single-ended input/output", pin
, attrs
,
318 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
320 port
.attrs
["useioff"] = 1
323 m
.submodules
[pin
.name
] = Instance("altiobuf_bidir",
324 p_enable_bus_hold
="FALSE",
325 p_number_of_channels
=pin
.width
,
326 p_use_differential_mode
="FALSE",
327 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
329 o_dataout
=self
._get
_ireg
(m
, pin
, invert
),
330 i_oe
=self
._get
_oereg
(m
, pin
),
334 def get_diff_input(self
, pin
, port
, attrs
, invert
):
335 self
._check
_feature
("differential input", pin
, attrs
,
336 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
338 port
.p
.attrs
["useioff"] = 1
339 port
.n
.attrs
["useioff"] = 1
342 m
.submodules
[pin
.name
] = Instance("altiobuf_in",
343 p_enable_bus_hold
="FALSE",
344 p_number_of_channels
=pin
.width
,
345 p_use_differential_mode
="TRUE",
348 o_dataout
=self
._get
_ireg
(m
, pin
, invert
)
352 def get_diff_output(self
, pin
, port
, attrs
, invert
):
353 self
._check
_feature
("differential output", pin
, attrs
,
354 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
356 port
.p
.attrs
["useioff"] = 1
357 port
.n
.attrs
["useioff"] = 1
360 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
361 p_enable_bus_hold
="FALSE",
362 p_number_of_channels
=pin
.width
,
363 p_use_differential_mode
="TRUE",
365 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
371 def get_diff_tristate(self
, pin
, port
, attrs
, invert
):
372 self
._check
_feature
("differential tristate", pin
, attrs
,
373 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
375 port
.p
.attrs
["useioff"] = 1
376 port
.n
.attrs
["useioff"] = 1
379 m
.submodules
[pin
.name
] = Instance("altiobuf_out",
380 p_enable_bus_hold
="FALSE",
381 p_number_of_channels
=pin
.width
,
382 p_use_differential_mode
="TRUE",
384 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
387 i_oe
=self
._get
_oereg
(m
, pin
),
391 def get_diff_input_output(self
, pin
, port
, attrs
, invert
):
392 self
._check
_feature
("differential input/output", pin
, attrs
,
393 valid_xdrs
=(0, 1, 2), valid_attrs
=True)
395 port
.p
.attrs
["useioff"] = 1
396 port
.n
.attrs
["useioff"] = 1
399 m
.submodules
[pin
.name
] = Instance("altiobuf_bidir",
400 p_enable_bus_hold
="FALSE",
401 p_number_of_channels
=pin
.width
,
402 p_use_differential_mode
="TRUE",
403 i_datain
=self
._get
_oreg
(m
, pin
, invert
),
406 o_dataout
=self
._get
_ireg
(m
, pin
, invert
),
407 i_oe
=self
._get
_oereg
(m
, pin
),
411 # The altera_std_synchronizer{,_bundle} megafunctions embed SDC constraints that mark false
412 # paths, so use them instead of our default implementation.
414 def get_ff_sync(self
, ff_sync
):
415 return Instance("altera_std_synchronizer_bundle",
416 p_width
=len(ff_sync
.i
),
417 p_depth
=ff_sync
._stages
,
418 i_clk
=ClockSignal(ff_sync
._o
_domain
),
424 def get_async_ff_sync(self
, async_ff_sync
):
426 sync_output
= Signal()
427 if async_ff_sync
._edge
== "pos":
428 m
.submodules
+= Instance("altera_std_synchronizer",
429 p_depth
=async_ff_sync
._stages
,
430 i_clk
=ClockSignal(async_ff_sync
._o
_domain
),
431 i_reset_n
=~async_ff_sync
.i
,
436 m
.submodules
+= Instance("altera_std_synchronizer",
437 p_depth
=async_ff_sync
._stages
,
438 i_clk
=ClockSignal(async_ff_sync
._o
_domain
),
439 i_reset_n
=async_ff_sync
.i
,
443 m
.d
.comb
+= async_ff_sync
.o
.eq(~sync_output
)