1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
4 from nmigen
.compat
import Case
6 __ALL__
= ["delayed_enter", "RoundRobin", "Timeline"]
8 def delayed_enter(m
, src
, dst
, delay
):
11 for i
in range(delay
):
15 statename
= "{}-{}".format(src
, i
)
20 deststate
= "{}-{}".format(src
, i
+1)
22 with m
.State(statename
):
25 # Original nMigen implementation by HarryHo90sHK
26 class RoundRobin(Elaboratable
):
27 """A round-robin scheduler.
31 Maximum number of requests to handle.
35 Signal where a '1' on the i-th bit represents an incoming request from the i-th device.
36 grant : Signal(range(n))
37 Signal that equals to the index of the device which is currently granted access.
39 Strobe signal to enable granting access to the next device requesting. Externally driven.
41 def __init__(self
, n
):
43 self
.request
= Signal(n
)
44 self
.grant
= Signal(range(n
))
47 def elaborate(self
, platform
):
51 with m
.Switch(self
.grant
):
52 for i
in range(self
.n
):
54 for j
in reversed(range(i
+1, i
+self
.n
)):
55 # If i+1 <= j < n, then t == j; (after i)
56 # If n <= j < i+n, then t == j - n (before i)
58 with m
.If(self
.request
[t
]):
59 m
.d
.sync
+= self
.grant
.eq(t
)
63 class Timeline(Elaboratable
):
64 def __init__(self
, events
):
65 self
.trigger
= Signal()
68 def elaborate(self
, platform
):
71 lastevent
= max([e
[0] for e
in self
._events
])
72 counter
= Signal(range(lastevent
+1))
74 # Counter incrementation
75 # (with overflow handling)
76 if (lastevent
& (lastevent
+ 1)) != 0:
77 with m
.If(counter
== lastevent
):
78 m
.d
.sync
+= counter
.eq(0)
80 with m
.If(counter
!= 0):
81 m
.d
.sync
+= counter
.eq(counter
+1)
82 with m
.Elif(self
.trigger
):
83 m
.d
.sync
+= counter
.eq(1)
85 with m
.If(counter
!= 0):
86 m
.d
.sync
+= counter
.eq(counter
+1)
87 with m
.Elif(self
.trigger
):
88 m
.d
.sync
+= counter
.eq(1)
90 for e
in self
._events
:
92 with m
.If(self
.trigger
& (counter
== 0)):
95 with m
.If(counter
== e
[0]):