*** tpb <[email protected]> has joined #yosys | 00:00 | |
*** lexano <[email protected]> has quit IRC (Ping timeout: 250 seconds) | 00:04 | |
*** skipwich_ <skipwich_!~skipwich@user/skipwich> has quit IRC (Quit: DISCONNECT) | 03:01 | |
*** skipwich <skipwich!~skipwich@user/skipwich> has joined #yosys | 03:03 | |
*** peepsalot <peepsalot!~peepsalot@openscad/peepsalot> has quit IRC (Remote host closed the connection) | 03:03 | |
*** peepsalot <peepsalot!~peepsalot@openscad/peepsalot> has joined #yosys | 03:04 | |
*** citypw <citypw!~citypw@gateway/tor-sasl/citypw> has joined #yosys | 03:45 | |
*** krispaul <[email protected]> has joined #yosys | 07:02 | |
*** kristianpaul <kristianpaul!~paul@user/kristianpaul> has quit IRC (Ping timeout: 252 seconds) | 07:03 | |
*** lexano <[email protected]> has joined #yosys | 16:28 | |
*** napaalm <[email protected]> has joined #yosys | 16:30 | |
napaalm | Hi, I have an issue with yosys synthesis, which results in a different behaviour than the input file: | 16:34 |
---|---|---|
napaalm | module test(clk, rst_n); | 16:34 |
napaalm | input clk, rst_n; | 16:34 |
napaalm | reg STAR; | 16:34 |
napaalm | localparam S0=0, S1=1; | 16:34 |
napaalm | always @(rst_n==0) STAR <= S0; | 16:34 |
napaalm | always @(posedge clk) if (rst_n==1) | 16:34 |
napaalm | casex(STAR) | 16:34 |
napaalm | S0: STAR <= S1; | 16:34 |
napaalm | S1: STAR <= S0; | 16:34 |
napaalm | endcase | 16:34 |
napaalm | endmodule | 16:34 |
napaalm | executing | 16:34 |
napaalm | $ yosys -p "synth -auto-top; write_verilog synth.v" test.v | 16:34 |
napaalm | results in the following file: | 16:34 |
napaalm | (* hdlname = "\\test" *) | 16:34 |
napaalm | (* top = 1 *) | 16:34 |
napaalm | (* src = "test.v:1.1-12.10" *) | 16:34 |
napaalm | I see that my previous message is not so readable, so I uploaded the input and output files to pastebin | 16:38 |
napaalm | Input file: https://pastebin.com/1ZzSkp7H | 16:38 |
napaalm | Command: yosys -p "synth -auto-top; write_verilog synth.v" test.v | 16:38 |
tpb | Title: test.v - Pastebin.com (at pastebin.com) | 16:38 |
napaalm | Output file: https://pastebin.com/6p1G2bQ6 | 16:38 |
napaalm | The yosys synthesis is wrong, because STAR is no longer a register and its value doesn't change on clock positive edges. Can anyone give me some info on why this happens? Thank you! | 16:38 |
tpb | Title: synth.v - Pastebin.com (at pastebin.com) | 16:38 |
corecode | is it okay to have two processes assign to the same register? | 16:39 |
corecode | i wouldn't write it that way | 16:40 |
napaalm | That is how verilog RTL it's taught at my university. Could you please show me a better way to write it? | 16:41 |
corecode | hm maybe always @(posedge clk, negedge rst_n) if (!rst_n) STAR <= 0 else STAR <= !STAR; | 16:43 |
corecode | if you write two processes, you have two drivers; one is a latch, the other a register | 16:44 |
corecode | i think | 16:44 |
napaalm | Unfortunatly I don't know what exactly is a process, in this context | 16:44 |
corecode | ZipCPU might have an opinion | 16:45 |
corecode | always block | 16:45 |
napaalm | Oh I see | 16:46 |
corecode | do you write tests? | 16:47 |
napaalm | Yes, if I simulate my code with a simple testbench using iverilog, the behaviour is as expected | 16:47 |
napaalm | I can show you | 16:47 |
corecode | not necessary | 16:48 |
corecode | simulators don't always exhibit the exact same behavior when the code is incorrect | 16:48 |
corecode | did you not get any message about two drivers for one signal? | 16:48 |
napaalm | I did not | 16:49 |
corecode | try to set everything to maximum warns and lints | 16:50 |
corecode | https://github.com/chipsalliance/verible | 16:50 |
corecode | this could help? | 16:51 |
napaalm | iverilog with -Wall doesn't output any warning | 16:51 |
corecode | maybe ask in ##fpga | 16:52 |
corecode | this channel is pretty quiet | 16:52 |
napaalm | Ok, in case this code style is actually correct, isn't this a bug in yosys? | 16:53 |
napaalm | The linter you just linked my also doesn't show any warning: I just tried | 16:53 |
corecode | hm | 16:56 |
corecode | maybe it is valid code because of the conditions? | 16:56 |
corecode | seems unlikely tho | 16:56 |
napaalm | I don't know, my verilog knowledge is very limited, I'll try asking in the other channel, as you suggested. Thank you | 17:01 |
*** napaalm <[email protected]> has quit IRC (Quit: Client closed) | 17:02 | |
*** napaalm <[email protected]> has joined #yosys | 17:02 | |
*** napaalm47 <[email protected]> has joined #yosys | 17:03 | |
*** napaalm47 is now known as YourNick | 17:03 | |
*** YourNick <[email protected]> has left #yosys | 17:04 | |
whitequark | corecode: no, it is not okay to have two processes assign to the same register | 17:11 |
whitequark | oh, sorry, I missed a bit of context | 17:11 |
napaalm | So, is my code incorrect? | 17:13 |
whitequark | yes. there are at least two issues with it | 17:13 |
whitequark | first: you cannot use two processes to write to a register with yosys (or any other synthesizer I know) | 17:14 |
whitequark | second: yosys does not support conditions like always @(rst_n==0) | 17:14 |
whitequark | I think the specific behavior is that it is treated like always @* in this case | 17:14 |
whitequark | but it is an error (which is not diagnosed by yosys) to use a condition like that | 17:14 |
napaalm | Could it be an old syntax? Because here at my university we are taught this exact way to write RTL code | 17:16 |
napaalm | Is the following code correct? https://pastebin.com/zm3cqcVU | 17:25 |
tpb | Title: test_corrected.v - Pastebin.com (at pastebin.com) | 17:25 |
*** citypw <citypw!~citypw@gateway/tor-sasl/citypw> has quit IRC (Ping timeout: 240 seconds) | 17:42 | |
*** srk_ <srk_!~sorki@user/srk> has joined #yosys | 18:40 | |
*** srk <srk!~sorki@user/srk> has quit IRC (Ping timeout: 246 seconds) | 18:43 | |
*** srk_ is now known as srk | 18:43 | |
ZipCPU | napaalm: Yes, your last pastebin will work. | 19:34 |
ZipCPU | The code you wrote initially is only legal in a simulation context. Verilog was initially written as a simulation language, and so it can work in simulations. | 19:35 |
ZipCPU | However, you can't map it to hardware. | 19:35 |
ZipCPU | When it comes to mapping a design to hardware, you have to limit yourself to only the constructs that the hardware supports, and assigning the same register in two separate always blocks is ... well, that doesn't describe any hardware. | 19:35 |
ZipCPU | It only has meaning in a simulation. | 19:36 |
*** kraiskil <[email protected]> has joined #yosys | 19:36 | |
ZipCPU | If that's the kind of logic taught you in your school, then either 1) you are taking a class in how to write Verilog simulations (check your syllabus), 2) you missed a key piece of context in the lesson, or 3) you instructor has been delinquent about telling you the difference. | 19:37 |
*** kraiskil <[email protected]> has quit IRC (Ping timeout: 245 seconds) | 20:25 | |
napaalm | Thank you ZipCPU, now it all makes sense! During the class we never touch actual hardware, instead we write simulations with iverilog | 21:00 |
ZipCPU | napaalm: You aren't the first person with this type of question. | 21:01 |
ZipCPU | Indeed, its a common beginners mistake. I see this sort of thing all the time. | 21:01 |
napaalm | I can imagine that | 21:02 |
ZipCPU | It's also why I limited my tutorial to *only* those parts of Verilog that could be synthesized. | 21:02 |
napaalm | Speaking of code that can't be synthesized, now I am trying to synthesize tri-state logic, but I can't get yosys to convert it to a form that can be synthesized to an fpga. I don't understand the exact purpose of the "tribuf" command, and it doesn't seem to make a difference in my code | 21:05 |
ZipCPU | Heh. Yeah, that's another one. | 21:06 |
ZipCPU | The trick is there's only a couple ways to do it, and a lot of ways to mess it up. | 21:06 |
ZipCPU | Properly, you might write: assign out = (tristate) ? 1'bz : value; | 21:06 |
ZipCPU | But beware, you can *only* do that to output of the chip at the top level. | 21:07 |
ZipCPU | The other way to do it is to instantiate the FPGAs tri-state IO buffer. | 21:07 |
ZipCPU | Which buffer you instantiate, however, depends upon the FPGA you are using. | 21:07 |
napaalm | Okay, so this applies only to top-level outputs, and what about internal logic? | 21:08 |
ZipCPU | Internal tristate logic is only supported by some daring synthesis tools. | 21:08 |
napaalm | My FPGA is a Lattice ECP5 | 21:09 |
ZipCPU | It's not universally supported. | 21:09 |
ZipCPU | See, the thing is, there's _NO_SUCH_THING_ as internal tristates on an FPGA. The hardware doesn't allow it. | 21:09 |
ZipCPU | Some synthesis tools will attempt to approximate it via logic, but the hardware for it doesn't exist. | 21:09 |
ZipCPU | (I don't mean to yell, but if I were an instructor I would've given a proverbial foot stomp at that, and ... I'm not sure how to write that in IRC text ...) | 21:10 |
napaalm | Okay, I had found online this limitation of FPGAs, so the question is: can yosys do this kind of approximation? | 21:12 |
ZipCPU | I haven't tried it. I think some of the developers have said it could, but it wouldn't be a widely used or tested feature so ... your mileage might vary. | 21:13 |
ZipCPU | In my case, I'm always writing to the lowest common denominator, so if there's one synthesizer my customers might use that doesn't support a feature, I'm stuck without it. | 21:14 |
ZipCPU | Sometimes I think they bought commercial tool XYZ back in the early 2000's, and they couldn't afford to update the licenses ... so, the market I work with leaves me stuck w/o a lot of language features others really like. | 21:15 |
napaalm | I see, it doesn't seem like an easy field to work in | 21:17 |
ZipCPU | It's not all that bad. You just have to learn the few constructs that are universally supported. | 21:18 |
lofty | napaalm: pretty much whenever you use tristate logic then Yosys will issue a warning about limited support for it. | 21:19 |
lofty | But, really, there's no real need for tristate logic internally? | 21:19 |
ZipCPU | I agree with lofty. There's no reason to use it internally. | 21:20 |
napaalm | Yeah, I am trying to synthesize an educational CPU we studied in class, which has an internal bus to connect to memory and IO space | 21:20 |
napaalm | I would like to avoid manually reimplement that code without tri-state logic, that's all | 21:20 |
lofty | I assume your mental model was tristate buffers to control read/write to a common set of wires | 21:20 |
ZipCPU | Technically, ASICs can support internal tristates. That doesn't mean they're good ideas to use. However, there was a past generation that used them more liberally. | 21:21 |
napaalm | lofty: Yes, it's a common bus for all devices | 21:21 |
lofty | Even if tristate buffers were supported in internal fabric, they were *very* slow | 21:22 |
ZipCPU | To use a tristate bus in an FPGA, you have to keep a copy of the bus for each potential source, together with the tristate enable for each source, and then you use a LUT (or two or three) per bit to determine the bus value. | 21:22 |
ZipCPU | It's often easier for a two-way bus to simply keep track of both directions independently, rather than those plus the logic necessary to merge them. | 21:23 |
lofty | napaalm: instead what tends to happen is the CPU has separate read/write buses; all devices read from the CPU's write bus, and their write output is multiplexed based on a device's validity signal | 21:23 |
lofty | ZipCPU: Well, all ASICs use internal tristates due to the nature of a transistor, but that's being pedantic | 21:24 |
napaalm | Okay, it makes sense. I thought that yosys could autonomously do this kind of transformation | 21:25 |
ZipCPU | I was trying to describe how you'd build an internal tristate within an FPGA, but ... okay. | 21:25 |
napaalm | Do you know what's the exact purpose of this? https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/tribuf.html | 21:26 |
tpb | Title: tribuf - infer tri-state buffers (at yosyshq.readthedocs.io) | 21:26 |
lofty | That's pretty much for I/O buffer inference | 21:26 |
napaalm | And what about the option "-logic"? | 21:27 |
ZipCPU | Not sure. Try it. | 21:28 |
lofty | "convert tri-state buffers that do not drive output ports to non-tristate logic." | 21:28 |
lofty | AKA, infer an input buffer rather than a tristate buffer if possible | 21:28 |
napaalm | I did try (and it's already included in the synth_ecp5 command), but doesn't help in my case: at the end of the synthesis I get many warning about multiply driven ports | 21:29 |
ZipCPU | Warning, schmorning. If it's not an error, it did something | 21:29 |
ZipCPU | Unlike software, warnings are quite plentify in hardware design | 21:30 |
ZipCPU | Few tools will let you synthesize without generating them | 21:30 |
lofty | Yeah, uh, I would treat a multiple-driver warning seriously, unlike ZipCPU | 21:30 |
napaalm | Yeah, if I then proceed to place and route I get an actual error | 21:30 |
napaalm | nextpnr-ecp5 --json computer.json --textcfg computer_out.config --85k --package CSFBGA285 --lpf orangecrab_r0.2.pcf --lpf-allow-unconstrained | 21:30 |
napaalm | ERROR: Net 'C.d7_d0[0]' is multiply driven by cell ports C.P.D7_D0_TRELLIS_FF_Q_7.Q and C.SdIO.Switch.RBR_TRELLIS_FF_Q.Q | 21:30 |
lofty | Because in the best possible case that's unimplementable | 21:30 |
ZipCPU | lofty: ;) Normally I'd treat it seriously too. | 21:30 |
lofty | And in the worst case you have a bitstream that will produce magic smoke | 21:30 |
lofty | This is...less common these days though, because FPGAs don't have tristate buffers in them | 21:31 |
ZipCPU | Do we need to explain to napaalm how these FPGAs run on smoke? | 21:31 |
ZipCPU | This stuff needs its smoke to run. If you ever let the smoke out, it stops working. | 21:32 |
napaalm | Hahahah | 21:32 |
napaalm | So, it seems I don't have much choice but to implement two separate buses | 21:33 |
lofty | Correct | 21:33 |
napaalm | Thank you very much for your help ZipCPU and lofty ! | 21:34 |
ZipCPU | ;) | 21:34 |
ZipCPU | Good luck. | 21:34 |
napaalm | Thanks | 21:34 |
* ZipCPU goes back to working on his 10Gb Ethernet, trying to configure those GTX transceivers just right ... | 21:34 | |
lofty | napaalm: no worries | 21:34 |
* ZipCPU can't find a valid way to use Xilinx's 66B/64B gearboxes, grumbles and goes on to write his own ... | 21:37 | |
whitequark | ZipCPU: there are some old FPGAs that do have internal tristates | 21:57 |
whitequark | I'm not sure whether they exposed those, but architecturally some old Xilinx devices did have them | 21:57 |
ZipCPU | Seriously? Wow. I have just learned something. Do you remember which ones? | 21:57 |
whitequark | mwk would know for sure, but I think it was... xc2s, maybe? | 21:58 |
whitequark | I believe internal tristates were used to save die area on interconnect | 21:58 |
whitequark | and they stopped using those because doing timing driven routing where you have to consider that your capacitance changes depending on the pass transistors you enable isn't tractable | 21:59 |
whitequark | https://www.mouser.co.uk/datasheet/2/903/ds001-1595278.pdf#page=12 | 22:00 |
whitequark | "One third of the Hex lines are bidirectional, while the remaining ones are unidirectional." | 22:00 |
whitequark | "12 Longlines are buffered, bidirectional wires that distribute signals across the device quickly and efficiently." | 22:01 |
* whitequark uploaded an image: (54KiB) < https://libera.ems.host/_matrix/media/v3/download/matrix.org/cLAVdqQpIXgAzuVBDeAmqvIm/Screenshot_20230722_220125.png > | 22:01 | |
whitequark | there's even a picture saying "3 state lines". so yep, that one has it | 22:01 |
whitequark | those bidirectional buffers look like an absolute nightmare to me... it's amazing they got it to work reliably | 22:02 |
ZipCPU | Wow. Cool. That explains a lot though. | 22:03 |
ZipCPU | It also explains why there's logic around that uses these things, when they are (apparently no longer) synthesizable. | 22:03 |
whitequark | I don't have a way to check but it seems like you could use BUFT internally | 22:03 |
* whitequark uploaded an image: (57KiB) < https://libera.ems.host/_matrix/media/v3/download/matrix.org/ZSrATnjXvbLxhbFxdsByYqsr/Screenshot_20230722_220526.png > | 22:05 | |
whitequark | yeah looks like you could | 22:05 |
whitequark | also the name implies it's solely for internal routing (or it would be an OBUFT/IOBUFT) | 22:05 |
lofty | The Pilkington FPGA has internal tristate buffers too | 22:13 |
lofty | But I think they were intended for logic more than anything | 22:13 |
*** nonchip <[email protected]> has quit IRC (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.) | 22:15 | |
*** nonchip <[email protected]> has joined #yosys | 22:15 | |
mwk | whitequark: xc3k, xc4k, xc5k, xcs, xc2s, xcv, xc2v and all variants thereof | 22:20 |
whitequark | wait, xc5k? | 22:20 |
mwk | xc3k, xc4k, xc5k, xcs have real tristates IIRC; the ones on xcv, xc2s, xc2v are... kinda emulated in hardware, but in a fast way | 22:20 |
mwk | xc5200 | 22:21 |
whitequark | huh | 22:21 |
mwk | an old family of cheap FPGAs | 22:21 |
whitequark | how are they emulated? | 22:21 |
mwk | xilinx actually described it in a patent | 22:21 |
mwk | basically... well, like you'd expect | 22:21 |
mwk | it's a wired-and, except with a real and gate instead of the wired part | 22:22 |
mwk | in short: every CLB has 4 horizontal tristate lines going through it; each horizontal tristate line is splittable into 4-CLB segments | 22:23 |
mwk | and each CLB has two TBUFs (with T and I inputs), each of which has two tristate lines that it can drive | 22:24 |
mwk | there are programmable joiners which basically boil down to chaining the AND gate inputs in both directions or not | 22:24 |
mwk | also I very vaguely recall old lattice (maybe even AT&T era?) FPGAs having tristates too, but... | 22:27 |
mwk | oh, and also | 22:31 |
mwk | the thing about timing and routing is | 22:31 |
mwk | before xc2v, the interconnect in xilinx FPGAs wasn't fully *buffered* | 22:31 |
mwk | so the timing analysis had to actually compute things like capacity of each unbuffered pass-transistor-joined segment of the network | 22:32 |
Generated by irclog2html.py 2.17.2 by Marius Gedminas - find it at https://mg.pov.lt/irclog2html/!