Add more memory tests
[gram.git] / gram / simulation / crg.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2
3 from nmigen import *
4
5 __ALL__ = ["ECPIX5CRG"]
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=2, CLK1_DIV=3, CLK2_DIV=24):
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.ports = [
21 self.clkin,
22 self.clkout1,
23 self.clkout2,
24 self.clkout3,
25 self.clkout4,
26 self.clksel,
27 self.lock,
28 ]
29
30 def elaborate(self, platform):
31 clkfb = Signal()
32 pll = Instance("EHXPLLL",
33 p_OUTDIVIDER_MUXA='DIVA',
34 p_OUTDIVIDER_MUXB='DIVB',
35 p_CLKOP_ENABLE='ENABLED',
36 p_CLKOS_ENABLE='ENABLED',
37 p_CLKOS2_ENABLE='DISABLED',
38 p_CLKOS3_ENABLE='DISABLED',
39 p_CLKOP_DIV=self.CLKOP_DIV,
40 p_CLKOS_DIV=self.CLKOS_DIV,
41 p_CLKFB_DIV=self.CLKFB_DIV,
42 p_CLKI_DIV=self.CLKI_DIV,
43 p_FEEDBK_PATH='INT_OP',
44 p_CLKOP_TRIM_POL="FALLING",
45 p_CLKOP_TRIM_DELAY=0,
46 p_CLKOS_TRIM_POL="FALLING",
47 p_CLKOS_TRIM_DELAY=0,
48 p_CLKOP_CPHASE=2,
49 p_CLKOS_CPHASE=23,
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_PHASELOADREG=0,
59 i_PLLWAKESYNC=0,
60 i_ENCLKOP=1,
61 i_ENCLKOS=1,
62 i_ENCLKOS2=0,
63 i_ENCLKOS3=0,
64 o_CLKOP=self.clkout1,
65 o_CLKOS=self.clkout2,
66 o_CLKOS2=self.clkout3,
67 o_CLKOS3=self.clkout4,
68 o_LOCK=self.lock,
69 )
70 m = Module()
71 m.submodules += pll
72 with m.If(self.clksel == 0):
73 m.d.comb += clkfb.eq(self.clkout1)
74 with m.Elif(self.clksel == 1):
75 m.d.comb += clkfb.eq(self.clkout2)
76 with m.Elif(self.clksel == 2):
77 m.d.comb += clkfb.eq(self.clkout3)
78 with m.Else():
79 m.d.comb += clkfb.eq(self.clkout4)
80 return m
81
82
83 class ECPIX5CRG(Elaboratable):
84 def __init__(self):
85 ...
86
87 def elaborate(self, platform):
88 m = Module()
89
90 # Get 100Mhz from oscillator
91 clk100 = platform.request("clk100")
92 cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
93 m.d.comb += cd_rawclk.clk.eq(clk100)
94 m.domains += cd_rawclk
95
96 # Reset
97 reset = platform.request(platform.default_rst).i
98 gsr0 = Signal()
99 gsr1 = Signal()
100
101 m.submodules += [
102 Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"), i_D=~reset, o_Q=gsr0),
103 Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"), i_D=gsr0, o_Q=gsr1),
104 Instance("SGSR", i_CLK=ClockSignal("rawclk"), i_GSR=gsr1),
105 ]
106
107 # Power-on delay (655us)
108 podcnt = Signal(16, reset=2**16-1)
109 pod_done = Signal()
110 with m.If(podcnt != 0):
111 m.d.rawclk += podcnt.eq(podcnt-1)
112 m.d.comb += pod_done.eq(podcnt == 0)
113
114 # Generating sync2x (200Mhz) and init (25Mhz) from clk100
115 cd_sync2x = ClockDomain("sync2x", local=False)
116 cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=False, reset_less=True)
117 cd_init = ClockDomain("init", local=False)
118 cd_sync = ClockDomain("sync", local=False)
119 cd_dramsync = ClockDomain("dramsync", local=False)
120 m.submodules.pll = pll = PLL(ClockSignal("rawclk"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=1, CLK2_DIV=4,
121 clkout1=ClockSignal("sync2x_unbuf"), clkout2=ClockSignal("init"))
122 m.submodules += Instance("ECLKSYNCB",
123 i_ECLKI = ClockSignal("sync2x_unbuf"),
124 i_STOP = 0,
125 o_ECLKO = ClockSignal("sync2x"))
126 m.domains += cd_sync2x_unbuf
127 m.domains += cd_sync2x
128 m.domains += cd_init
129 m.domains += cd_sync
130 m.domains += cd_dramsync
131 m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
132 m.d.comb += ResetSignal("sync").eq(~pll.lock|~pod_done)
133 m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
134
135 # # Generating sync (100Mhz) from sync2x
136
137 m.submodules += Instance("CLKDIVF",
138 p_DIV="2.0",
139 i_ALIGNWD=0,
140 i_CLKI=ClockSignal("sync2x"),
141 i_RST=0,
142 o_CDIVX=ClockSignal("sync"))
143 m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
144
145 return m