ChanServ changed the topic of #nmigen to: nMigen hardware description language · code at https://github.com/nmigen · logs at https://freenode.irclog.whitequark.org/nmigen · IRC meetings each Monday at 1800 UTC · next meeting TBD
lf has quit [Ping timeout: 260 seconds]
lf has joined #nmigen
vup2 is now known as vup
<_whitenotifier> [YoWASP/yosys] whitequark pushed 1 commit to develop [+0/-0/±1] https://git.io/JtOaQ
<_whitenotifier> [YoWASP/yosys] whitequark ddd87c2 - Update dependencies.
emeb has quit [Quit: Leaving.]
modwizcode has quit [Quit: Later]
modwizcode has joined #nmigen
electronic_eel has quit [Ping timeout: 256 seconds]
electronic_eel has joined #nmigen
Degi_ has joined #nmigen
Degi has quit [Ping timeout: 265 seconds]
Degi_ is now known as Degi
Bertl_oO is now known as Bertl_zZ
PyroPeter_ has joined #nmigen
PyroPeter has quit [Ping timeout: 265 seconds]
PyroPeter_ is now known as PyroPeter
Yatekii has quit [Ping timeout: 246 seconds]
emeb_mac has quit [Quit: Leaving.]
bvernoux has joined #nmigen
jjeanthom has joined #nmigen
<_florent_> Hi, cr1901_modern: my point with "This is not a long term solution" is that the use of the compat layer in LiteX would just be temporary and it's not just a matter of changing the import.
<_florent_> This has to be done at a point in time where things are simplified/stabilized with good unit-tests and that's where the current efforts are put into.
<_florent_> Also like Migen, LiteX has its own flaws and this has to be pondered if a switch to nMigen with current LiteX codebase would be a good decision or if a complete reboot as a different project would be more interesting (both approaches have advantages/disavantages).
<_florent_> So the situation is maybe not ideal, creating design with nMigen/LiteX is already possible but less convenient than it could be, but the important thing is that both projects are improving things on the open-hardware FPGA front, with a friendly communities and are stimulating I think for each others.
<_florent_> I'm for example admirative of the work done on nMigen/CXXRTL/Glasgow and can't wait to receive the Glasgows ordered from the crowdsupply campaign to play a bit more with nMigen :)
jjeanthom has quit [Ping timeout: 265 seconds]
cesar[m]1 has quit [Ping timeout: 268 seconds]
jfng has quit [Ping timeout: 268 seconds]
JJJollyjim has quit [Ping timeout: 240 seconds]
whitequark[m] has quit [Ping timeout: 244 seconds]
emily has quit [Ping timeout: 240 seconds]
blazra has quit [Ping timeout: 260 seconds]
blazra has joined #nmigen
emily has joined #nmigen
whitequark[m] has joined #nmigen
cesar[m] has joined #nmigen
JJJollyjim has joined #nmigen
jfng has joined #nmigen
Bertl_zZ is now known as Bertl
pftbest has joined #nmigen
<cr1901_modern> pftbest: Ahhh, there's a familiar name :P
<pftbest> @cr1901_modern: it's a small world :)
slan has joined #nmigen
jjeanthom has joined #nmigen
pftbest has quit [Remote host closed the connection]
pftbest has joined #nmigen
Yatekii has joined #nmigen
<awygle> welcome pftbest :-)
<pftbest> awygle: hello to you too
<pftbest> I recently purchased ECPIX-5 board just to play around, and it says nMigen right on the box
<pftbest> So i decided to try it out. but so far it looks a bit strange compared to chisel/spinal
jjeanthom has quit [Ping timeout: 260 seconds]
zignig has joined #nmigen
* zignig has resoldered the TInyBX and has Console on my Boneless-v3 again , screen failure and a burnt graphics card later.
<zignig> phew.
jjeanthom has joined #nmigen
chipmuenk has joined #nmigen
jjeanthom has quit [Ping timeout: 264 seconds]
pftbest has quit [Remote host closed the connection]
pftbest has joined #nmigen
pftbest has quit [Remote host closed the connection]
pftbest has joined #nmigen
peeps[zen] has joined #nmigen
peepsalot has quit [Ping timeout: 240 seconds]
peepsalot has joined #nmigen
peeps[zen] has quit [Ping timeout: 265 seconds]
peeps[zen] has joined #nmigen
peepsalot has quit [Ping timeout: 265 seconds]
emeb has joined #nmigen
emeb_mac has joined #nmigen
<lkcl> pftbest: it's... initially strange but pretty damn good. the fact that python is known by around 30% of programmers according to the TIOBE index kinda helps :)
<lkcl> it took me... about... 2-3 weeks to adapt/learn after going through excellent tutorials online
<lkcl> and by god is it worth it. being able to write multiply-inheritable classes, read CSV files using python, do... "normal" stuff, i mean...
<lkcl> the "weirdness" is the fact that "it's not the language itself, it's not a language itself". the nmigen code creates an actual Abstract Syntax Tree. m.d.comb += x.eq(5) means "create an in-memory AST fragment where x is assigned to 5 and add that to the combinatorial circuit domain"
<lkcl> contrast that with myhdl where they LITERALLY re-interpret the actual python program as if it was an HDL programming language.
<lkcl> meaning: you absolutely cannot mix in reading of e.g. CSV files, or use python exceptions, in myhdl, because the actual *python* code is language-translated into verilog
<pftbest> I'm mostly confused by the Signal concept at the moment, in chisel/spinal you explicitly specify if you want a register or a wire, but it looks like nMigen is using a Signal class for both
<lkcl> yes. and it works out for you which to use
<pftbest> and then somehow infers if you want a register or not
<lkcl> yes. if you use m.d.sync that will create latches/registers for you
<lkcl> if you add it to m.d.comb it will create combinatorial circuits
<agg> it's not inferred as such, assignments to comb are wired and assignments to other clock domain generate registers
<lkcl> agg: thx
<lkcl> pftbest, what agg said :)
<lkcl> it's best if you do some examples, create the verilog output (use yosys manually if you prefer) and have a look at the output
<agg> with a and b as Signal, m.d.comb += a.eq(b) is a wired assignment, m.d.sync += a.eq(b) makes a register clocked by 'sync' with b as input and a as output
<lkcl> you'll quickly go "oh yeah that's generated all the @rising_edge nonsense for me. huh. cool"
<lkcl> :)
<agg> i share lkcl's enthusiasm for the general concept, creating the circuit from general purpose python is very productive and powerful
<lkcl> pftbest, btw i wasn't kidding about reading CSV files. this code is *under one percent* nmigen - you have to look really hard to actually find it uses Cat(), m.Switch() and m.Case() :)
<lkcl> https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder.py;hb=HEAD
<lkcl> that's a recursively-generated OpenPOWER ISA decoder, by reading CSV files that contain the fields to be decoded and the instructions to add to a recursively-cascading hierarchical set of switch/case statements!
<hell__> O_o
<lkcl> with dynamically-selectable row *and* column filtering, where we can create *per-pipeline* filtered subsets
<pftbest> For example, I wrote a blinky example like this http://88.99.85.67:1337/a.png
<pftbest> and I'm looking at the verilog code and I see 2 registers for a counter
<lkcl> looks great to me
<pftbest> wrong link sorry sorry
<pftbest> and I don't know why it needs 2 registers herer
<lkcl> initial value most like.
<lkcl> counter$next is the value of the register after the sync.
<lkcl> that's a very common coding technique even in manually-written verilog.
<lkcl> the ariane team did that.
<lkcl> use combinatorial code to create the values
<lkcl> then follow up with assignment of those combinatorially-computed values into registers
<lkcl> with names prefixed with "n" and "q" to distinguish them
<lkcl> microwatt does something similar in their VHDL code as well
<pftbest> but after I do synth_ecp5 then in the end I have only one 27 bit FF in implementation, so I guess it's all good.
<lkcl> :)
<pftbest> so it seems to optimize it out
peeps[zen] is now known as peepsalot
lf_ has joined #nmigen
lf has quit [Ping timeout: 260 seconds]
<pftbest> lkcl: agg: I cleaned up the code a bit https://dpaste.com/9529JGUN2
<pftbest> but it doesn't look like initial value
<pftbest> I'm still learning fpga s, so this kind of code looks weird to me
<agg> so here 'counter' is your actual counter register, 27 FFs, 'counter$next' is the next value to load into it; a fun verilog thing is that a 'reg' type doesn't mean it will actually be FFs, only if you assign to it inside an edge-sensitive block (*I am sure it is more subtle than this in practice)
<agg> the only FFs instantiated by that verilog is when you have `always @(posedge clk) counter <= \counter$next;`
<agg> the rest I guess you can follow; $1 is the reset-to-0 condition when it reaches your max value, counter$next is either 0 or $4 depending on that $1, and $4 is counter+1
<modwizcode> It'd be interesting to see a tutorial that combined something like nmigen and cxxrtl to show the python input, the verilog output and the cxxrtl output and use the latter two to try and help people understand how the verilog logic looks more clearly.
<modwizcode> While cxxrtl isn't a perfect model or anything, a lot of the ways it generates code are very helpful and clear in terms of understanding intent.
<pftbest> I see, i was expecting reg to always become an FF, but i was wrong
<modwizcode> yeah reg essentially just means "variable"
<modwizcode> wire can (in a weird sort of way) be understood more to indicate something like a c++ reference.
<pftbest> agg: thanks for the link, it's very helpful
lf_ has quit [Ping timeout: 264 seconds]
lf has joined #nmigen
<pftbest> agg: modwizcode: I was working with chisel/rocket-chip before and it never ever generates an @* block, all the code is in "always @(posedge clk)" blocks
<pftbest> so to be honest I don't even understand what @* does exactly
<modwizcode> @* is confusing but triggers whenever any of the input signals used within it change (don't quote me 100% on that)
<modwizcode> but basically it's used to let you do combinational logic inside processes (where you assign to a reg inside a process)
<pftbest> So I had a mental model that every "reg" is a FF, because all my blocks were edge sensitive
<pftbest> but nMigen generates the code a little different
<modwizcode> Yeah that's not correct, reg just means it holds a value. If the value is assigned by clocked logic a flip-flop is inferred, otherwise various other things happen
<modwizcode> If you assign the value in an unclocked block (no posedge/negedge in the @ declaration) you get a latch (if not every path assigns to the value), generally that's not what you want. If every path assigns a specific value, then you (should) get combinational logic.
<modwizcode> The problem is that if you make a mistake (forget a switch case for instance), you can end up with a latch which isn't what you want, without realizing it.
<modwizcode> It's easier and clearer to just never use such blocks generally, which is why nmigen does all comb logic in assignment blocks.
<pftbest> Is it possible to make an asynchronous reset in nMigen? I know in chisel you can't unless you use a special class for that.
<modwizcode> You can use a specific class for it
<modwizcode> that doesn't really explain how to use it though
<pftbest> i mean if you can write a code that will generate "always @(posedge clock or posedge reset) begin" block
<modwizcode> uh.
<pftbest> but thanks for the link I need to try it out
<modwizcode> What I linked is how you do an async reset with async assertion and sync deassertion, it builds on the base block that just does that synchronization by automatically grabbing the ResetSignal which is usually generated automatically (and hence you use ResetSignal to reference it since it doesn't come in as an input)
alexhw has quit [Ping timeout: 268 seconds]
<modwizcode> You can look at that file for how it (and the backing code in AsyncFFSynchronizer) handles the case which will probably help you learn.
<whitequark> pftbest: to be a bit more precise: `reg` can be assigned from always blocks, `wire` can be assigned with `assign` statement
<whitequark> the difference is syntactic, which is why SystemVerilog has just `logic`
<pftbest> and it doesn't matter which one you use, only how you are using it?
<pftbest> i never seen SystemVerilog code, but i guess now my chances to understand it increased a bit if i will ever need to see it, thanks to you all
<whitequark> something like that yeah
chipmuenk has quit [Read error: Connection reset by peer]
pftbest has quit [Remote host closed the connection]
pftbest has joined #nmigen
<d1b2> <dub_dub_11> pftbest this may be a controversial opinion here, but imo if you are starting with FPGAs learning (System)Verilog or VHDL first is probably still best
<awygle> heh, a bold position indeed
<pftbest> that is why i try to read the generated code and understand what it does
<awygle> imo that's kind of the worst of both worlds? because the generated code is not really trying to be idiomatic Verilog. in fact nmigen doesn't even generate verilog, it generates RTLIL which yosys can write out as Verilog
<awygle> (this is because Verilog is not a very good intermediate language as its rules are very esoteric)
<d1b2> <dub_dub_11> yeah that's the thing, I look at my generated code occasionally when debugging and doing wonky things, but it's hard even with verilog knowledge
Bertl is now known as Bertl_oO
<d1b2> <dub_dub_11> I think when I first started using nmigen I did make use of convert() to understand what it was doing, but that's because I already knew verilog so it was fairly easy to see structure in the generated code
<pftbest> when i look at the output from chisel i can see how it corresponds to the code i wrote, and i can debug it in chipscope and observe the signals
<whitequark> awygle: write_verilog is trying to generate idiomatic...ish verilog
<pftbest> but for nMigen i guess it's not the case, the generated code is quite compilcated
<whitequark> it's not doing it very successfully because verilog is utterly heinous and i have failed multiple times to improve the output of write_verilog
<whitequark> pftbest: the reason this happens is because nmigen code basically turns into a netlist and then back into verilog
<whitequark> this allows it to avoid a massive number of bugs that plagued migen
<whitequark> but it comes with a cost as well
<whitequark> long term i expect the output to improve significantly but it will still be a roundtrip through a netlist
<whitequark> so no 1:1 correspondence to what you wrote in python
<awygle> whitequark: nmigen _used_ to output verilog directly, is that right? or was that change made at the start of nmigen?
<whitequark> nope, never did
<whitequark> the very first prototype wrote rtlil
<awygle> ah, ok
vmedea[m] has joined #nmigen
<awygle> i was thinking the other day about writing a bespoke verilog generator for some nmigen
<awygle> and/or vhdl generator
<awygle> to try to output optimally idiomatic code
<awygle> specifically to reduce the barrier of using a primary-nmigen IP core in a primary-Verilog or primary-VHDL tool flow
<awygle> idk how possible that is, but it feels doable as long as it's constrained to a particular context
<pftbest> one more thing i want to understand is blocking assignments. for example this code is impossible to write in chisel
<pftbest> and i want to understand how it works
<pftbest> could you please suggest some links i can read?
<d1b2> <dub_dub_11> I don't think you ever should use this in synthesis
<d1b2> <dub_dub_11> or
<d1b2> <dub_dub_11> ever
<d1b2> <dub_dub_11> maybe in a tb but idk why
<pftbest> why not?
<d1b2> <dub_dub_11> it seems to suggest that you're driving a clock from logic basically
<pftbest> but it will be routed on the clock net
<d1b2> <dub_dub_11> could be, but I think you still get timing issues
<d1b2> <dub_dub_11> maybe this is something that's done in IC development idk
<d1b2> <dub_dub_11> but on an FPGA you never do that, the FFs have enable bits for this purpose
<pftbest> i am more interested in syntax, not actually using this
<pftbest> why there is a difference if you do blocking or non blocking assignment here
<daveshah> I don't understand the Verilog execution model well enough to explain the sim side, but it is important that in this case synthesis will be the same for blocking or non-blocking
<awygle> yeah tbh i'm surprised to learn that there's a difference in this case. typically i think of blocking vs nonblocking as affecting "ordering" of statements and there's only one statement in the process.
<awygle> but i'm completely willing to believe there's a bizzare edge case in the Verilog execution model that does lead to a difference, which is just further indication that Verilog is pretty weird overall
<whitequark> awygle: a direct verilog generator is not something i ever want to maintain, except in the case that it has an extensive property based testsuite with much more than just 100% statement/condition coverage
<whitequark> i.e. you need to significantly improve on vloghammer
<whitequark> (and vloghammer is hard enough to satisfy that the inline PR is sitting in the queue for a long time)
<whitequark> honestly, I think that the effort you'd spend on such a thing would be better spent on first improving write_verilog, because there is no way you will escape implementing all that logic the second time, anyway
<whitequark> daveshah: pftbest: dub_dub_11: awygle: there is a difference and i can explain what it is, because it is something that is highly relevant to cxxrtl
<whitequark> awygle is very close here, it is about ordering of statements within zero physical time
<whitequark> there is only one statement that you see. but it's a statement that involves clocks. if you use =, then clocked logic that triggers on clk_in and logic that triggers on clk_out will be activated simultaneously (during the times when the edges co-occur)
<whitequark> but if you use <=, then the logic that triggers on clk_out will be activated in the next delta cycle after the logic that triggers on clk_in. in the verilog model, this still happens in zero physical time, so the edges on clk_in and clk_out will look exactly the same on the waveform viewer
<whitequark> however if you have an FF clocked by clk_out reading the output of an FF clocked by clk_in, in the former case it will read the old value, and in the latter it will read the new value. using <= introduces something similar to a race condition, but not quite like it; what it does is it creates a causal relationship between two events happening in zero physical time
<pftbest> oh so it affects statements on other code using the generated clock?
<whitequark> yeah
<whitequark> well, actually using <= is a bit worse here because of Verilog's lack of determinism
<whitequark> I'm not entirely sure whether using <= in a clock divider will ever produce a well-defined result
<whitequark> in Verilog that is
<whitequark> the really tricky part starts when you consider how similar code behaves in VHDL or nMigen
<whitequark> or CXXRTL
<whitequark> so in VHDL you can *only* use <= when writing something like that clock divider, but the execution model is well specified and fully deterministic. this means that you have to take your original clock, clk_in, and produce two clocks, clk1_out (which is just clk_in delayed by 1 delta cycle) and clk2_out (which is clk_in divided by 2)
<whitequark> then all of the logic that would have otherwise been triggered by clk_in must be altered to trigger on clk1_out, and the logic that has to be triggered by divided clock, of course, must trigger on clk2_out
<whitequark> basically, you are balancing clock trees to make sure you have two clocks that are exactly in phase to each other... except, since they are by definition always transition during the same physical instant, "in phase" means "in the same delta cycle within that zero physical time instant"
<whitequark> both nMigen and CXXRTL adopt VHDL's deterministic execution model, but neither specifies the exact scheduling, for reasons of implementation convenience and performance, respectively
<whitequark> that makes it impossible to balance clock trees manually, at least in a reliable way
<whitequark> that's why it's tricky. it must be possible to specify to the simulation runtime that "these two clocks must transition either exactly in phase or in different physical time", this needs to be taken into account when scheduling, and enforced by emitting an error when this is not possible
<whitequark> the scheduling part is hard. the detection of race conditions part has, as far as i know, never been done before in context of HDL, at least not in the way i see it. so it's an open research problem
<pftbest> can you have a similar problem when you are actually using such divider, not in a simulation? I mean it will be shifted relative to the original clock and if you ever try pass data between the two you will violate setup/hold times?
<pftbest> is that why it is such a bad practice to create clocks in logic?
<whitequark> generally (on FPGAs at least), the divider in the file you linked should only be used in simulation
<whitequark> in synthesis, it is not even guaranteed that clk_out will be glitchless, much less within setup/hold time constraints
<whitequark> on ASICs I think things are different
<pftbest> thanks for the explanation, it was very interesting
patrickod has quit [Quit: ZNC 1.8.2 - https://znc.in]
<awygle> whitequark: thanks for that, i understand now. needed to widen my vision to include downstream elements.
<awygle> as for the verilog generator thing, i wouldn't ask you to maintain such a thing, and if i wanted it to be useful in the general case i'd improve on write_verilog as you suggest
<awygle> (or more likely try and fail)
<whitequark> i can probably guide you if you want to improve write_verilog
<whitequark> i roughly know how to make it work, it's just... a lot
jjeanthom has joined #nmigen