vendor.quicklogic: utilize internal SoC clock in EOS-S3
[nmigen.git] / nmigen / vendor / quicklogic.py
1 from abc import abstractproperty
2
3 from ..hdl import *
4 from ..lib.cdc import ResetSynchronizer
5 from ..build import *
6
7
8 __all__ = ["QuicklogicPlatform"]
9
10
11 class QuicklogicPlatform(TemplatedPlatform):
12 """
13 Symbiflow toolchain
14 -------------------
15 Required tools:
16 * ``symbiflow_synth``
17 * ``symbiflow_pack``
18 * ``symbiflow_place``
19 * ``symbiflow_route``
20 * ``symbiflow_write_fasm``
21 * ``symbiflow_write_bitstream``
22 The environment is populated by running the script specified in the environment variable
23 ``NMIGEN_ENV_QLSymbiflow``, if present.
24 Available overrides:
25 * ``add_constraints``: inserts commands in XDC file.
26 """
27
28 device = abstractproperty()
29 part = abstractproperty()
30
31 # Since the QuickLogic version of SymbiFlow toolchain is not upstreamed yet
32 # we should distinguish the QuickLogic version from mainline one.
33 # QuickLogic toolchain: https://github.com/QuickLogic-Corp/quicklogic-fpga-toolchain/releases
34 toolchain = "QLSymbiflow"
35
36 required_tools = [
37 "symbiflow_synth",
38 "symbiflow_pack",
39 "symbiflow_place",
40 "symbiflow_route",
41 "symbiflow_write_fasm",
42 "symbiflow_write_bitstream"
43 ]
44 file_templates = {
45 **TemplatedPlatform.build_script_templates,
46 "{{name}}.v": r"""
47 /* {{autogenerated}} */
48 {{emit_verilog()}}
49 """,
50 "{{name}}.debug.v": r"""
51 /* {{autogenerated}} */
52 {{emit_debug_verilog()}}
53 """,
54 "{{name}}.pcf": r"""
55 # {{autogenerated}}
56 {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
57 set_io {{port_name}} {{pin_name}}
58 {% endfor %}
59 """,
60 "{{name}}.xdc": r"""
61 # {{autogenerated}}
62 {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
63 {% for attr_name, attr_value in attrs.items() -%}
64 set_property {{attr_name}} {{attr_value}} [get_ports {{port_name|tcl_escape}} }]
65 {% endfor %}
66 {% endfor %}
67 {{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
68 """,
69 "{{name}}.sdc": r"""
70 # {{autogenerated}}
71 {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
72 {% if port_signal is not none -%}
73 create_clock -period {{100000000/frequency}} {{port_signal.name|ascii_escape}}
74 {% endif %}
75 {% endfor %}
76 """
77 }
78 command_templates = [
79 r"""
80 {{invoke_tool("symbiflow_synth")}}
81 -t {{name}}
82 -v {% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%} {{file}} {% endfor %} {{name}}.v
83 -d {{platform.device}}
84 -p {{name}}.pcf
85 -P {{platform.part}}
86 -x {{name}}.xdc
87 """,
88 r"""
89 {{invoke_tool("symbiflow_pack")}}
90 -e {{name}}.eblif
91 -d {{platform.device}}
92 -s {{name}}.sdc
93 """,
94 r"""
95 {{invoke_tool("symbiflow_place")}}
96 -e {{name}}.eblif
97 -d {{platform.device}}
98 -p {{name}}.pcf
99 -n {{name}}.net
100 -P {{platform.part}}
101 -s {{name}}.sdc
102 """,
103 r"""
104 {{invoke_tool("symbiflow_route")}}
105 -e {{name}}.eblif
106 -d {{platform.device}}
107 -s {{name}}.sdc
108 """,
109 r"""
110 {{invoke_tool("symbiflow_write_fasm")}}
111 -e {{name}}.eblif
112 -d {{platform.device}}
113 -s {{name}}.sdc
114 """,
115 r"""
116 {{invoke_tool("symbiflow_write_bitstream")}}
117 -f {{name}}.fasm
118 -d {{platform.device}}
119 -P {{platform.part}}
120 -b {{name}}.bit
121 """
122 ]
123
124 # Common logic
125
126 def __init__(self):
127 super().__init__()
128
129 def add_clock_constraint(self, clock, frequency):
130 super().add_clock_constraint(clock, frequency)
131 clock.attrs["keep"] = "TRUE"
132
133 def create_missing_domain(self, name):
134 if name == "sync" and self.default_clk is not None:
135 m = Module()
136 if self.default_clk == "sys_clk0":
137 clk_i = Signal()
138 sys_clk0 = Signal()
139 m.submodules += Instance("qlal4s3b_cell_macro",
140 o_Sys_Clk0=sys_clk0)
141 m.submodules += Instance("gclkbuff",
142 o_A=sys_clk0,
143 o_Z=clk_i)
144 else:
145 clk_i = self.request(self.default_clk).i
146
147 if self.default_rst is not None:
148 rst_i = self.request(self.default_rst).i
149 else:
150 rst_i = Const(0)
151
152 m.domains += ClockDomain("sync")
153 m.d.comb += ClockSignal("sync").eq(clk_i)
154 m.submodules.reset_sync = ResetSynchronizer(rst_i, domain="sync")
155 return m