52f8ca9705c699b75933f8bbae3b0bb54347ab93
[litex.git] / litex / gen / migen / build / xilinx / common.py
1 import os
2 import sys
3 from distutils.version import StrictVersion
4
5 from migen.fhdl.structure import *
6 from migen.fhdl.specials import Instance
7 from migen.fhdl.module import Module
8 from migen.fhdl.specials import SynthesisDirective
9 from migen.genlib.cdc import *
10 from migen.genlib.resetsync import AsyncResetSynchronizer
11 from migen.genlib.io import *
12
13 from migen.build import tools
14
15
16 def settings(path, ver=None, sub=None):
17 vers = list(tools.versions(path))
18 if ver is None:
19 ver = max(vers)
20 else:
21 ver = StrictVersion(ver)
22 assert ver in vers
23
24 full = os.path.join(path, str(ver))
25 if sub:
26 full = os.path.join(full, sub)
27
28 search = [64, 32]
29 if tools.arch_bits() == 32:
30 search.reverse()
31
32 if sys.platform == "win32" or sys.platform == "cygwin":
33 script_ext = "bat"
34 else:
35 script_ext = "sh"
36
37 for b in search:
38 settings = os.path.join(full, "settings{0}.{1}".format(b, script_ext))
39 if os.path.exists(settings):
40 return settings
41
42 raise OSError("no settings file found")
43
44
45 class XilinxNoRetimingImpl(Module):
46 def __init__(self, reg):
47 self.specials += SynthesisDirective("attribute register_balancing of {r} is no", r=reg)
48
49
50 class XilinxNoRetiming:
51 @staticmethod
52 def lower(dr):
53 return XilinxNoRetimingImpl(dr.reg)
54
55
56 class XilinxMultiRegImpl(MultiRegImpl):
57 def __init__(self, *args, **kwargs):
58 MultiRegImpl.__init__(self, *args, **kwargs)
59 self.specials += [SynthesisDirective("attribute shreg_extract of {r} is no", r=r)
60 for r in self.regs]
61
62
63 class XilinxMultiReg:
64 @staticmethod
65 def lower(dr):
66 return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n)
67
68
69 class XilinxAsyncResetSynchronizerImpl(Module):
70 def __init__(self, cd, async_reset):
71 rst1 = Signal()
72 self.specials += [
73 Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset,
74 i_CE=1, i_C=cd.clk, o_Q=rst1),
75 Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset,
76 i_CE=1, i_C=cd.clk, o_Q=cd.rst)
77 ]
78
79
80 class XilinxAsyncResetSynchronizer:
81 @staticmethod
82 def lower(dr):
83 return XilinxAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)
84
85
86 class XilinxDifferentialInputImpl(Module):
87 def __init__(self, i_p, i_n, o):
88 self.specials += Instance("IBUFDS", i_I=i_p, i_IB=i_n, o_O=o)
89
90
91 class XilinxDifferentialInput:
92 @staticmethod
93 def lower(dr):
94 return XilinxDifferentialInputImpl(dr.i_p, dr.i_n, dr.o)
95
96
97 class XilinxDifferentialOutputImpl(Module):
98 def __init__(self, i, o_p, o_n):
99 self.specials += Instance("OBUFDS", i_I=i, o_O=o_p, o_OB=o_n)
100
101
102 class XilinxDifferentialOutput:
103 @staticmethod
104 def lower(dr):
105 return XilinxDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n)
106
107
108 class XilinxDDROutputImpl(Module):
109 def __init__(self, i1, i2, o, clk):
110 self.specials += Instance("ODDR2",
111 p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
112 i_C0=clk, i_C1=~clk, i_CE=1, i_S=0, i_R=0,
113 i_D0=i1, i_D1=i2, o_Q=o,
114 )
115
116
117 class XilinxDDROutput:
118 @staticmethod
119 def lower(dr):
120 return XilinxDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk)
121
122
123 xilinx_special_overrides = {
124 NoRetiming: XilinxNoRetiming,
125 MultiReg: XilinxMultiReg,
126 AsyncResetSynchronizer: XilinxAsyncResetSynchronizer,
127 DifferentialInput: XilinxDifferentialInput,
128 DifferentialOutput: XilinxDifferentialOutput,
129 DDROutput: XilinxDDROutput
130 }
131
132
133 class XilinxDDROutputImplS7(Module):
134 def __init__(self, i1, i2, o, clk):
135 self.specials += Instance("ODDR",
136 p_DDR_CLK_EDGE="SAME_EDGE",
137 i_C=clk, i_CE=1, i_S=0, i_R=0,
138 i_D1=i1, i_D2=i2, o_Q=o,
139 )
140
141
142 class XilinxDDROutputS7:
143 @staticmethod
144 def lower(dr):
145 return XilinxDDROutputImplS7(dr.i1, dr.i2, dr.o, dr.clk)
146
147
148 xilinx_s7_special_overrides = {
149 DDROutput: XilinxDDROutputS7
150 }