Fix typo
[gram.git] / gram / simulation / simcrg.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2
3 from nmigen import *
4 from nmigen.cli import main
5 from nmigen.lib.cdc import ResetSynchronizer
6
7 class PLL(Elaboratable):
8 def __init__(self, clkin, clksel=Signal(shape=2, reset=2), clkout1=Signal(), clkout2=Signal(), clkout3=Signal(), clkout4=Signal(), lock=Signal(), CLKI_DIV=1, CLKFB_DIV=1, CLK1_DIV=3, CLK2_DIV=4, CLK3_DIV=5, CLK4_DIV=6):
9 self.clkin = clkin
10 self.clkout1 = clkout1
11 self.clkout2 = clkout2
12 self.clkout3 = clkout3
13 self.clkout4 = clkout4
14 self.clksel = clksel
15 self.lock = lock
16 self.CLKI_DIV = CLKI_DIV
17 self.CLKFB_DIV = CLKFB_DIV
18 self.CLKOP_DIV = CLK1_DIV
19 self.CLKOS_DIV = CLK2_DIV
20 self.CLKOS2_DIV = CLK3_DIV
21 self.CLKOS3_DIV = CLK4_DIV
22 self.ports = [
23 self.clkin,
24 self.clkout1,
25 self.clkout2,
26 self.clkout3,
27 self.clkout4,
28 self.clksel,
29 self.lock,
30 ]
31
32 def elaborate(self, platform):
33 clkfb = Signal()
34 pll = Instance("EHXPLLL",
35 p_PLLRST_ENA='DISABLED',
36 p_INTFB_WAKE='DISABLED',
37 p_STDBY_ENABLE='DISABLED',
38 p_CLKOP_FPHASE=0,
39 p_CLKOP_CPHASE=1,
40 p_OUTDIVIDER_MUXA='DIVA',
41 p_CLKOP_ENABLE='ENABLED',
42 p_CLKOP_DIV=self.CLKOP_DIV,
43 p_CLKOS_DIV=self.CLKOS_DIV,
44 p_CLKOS2_DIV=self.CLKOS2_DIV,
45 p_CLKOS3_DIV=self.CLKOS3_DIV,
46 p_CLKFB_DIV=self.CLKFB_DIV,
47 p_CLKI_DIV=self.CLKI_DIV,
48 p_FEEDBK_PATH='CLKOP',
49 #p_FREQUENCY_PIN_CLKOP='200',
50 i_CLKI=self.clkin,
51 #i_CLKFB=clkfb,
52 i_RST=0,
53 i_STDBY=0,
54 i_PHASESEL0=0,
55 i_PHASESEL1=0,
56 i_PHASEDIR=0,
57 i_PHASESTEP=0,
58 i_PLLWAKESYNC=0,
59 i_ENCLKOP=0,
60 i_ENCLKOS=0,
61 i_ENCLKOS2=0,
62 i_ENCLKOS3=0,
63 o_CLKOP=self.clkout1,
64 o_CLKOS=self.clkout2,
65 o_CLKOS2=self.clkout3,
66 o_CLKOS3=self.clkout4,
67 o_LOCK=self.lock,
68 )
69 m = Module()
70 m.submodules += pll
71 with m.If(self.clksel == 0):
72 m.d.comb += clkfb.eq(self.clkout1)
73 with m.Elif(self.clksel == 1):
74 m.d.comb += clkfb.eq(self.clkout2)
75 with m.Elif(self.clksel == 2):
76 m.d.comb += clkfb.eq(self.clkout3)
77 with m.Else():
78 m.d.comb += clkfb.eq(self.clkout4)
79 return m
80
81
82 class ECPIX5CRG(Elaboratable):
83 def __init__(self):
84 self.clkin = Signal()
85
86 def elaborate(self, platform):
87 m = Module()
88
89 # Get 100Mhz from oscillator
90 cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
91 m.d.comb += cd_rawclk.clk.eq(self.clkin)
92 m.domains += cd_rawclk
93
94 # Power-on delay (655us)
95 podcnt = Signal(16, reset=2**16-1)
96 pod_done = Signal()
97 with m.If(podcnt != 0):
98 m.d.rawclk += podcnt.eq(podcnt-1)
99 m.d.comb += pod_done.eq(podcnt == 0)
100
101 # Generating sync2x (200Mhz) and init (25Mhz) from clk100
102 cd_sync2x = ClockDomain("sync2x", local=False)
103 cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=True, reset_less=True)
104 cd_init = ClockDomain("init", local=False)
105 cd_sync = ClockDomain("sync", local=False, reset_less=True)
106 cd_dramsync = ClockDomain("dramsync", local=False)
107 m.submodules.pll = pll = PLL(ClockSignal("rawclk"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=2, CLK2_DIV=16, CLK3_DIV=4,
108 clkout1=ClockSignal("sync2x_unbuf"), clkout2=ClockSignal("init"))
109 m.submodules += Instance("ECLKSYNCB",
110 i_ECLKI = ClockSignal("sync2x_unbuf"),
111 i_STOP = 0,
112 o_ECLKO = ClockSignal("sync2x"))
113 m.domains += cd_sync2x_unbuf
114 m.domains += cd_sync2x
115 m.domains += cd_init
116 m.domains += cd_sync
117 m.domains += cd_dramsync
118 m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
119 m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
120
121 # Generating sync (100Mhz) from sync2x
122
123 m.submodules += Instance("CLKDIVF",
124 p_DIV="2.0",
125 i_ALIGNWD=0,
126 i_CLKI=ClockSignal("sync2x"),
127 i_RST=0,
128 o_CDIVX=ClockSignal("sync"))
129 m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
130
131 return m
132
133 class SimCRGTop(Elaboratable):
134 def __init__(self):
135 self.clkin = Signal()
136
137 self.sync2x = Signal()
138 self.sync = Signal()
139 self.dramsync = Signal()
140 self.init = Signal()
141
142 def elaborate(self, platform):
143 m = Module()
144
145 m.submodules.crg = crg = ECPIX5CRG()
146 m.d.comb += [
147 crg.clkin.eq(self.clkin),
148 self.sync2x.eq(ClockSignal("sync2x")),
149 self.sync.eq(ClockSignal("sync")),
150 self.dramsync.eq(ClockSignal("dramsync")),
151 self.init.eq(ClockSignal("init")),
152 ]
153
154 return m
155
156
157 if __name__ == "__main__":
158 top = SimCRGTop()
159 main(top, name="simcrgtop", ports=[top.clkin, top.sync, top.sync2x, top.dramsync, top.init])