<Sarayan>
uart.py:83: UnusedElaboratable: <__main__.UART object at 0x7f8caacef3c8> created but never used
<cr1901_modern>
"python uart.py simulate"
<Sarayan>
does nothing visible
<cr1901_modern>
or "python uart.py generate"
<cr1901_modern>
well, sprinkle some print functions ;)
<Sarayan>
generate generates... stuff, which I guess is verilog?
<Sarayan>
I've only done vhdl in my checkered past
<cr1901_modern>
yes, it's verilog
<Sarayan>
oh, uart.gtkw and uart.vcd
<Sarayan>
was created
<cr1901_modern>
oh yes, that too
* cr1901_modern
forgot
<ZirconiumX>
I think you need to print things to get output from the simulator running, Sarayan
proteusguy has quit [Ping timeout: 244 seconds]
proteusguy has joined #m-labs
<Sarayan>
ok, the .gtkw looks very good under gtkwave
<Sarayan>
verrrrrrrrrrrrry nice
<Sarayan>
Ok, I want to try to convert my wd1772 (floppy disk controller) schematic to nmigen (mostly by hand)
<Sarayan>
I don't know how I can handle the clocks
<Sarayan>
There's a conditional divider by two at the start, and more importantly there's a pll-generated clock in the middle
<cr1901_modern>
I thought the wd1772 used a synchronous counter for clock recovery
<Sarayan>
the pll-generated clock clocking 90% of thehip in practice
<Sarayan>
Oh, th edges are very probably in sync with the initial 8MHz clock, but it's not 100% stable since it depends on the floppy input
<Sarayan>
I suspect it's going to be around 1 or 2 MHz
<Sarayan>
not sure yet
<cr1901_modern>
Sarayan: For an example of multiple clocks, look at examples/por.py
<Sarayan>
thanks
<cr1901_modern>
this creates a generic "power on reset" circuit that works on any FPGA (and relies on the ability of an FPGA to initialize registers to a defined value)
Gurty has quit [Ping timeout: 276 seconds]
Gurty has joined #m-labs
Gurty has quit [Changing host]
Gurty has joined #m-labs
<cr1901_modern>
whitequark: How does the pysim decide which task to call first when it starts running? Is Passive() a message that says "don't call me again if there's nothing to do, I will be called in response to external events happening"?
<whitequark>
no
<whitequark>
pysim goes through tasks in the order they were added iirc
<whitequark>
but i think its code and interface need review
<cr1901_modern>
What does Passive() do?
<whitequark>
makes it so that run() ignores that task
<cr1901_modern>
ahhh, in the uart example you call Passive() immediately in loopback_proc
<cr1901_modern>
so it's completely ignored then?
<cr1901_modern>
oh wait, it has to be
<cr1901_modern>
otherwise the sim would never end
<whitequark>
it's not ignored
<cr1901_modern>
it runs the first statement in the loopback task, but the "while True" loop never runs*
<whitequark>
the while True obviously runs
<whitequark>
or the test would fail
<cr1901_modern>
ooooh okay, I think I get it now
<cr1901_modern>
And yea, that makes sense
rohitksingh has joined #m-labs
<cr1901_modern>
If I were to remove the Passive(), I think the simulation would never end, because run() would be waiting for an infinite loop to finish
<whitequark>
ye
<Sarayan>
re
<Sarayan>
so, I have a schematics with a clk and a /clk line, and mofsets that connects things on these
<Sarayan>
how does that end up in nmigen-land?
<cr1901_modern>
Something like 'm.d.comb += ClockSignal("neg").eq(~ClockSignal("pos"))'
* cr1901_modern
wishes he could take back IRC msgs
<cr1901_modern>
Sarayan: ignore, I misread the question
<Sarayan>
huhuhu
<whitequark>
cr1901_modern: that's almost correct
<Sarayan>
practical example, the firmware block connects the input address to the address decoder in clk0, drives up the rom metal lines on clk1, connects the metal lines to the output on clk0
<whitequark>
Sarayan: so there are basically two clock domains in that case, right?
<whitequark>
one clock domain has logic triggered on posedge, another on negedge
<Sarayan>
there actually are six (three clocks signals, neg/pos) but two for a start
<Sarayan>
technically, since it's mosfet, it's on level, not edge
<whitequark>
I would personally do something like
<Sarayan>
but that doesn't really matter
<whitequark>
hm
<whitequark>
right, so I'd do this
<whitequark>
m.d.ck0p += <logic on domain 0 posedge>
<whitequark>
m.d.ck1n += <logic on domain 1 negedge>
<whitequark>
and so on
<whitequark>
then at toplevel I would add a clock generator block that generates six signals in appropriate polarity and phase.
<cr1901_modern>
I backed off because I wasn't sure whether nmigen allows the negative edge to be used for events
<Sarayan>
ck1n, not ck0n?
<whitequark>
Sarayan: you said three domains
<Sarayan>
ah ok
<whitequark>
so I picked two different domains, two differente dges for an example
<whitequark>
cr1901_modern: it does not currently allow negedge domains
<whitequark>
but it's easy enough to add that if necessary
<Sarayan>
most of the chip is on one, so I'm going to start on that one
<cr1901_modern>
Ahhh okay
<Sarayan>
so ck0n/ck0p
<whitequark>
yup
<Sarayan>
How do I create them and how do Isim them?
<cr1901_modern>
Sarayan: Anything that should occur on a negative edge, for now you will need to invert ck0n as it comes into your design from the outside world
<Sarayan>
I need to test it? I thought it was implictely going to logical one when the combinatorics happened
<whitequark>
Sarayan: you do this: m.clock_domains += ClockDomain("ck0n"), ClockDomain("ck0n")
<whitequark>
for simulation, you probably should convert to Verilog and use something like iverilog or verilator
<whitequark>
nmigen's internal simulator is definitely not fast enough for your design
<Sarayan>
It's not going to be a big design
<whitequark>
nmigen's internal simulator is extremely slow
<Sarayan>
at least for a while
<Sarayan>
that bad?
<whitequark>
I wrote it using some Python features I should not have used for it
<whitequark>
well, it was fine for a proof of concept, but it needs rework
<Sarayan>
m.clock_domains is in which elaborate?
<Sarayan>
all of them?
<cr1901_modern>
hehehe
<whitequark>
exactly one
<whitequark>
usually the toplevel one
<Sarayan>
top level?
<Sarayan>
can I say "x and y are connected" independently of any clock?
<whitequark>
yes. m.d.comb += x.eq(y) [or y.eq(x)
<whitequark>
note that all connections in nmigen (or synthesizable verilog for that matter) are direction
<whitequark>
*directional
<whitequark>
if you have multiple drives for some wire, you need to manually add a mux
<whitequark>
or something like wired-OR or wired-AND
<Sarayan>
dest.eq(src)
<whitequark>
yes.
<Sarayan>
I'm going to need wired-and quickly actually
<whitequark>
sure. wired-AND becomes... AND.
<whitequark>
dest.eq(src1 & src2)
<Sarayan>
I'd rather not *immediatly* go into the iverilog hole, how do I drive ck0n/ck0p from python?
<whitequark>
let's see
<Sarayan>
(I'd rather have something that slightly orks first)
<whitequark>
this will work well as long as you feed the stimulus in on the edge of the same domain, like always on ck0p for example
<Sarayan>
I can do that, yes
<cr1901_modern>
Tick("clk") waits for the specified clock to tick?
<whitequark>
yes
<whitequark>
note that after `yield Tick("clk")` returned you are still observing the combinatorial values from the *previous* cycle
rohitksingh has quit [Ping timeout: 245 seconds]
<whitequark>
basically, `yield Tick("clk")` makes Python code that pretends to be a DFF
<whitequark>
cr1901_modern: reading your question now
<whitequark>
cr1901_modern: oof. I can't tell you a definite answer to that
<whitequark>
I'd have to go line by line with old and new code and compare
<cr1901_modern>
If you don't get around to it, I will
<whitequark>
the "Local Clock Domain" part doesn't apply for sure though
<cr1901_modern>
I had to do the same to write that doc for omigen
<whitequark>
wait
<whitequark>
oh I see, you're describing observable semantics, not internal semantics
<cr1901_modern>
Yes
<cr1901_modern>
Though I had to dig through omigen internals to write that doc anyway
<cr1901_modern>
In omigen, when you declared a clock domain, the observable semantics were basically that your clock domain name was added to a global namespace of clock domains (with the exception listed in the linked section)
<cr1901_modern>
So you could reference it anywhere in your omigen design in any module (ClockDomain("clk"), self.sync.clk += ...), and omigen would be able to uniquely resolve it to whatever Module actually declared the domain
<whitequark>
nmigen *first* renames domains and *then* resolves references to them
<whitequark>
except when renaming domains it also renames referencs accordingly
<whitequark>
so the observable semantics ends up the same
<Sarayan>
ok, it's not working, and why promises to be interesting
<whitequark>
Sarayan: do you want a combinatorial memory read port?
<whitequark>
then do read_port(domain="comb")
<Sarayan>
I'm not sure I understand the question
<whitequark>
by default, nmigen treats memories as synchronous devices
<whitequark>
memory ports*
<whitequark>
read_port() is the same as read_port(domain="sync"), so on each posedge in the sync domain, the port places the output in rdport.data
<whitequark>
your code seems to be written in a way that treats a port as a combinatorial device
<whitequark>
in that case, you want to do read_port(domain="comb")
<Sarayan>
pretty much, yes
<whitequark>
so that you get the output in .data one delta cycle after you change .addr
<Sarayan>
I probably should sync it on ck0n?
<Sarayan>
and drop l_*
<whitequark>
that would also work I think
<Sarayan>
changed, pushed, no change
<Sarayan>
If the init going wrong?
<Sarayan>
Is
<whitequark>
looking
<whitequark>
oh
<whitequark>
you forgot to add firmware as a submodule
<whitequark>
m.submodules += self.m_firmware
<whitequark>
didn't you get a warning when you run it?
<whitequark>
something like Elaboratable defined but not used
<Sarayan>
yes
<Sarayan>
so that what it means :-)
<whitequark>
yeah, that's why. it is a very common error in migen... which is why i spent a lot of time adding a warning
<Sarayan>
and it works, *nice*
<whitequark>
:D
<Sarayan>
now I just have to build, well, evrything else
<Sarayan>
I'll annoy you again when I add clocks, some generated from others and stuff, but that's going to be in a whike
<whitequark>
sure
<whitequark>
Sarayan: oh and one last thing, do you have any logic driven from both edges?
<Sarayan>
I don't know
<Sarayan>
(yet)
<Sarayan>
... yes, just found one
<whitequark>
how does it look like?
<whitequark>
in nmigen any signal can be driven from exactly 1 clock domain
<Sarayan>
a signal set to 1 on ck0n, to 0 on ck0p && n1997
<whitequark>
oh wtf
<Sarayan>
(where n1997 is some other signal)
<whitequark>
what does it eventually do?
<Sarayan>
not 100% sure, looks like it *may* be pc increment
<Sarayan>
inverted I suspect
<Sarayan>
not sure of anything
<whitequark>
that looks like it'd have to be replaced with its logical equivalent I think
<Sarayan>
ok
<Sarayan>
goes into combinational histrionics that copy over on ck0p
<whitequark>
yeah, it seems like it's just !n1997?
<whitequark>
(active high)
<Sarayan>
possibly, not sure on the timings on n1997 itself
<Sarayan>
otoh... since the output is not used on both edges only one matters
<whitequark>
yes, that's what I mean
<whitequark>
tbh what really bothers me is the PLL
<Sarayan>
yeah, I'm going to avoid it for now
<Sarayan>
gonna work on everything *after* the pll
<cr1901_modern>
>that looks like it'd have to be replaced with its logical equivalent I think
<cr1901_modern>
What does this mean, btw?
<whitequark>
I think it would be feasible, in worst case, to make the entire circuit work at (3*n)x the original clock
<whitequark>
where n is the amount of oversampling needed for PLL in digital domain
<whitequark>
it's not trivial how to demonstrate correctness of the DPLL though...
<whitequark>
but at least even iCE40 is much faster than 8 MHz
<Sarayan>
the pll is digital, and already 16x oversampled
<whitequark>
ohhhhh
<whitequark>
so its clock output is phase related to the input clock?
<Sarayan>
remember, dd transitions are on 2us edges, so 8MHz is 16 times that
<whitequark>
then it looks like its clock output can be replaced with enable output and downstream FFs be replaced with DFFEs
<whitequark>
that would be ideal
<Sarayan>
yeah, and I suspect it's 1 or 2 MHz
<whitequark>
because it would map perfectly to any FPGA
<whitequark>
cr1901_modern: exactly what it says on the tin
<Sarayan>
Well, you'll teach me that once I have more stuff working :-)
<whitequark>
sure
<Sarayan>
I'd like to try to run the firmware
<Sarayan>
(which I don't currently understand, in practice)
<cr1901_modern>
whitequark: That doesn't tell me anything, do you mean "route out both clocks" and put the equivalent logic to drive the signal from both clocks in "comb"?
* cr1901_modern
makes an example
<Sarayan>
cr1901: ignore the signal on the edge that doesn't matter, compute it (inversion in that case) on the one where it does, turning the dynamic logic into static one
<cr1901_modern>
ahh
<whitequark>
Sarayan: ah yeah, that's a nice goal
<Sarayan>
ok, one last thing (you wish)
<whitequark>
sure
<Sarayan>
I have a 19-bits rom output
mauz555 has quit []
<Sarayan>
I have n2183 = !(rom[8] || rom[6] || rom[4] || !(rom[5] && rom[7] && rom[3]))