5
5
from migen .bank .description import *
6
6
7
7
class DataCapture (Module , AutoReg ):
8
- def __init__ (self , ntbits , debug = False ):
8
+ def __init__ (self , ntbits ):
9
9
self .pad = Signal ()
10
10
self .serdesstrobe = Signal ()
11
11
self .d0 = Signal () # pix5x clock domain
12
12
self .d1 = Signal () # pix5x clock domain
13
13
14
- if debug :
15
- self ._r_current_tap = RegisterField (8 , READ_ONLY , WRITE_ONLY )
14
+ self ._r_dly_ctl = RegisterRaw (4 )
15
+ self ._r_dly_busy = RegisterField (1 , READ_ONLY , WRITE_ONLY )
16
+ self ._r_phase = RegisterField (2 , READ_ONLY , WRITE_ONLY )
17
+ self ._r_phase_reset = RegisterRaw ()
16
18
17
19
###
18
20
19
21
# IO
20
22
pad_delayed = Signal ()
21
23
delay_inc = Signal ()
22
24
delay_ce = Signal ()
25
+ delay_cal = Signal ()
26
+ delay_rst = Signal ()
27
+ delay_busy = Signal ()
23
28
self .specials += Instance ("IODELAY2" ,
24
29
Instance .Parameter ("DELAY_SRC" , "IDATAIN" ),
25
- Instance .Parameter ("IDELAY_TYPE" , "VARIABLE_FROM_ZERO " ),
30
+ Instance .Parameter ("IDELAY_TYPE" , "VARIABLE_FROM_HALF_MAX " ),
26
31
Instance .Parameter ("COUNTER_WRAPAROUND" , "STAY_AT_LIMIT" ),
27
32
Instance .Parameter ("DATA_RATE" , "SDR" ),
28
33
Instance .Input ("IDATAIN" , self .pad ),
29
34
Instance .Output ("DATAOUT" , pad_delayed ),
35
+ Instance .Input ("CLK" , ClockSignal ("pix5x" )),
36
+ Instance .Input ("IOCLK0" , ClockSignal ("pix10x" )),
30
37
Instance .Input ("INC" , delay_inc ),
31
38
Instance .Input ("CE" , delay_ce ),
32
- Instance .Input ("RST" , ResetSignal ("pix5x" )),
33
- Instance .Input ("CLK" , ClockSignal ("pix5x" )),
34
- Instance .Input ("IOCLK0" , ClockSignal ("pix20x" )),
35
- Instance .Input ("CAL" , 0 ),
39
+ Instance .Input ("CAL" , delay_cal ),
40
+ Instance .Input ("RST" , delay_rst ),
41
+ Instance .Output ("BUSY" , delay_busy ),
36
42
Instance .Input ("T" , 1 )
37
43
)
38
44
@@ -57,23 +63,19 @@ def __init__(self, ntbits, debug=False):
57
63
Instance .Input ("RST" , 0 )
58
64
)
59
65
60
- # Transition counter
61
- transitions = Signal (ntbits )
62
- lateness = Signal ((ntbits + 1 , True ))
63
- pulse_inc = Signal ()
64
- pulse_dec = Signal ()
66
+ # Phase detector
67
+ lateness = Signal (ntbits , reset = 2 ** (ntbits - 1 ))
68
+ too_late = Signal ()
69
+ too_early = Signal ()
70
+ reset_lateness = Signal ()
71
+ self .comb += [
72
+ too_late .eq (lateness == (2 ** ntbits - 1 )),
73
+ too_early .eq (lateness == 0 )
74
+ ]
65
75
self .sync .pix5x += [
66
- pulse_inc .eq (0 ),
67
- pulse_dec .eq (0 ),
68
- If (transitions == 2 ** ntbits - 1 ,
69
- If (lateness [ntbits ],
70
- pulse_inc .eq (1 )
71
- ).Else (
72
- pulse_dec .eq (1 )
73
- ),
74
- lateness .eq (0 ),
75
- transitions .eq (0 )
76
- ).Elif (self .d0 != self .d1 ,
76
+ If (reset_lateness ,
77
+ lateness .eq (2 ** (ntbits - 1 ))
78
+ ).Elif (~ delay_busy & ~ too_late & ~ too_early & (self .d0 != self .d1 ),
77
79
If (self .d0 ,
78
80
# 1 -----> 0
79
81
# d0p
@@ -90,39 +92,57 @@ def __init__(self, ntbits, debug=False):
90
92
).Else (
91
93
lateness .eq (lateness - 1 )
92
94
)
93
- ),
94
- transitions .eq (transitions + 1 )
95
+ )
96
+ )
97
+ ]
98
+
99
+ # Delay control
100
+ self .submodules .delay_done = PulseSynchronizer ("pix5x" , "sys" )
101
+ delay_pending = Signal ()
102
+ self .sync .pix5x += [
103
+ self .delay_done .i .eq (0 ),
104
+ If (~ delay_pending ,
105
+ If (delay_cal | delay_ce , delay_pending .eq (1 ))
106
+ ).Else (
107
+ If (~ delay_busy ,
108
+ self .delay_done .i .eq (1 ),
109
+ delay_pending .eq (0 )
110
+ )
95
111
)
96
112
]
97
113
98
- # Drive IODELAY controls
99
- delay_init = Signal ()
100
- delay_init_count = Signal (7 , reset = 127 )
101
- self .comb += delay_init .eq (delay_init_count != 0 )
102
- self .sync .pix5x += If (delay_init , delay_init_count .eq (delay_init_count - 1 ))
114
+ self .submodules .do_delay_cal = PulseSynchronizer ("sys" , "pix5x" )
115
+ self .submodules .do_delay_rst = PulseSynchronizer ("sys" , "pix5x" )
116
+ self .submodules .do_delay_inc = PulseSynchronizer ("sys" , "pix5x" )
117
+ self .submodules .do_delay_dec = PulseSynchronizer ("sys" , "pix5x" )
103
118
self .comb += [
104
- delay_ce .eq (delay_init | pulse_inc | pulse_dec ),
105
- delay_inc .eq (delay_init | pulse_inc )
119
+ delay_cal .eq (self .do_delay_cal .o ),
120
+ delay_rst .eq (self .do_delay_rst .o ),
121
+ delay_inc .eq (self .do_delay_inc .o ),
122
+ delay_ce .eq (self .do_delay_inc .o | self .do_delay_dec .o ),
106
123
]
107
124
108
- # Debug
109
- if debug :
110
- # Transfer delay update commands to system clock domain
111
- pix5x_reset_sys = Signal ()
112
- self .specials += MultiReg (ResetSignal ("pix5x" ), pix5x_reset_sys , "sys" )
113
- self .submodules .xf_inc = PulseSynchronizer ("pix5x" , "sys" )
114
- self .submodules .xf_dec = PulseSynchronizer ("pix5x" , "sys" )
115
- self .comb += [
116
- self .xf_inc .i .eq (pulse_inc ),
117
- self .xf_dec .i .eq (pulse_dec )
118
- ]
119
- # Update tap count in system clock domain
120
- current_tap = Signal (8 , reset = 127 )
121
- self .comb += self ._r_current_tap .field .w .eq (current_tap )
122
- self .sync += If (pix5x_reset_sys ,
123
- current_tap .eq (127 )
124
- ).Elif (self .xf_inc .o & (current_tap != 0xff ),
125
- current_tap .eq (current_tap + 1 )
126
- ).Elif (self .xf_dec .o & (current_tap != 0 ),
127
- current_tap .eq (current_tap - 1 )
128
- )
125
+ sys_delay_pending = Signal ()
126
+ self .sync += [
127
+ If (self .do_delay_cal .i | self .do_delay_inc .i | self .do_delay_dec .i ,
128
+ sys_delay_pending .eq (1 )
129
+ ).Elif (self .delay_done .o ,
130
+ sys_delay_pending .eq (0 )
131
+ )
132
+ ]
133
+
134
+ self .comb += [
135
+ self .do_delay_cal .i .eq (self ._r_dly_ctl .re & self ._r_dly_ctl .r [0 ]),
136
+ self .do_delay_rst .i .eq (self ._r_dly_ctl .re & self ._r_dly_ctl .r [1 ]),
137
+ self .do_delay_inc .i .eq (self ._r_dly_ctl .re & self ._r_dly_ctl .r [2 ]),
138
+ self .do_delay_dec .i .eq (self ._r_dly_ctl .re & self ._r_dly_ctl .r [3 ]),
139
+ self ._r_dly_busy .field .w .eq (sys_delay_pending )
140
+ ]
141
+
142
+ # Phase detector control
143
+ self .specials += MultiReg (Cat (too_late , too_early ), self ._r_phase .field .w )
144
+ self .submodules .do_reset_lateness = PulseSynchronizer ("sys" , "pix5x" )
145
+ self .comb += [
146
+ reset_lateness .eq (self .do_reset_lateness .o ),
147
+ self .do_reset_lateness .i .eq (self ._r_phase_reset .re )
148
+ ]
0 commit comments