-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assigning clock domain to attribute results in failures, radically different RTLIL output #567
Comments
Note, I believe the solution is not to use |
In general, you should only pass clock domain names around. (Take a look at how |
Makes sense. However, when I changed my enormous several thousand line design to use this method (by passing string names around instead of the actual domain, which just resulted in changing maybe 20 lines), I ran into an error that is difficult to debug:
|
That seems like you are misusing the result of |
It's true, I am... somewhere. Now I have to track it do--- oh. Yeah. Found it :) I neglected to refactor this one other file. |
I'm ok with closing out this question with the answer: don't do that, and instead use clock domain names. The updated correct example is: from nmigen import Signal, Module, Elaboratable, ClockSignal, ResetSignal, ClockDomain
from nmigen.build import Platform
from nmigen.asserts import Assert, Assume, Past, Rose
from nmigen.cli import main_parser, main_runner
class Example(Elaboratable):
def __init__(self, clk: str):
self.clk = clk
self.d0 = Signal(32)
self.d1 = Signal(32)
self.sel = Signal(2)
self.q = Signal(32)
def elaborate(self, _: Platform) -> Module:
m = Module()
c = m.d[self.clk]
with m.If(self.sel[0]):
c += self.q.eq(self.d0)
with m.Elif(self.sel[1]):
c += self.q.eq(self.d1)
return m
def formal():
"""Formal verification for the example."""
parser = main_parser()
args = parser.parse_args()
m = Module()
ph = ClockDomain("ph")
clk = ClockSignal("ph")
m.domains += ph
m.submodules.s = s = Example(clk="ph")
with m.If(Rose(clk)):
with m.Switch(~Past(s.sel)):
with m.Case(0b00):
m.d.comb += Assert(s.q == Past(s.q))
with m.Case(0b10):
m.d.comb += Assert(s.q == Past(s.d0))
with m.Case(0b01):
m.d.comb += Assert(s.q == Past(s.d1))
m.d.sync += clk.eq(~clk)
m.d.comb += Assume(~ResetSignal("ph"))
m.d.comb += Assume(s.sel != 0b11)
main_runner(parser, args, m, ports=[s.d0, s.d1, s.sel, s.q])
if __name__ == "__main__":
formal() |
The idea here is to create a module that does its thing based on whatever clock domain is passed to its
__init__
function.Here's the minimum viable test:
.sby file:
Run as:
$ python3 example.py generate -t il > toplevel.il $ sby -f ics.sby bmc
Replacing
c = self.clk
withc = m.d.ph
makes the example work. Otherwise, it fails bmc.We can also see that with
c = self.clk
, the RTLIL output bad.zip is very different from the output withc = m.d.ph
: good.zipInterestingly, modifying the example to eliminate the
Elif
makes the example work:The text was updated successfully, but these errors were encountered: