From: Harry Ho Date: Wed, 29 Jan 2020 04:14:11 +0000 (+0800) Subject: wishbone: fix that RoundRobin might assert CYC indefinitely X-Git-Tag: 24jan2021_ls180~22 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=976cef46fd5c2661eb22262dc135ebfa38097883;p=nmigen-soc.git wishbone: fix that RoundRobin might assert CYC indefinitely --- diff --git a/nmigen_soc/scheduler.py b/nmigen_soc/scheduler.py index 61b3d16..7af3b10 100644 --- a/nmigen_soc/scheduler.py +++ b/nmigen_soc/scheduler.py @@ -18,22 +18,28 @@ class RoundRobin(Elaboratable): Signal where a '1' on the i-th bit represents an incoming request from the i-th device. grant : Signal(range(n)) Signal that equals to the index of the device which is currently granted access. + stb : Signal() + Strobe signal to enable granting access to the next device requesting. Externally driven. """ def __init__(self, n): self.n = n self.request = Signal(n) self.grant = Signal(range(n)) + self.stb = Signal() def elaborate(self, platform): m = Module() - with m.Switch(self.grant): - for i in range(self.n): - with m.Case(i): - with m.If(~self.request[i]): - for j in reversed(range(i+1, i+self.n)): - t = j % self.n - with m.If(self.request[t]): - m.d.sync += self.grant.eq(t) + with m.If(self.stb): + with m.Switch(self.grant): + for i in range(self.n): + with m.Case(i): + with m.If(~self.request[i]): + for j in reversed(range(i+1, i+self.n)): + # If i+1 <= j < n, then t == j; (after i) + # If n <= j < i+n, then t == j - n (before i) + t = j % self.n + with m.If(self.request[t]): + m.d.sync += self.grant.eq(t) return m \ No newline at end of file diff --git a/nmigen_soc/wishbone/bus.py b/nmigen_soc/wishbone/bus.py index 142b099..7956b24 100644 --- a/nmigen_soc/wishbone/bus.py +++ b/nmigen_soc/wishbone/bus.py @@ -366,13 +366,17 @@ class Arbiter(Elaboratable): if self._scheduler == "rr": m.submodules.scheduler = scheduler = RoundRobin(self._next_index) grant = Signal(self._next_index) - m.d.comb += grant.eq(scheduler.grant) + m.d.comb += [ + # CYC should not be indefinitely asserted. (See RECOMMENDATION 3.05, Wishbone B4) + scheduler.stb.eq(~self.bus.cyc), + grant.eq(scheduler.grant) + ] for signal_name, (_, signal_direction) in self.bus.layout.fields.items(): # FANOUT signals: only mux the granted master with the interface if signal_direction == Direction.FANOUT: - master_signals = Array(getattr(master_bus, signal_name) - for __, (___, master_bus) + master_signals = Array(getattr(master_bus, signal_name) + for __, (___, master_bus) in self._masters.items()) m.d.comb += getattr(self.bus, signal_name).eq(master_signals[grant]) # FANIN signals: ACK and ERR are ORed to all masters; @@ -422,7 +426,7 @@ class InterconnectShared(Elaboratable): for target_bus in targets: self._targets.append(target_bus) - + self.arbiter = Arbiter( addr_width=self.addr_width, data_width=self.data_width, @@ -461,4 +465,4 @@ class InterconnectShared(Elaboratable): self.arbiter.bus.connect(self.decoder.bus) ) - return m \ No newline at end of file + return m