BMOW title
Floppy Emu banner

Understanding Verilog Warnings

Those of you who’ve followed the blog for a while know about my many frustrations with Verilog. Because it feels sort of a like a procedural programming language, but very definitely isn’t one, I keep expecting to be far more competent at Verilog design than I actually am. While working on Plus Too, the Xilinx synthesis tool reported many, many warnings that I didn’t understand. The warning list grew to at least 100, and was so long that I just stopped reading it. That was dangerous, as most of the warnings were likely problems that needed to be addressed.

I’ve been writing C and C++ programs for years, and I’m very comfortable with the language, its details, and the compiler warnings and errors produced by various mistakes. I normally  find the warnings easy to understand, because they reference a specific file and line number, and use well-known terminology to describe the problem. Sure, some more obscure errors like “not an lvalue” would probably flummox a beginner, but at least he’d know what line to scrutinize.

Most Verilog warnings I see are non-localized, and do not reference a specific file or line number. They are design-wide warnings, resulting from an analysis of all the modules in all the .v files. This can make it unclear where to even being looking for the cause of a warning. A typical example is something like:

Xst:647 – Input <vblank> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.

OK, there’s an unused input named vblank. But where? The vblank signal is routed through half a dozen different modules in the design, so how do I know which one I messed up? The only solution I’ve found is to search the whole project for all references to vblank, and verify each one. I also find that error message much too wordy.

Another example:

Xst:646 – Signal <ramAddr<0>> is assigned but never used. This unconnected signal will be trimmed during the optimization process.

This is basically the same as the first example, but has a totally different warning message. Why? Because one is single combinatorial output, and one is a bit in a register? Then there’s this:

Xst:2677 – Node <ac0/vt/videoAddr_17> of sequential type is unconnected in block <plusToo_top>

It’s essentially the same issue again, but yet another totally different warning message. This time it gives the name of the offending module, so it should be easier to track down.

The general meaning of all these warnings is fairly clear: some expected signal connections are missing. Find the problem, and either add the missing connection, or suppress the warning if the unconnected signal is intentional. There were two other warnings I saw frequently whose meanings were definitely not clear to me, however:

Xst:2042 – Unit dataController_top: 34 internal tristates are replaced by logic (pull-up yes): cpuData<0>, cpuData<10>, cpuData<11>, cpuData<12>, cpuData<13>, cpuData<14>, cpuData<15>, cpuData<1>, cpuData<2>, cpuData<3>, cpuData<4>, cpuData<5>, cpuData<6>, cpuData<7>, cpuData<8>, cpuData<9>, mouseClk, mouseData, ramData<0>, ramData<10>, ramData<11>, ramData<12>, ramData<13>, ramData<14>, ramData<15>, ramData<1>, ramData<2>, ramData<3>, ramData<4>, ramData<5>, ramData<6>, ramData<7>, ramData<8>, ramData<9>.

Um, what? This meant nothing to me. I wasn’t even sure if replacing internal tristates with logic was good or bad. The Xilinx tool shows each warning as a link you can click to get more info, but sadly it doesn’t work. Clicking the link just opens a web browser and does a search on the Xilinx site for “Xst:2042”, which returns no results. In fact, none of the synthesis warning links work. If a warning doesn’t make sense to you, you’re on your own.

After a lot of searching around on other web sites, I finally found a decent explanation. It seems that some (or all?) Xilinx devices do not support tristate logic (a signal with an output enable) anywhere but on the actual I/O pins. Signals internal to the FPGA can not be tristate. Tristate logic is typically used to enable multiple drivers to operate on a single shared bus, one at a time. So instead of using internal tristates, you need to construct your design using additional logic to select which module’s data should appear on the shared internal bus, using a mux or similar method.

That mostly makes sense, but I’m using the FPGA to simulate a system of separate parts (address controller, data controller, CPU, RAM, etc) that will eventually be physically separate chips communicating with tristate logic on shared busses. I don’t want to rewrite my design to eliminate tristate logic, because tristate logic is what will be used for these chips. For now I’ve left the logic as is, and I’m ignoring the warnings, and it seems to be working OK. I’m unclear exactly what the synthesis tool has substituted for the internal tristates, though– “logic (pull-up yes)”? What is that, and what problems might it cause?

The other confusing warning that’s been plaguing the design is:

Xst:2170 – Unit plusToo_top : the following signal(s) form a combinatorial loop: ramData<0>, ramData<0>LogicTrst20.

Xst:2170 – Unit plusToo_top : the following signal(s) form a combinatorial loop: ramData<1>, ramData<1>LogicTrst20.

…and so on, for every bit of ramData. This stems from my attempt to specify a bidirectional bus driver akin to a 74LS245:

assign ramData = (dataBusDriverEnable == 1’b1 && cpuRWn == 1’b0) ? cpuData : 16’hZZZZ;
assign cpuData = (dataBusDriverEnable == 1’b1 && cpuRWn == 1’b1) ? ramData : 16’hZZZZ;

This driver has ramData on one side, and cpuData on the other. When it’s enabled, it drives data from one side to the other. The direction in which data is driven is determined by the cpu read/write line. So why does this form a combinatorial loop? I’d expect to see that warning for something like:

assign a = b & c;

assign b = a & d;

but my bus driver code looks OK to me. I still haven’t found an explanation for this one, but I think it’s related to the previous issue about internal tristates. The synthesis tool is probably replacing my bidirectional bus driver tristates with some other logic, which then forms a combinatorial loop. I’m not sure how to fix this one without rewriting the design to use a different method than tristates. But again the final project will see ramData and cpuData on I/O pins connected to other chips using tristates, so I don’t want to rewrite the design.


Read 7 comments and join the conversation 

7 Comments so far

  1. Erik Petrich - September 9th, 2011 2:19 pm

    You’re using the tristate logic to allow different devices to write data to a bus as different times. Since the device you are synthesizing for doesn’t support internal tristate busses, you get the warning you see and it instead infers a multiplexer with everything that could drive the bus as inputs, the bus as the output, and some combinatorial logic to convert the tristate enable signals into select logic for the multiplexer.

    The combinatorial loop is then what results after this tristate buffer to multiplexer substitution where you try to bridge two sides with your bidirectional bus driver: you would have two multiplexers feeding into each other. If your logic is correct, this is not a problem, but the synthesizer is concerned that potentially you are creating a sequential circuit from combinatorial equations without realizing it.

  2. David - September 9th, 2011 7:52 pm

    Those XST warnings are typical for most designs, especially when trying to implement tristate logic – most “modern” Xilinx FPGAs (those made in the last several years) only have the trisate logic at the I/O pins, so XST will convert them to multiplexers, as Erik pointed out above. Tristate logic does not fit well into the FPGA “sea-of-gates” paradigm, but multiplexers do, so this is why they have been left out of the core FPGA logic lately.

    I believe the “pull-up yes” refers to your tristate logic probably implementing a default value of ‘1’ when nothing is driving the bus. This will become a mux input tied to ‘1’ when the bus is not selected.

  3. Stephen Trier - September 10th, 2011 3:11 am

    As a work-around for the bus problem, you might want to make a module that specifically emulates the shared bus. Move the “tri-state” logic into it, so each of your simulated parts will run separate output and input signals and an output-enable signal into it. (In other words, the interface to the bus-emulator module is one step before the tri-state buffers.) The bus module then has a big mux for all of the output signals, which drives all of the input signals, using the OE signals to control the mux.

    Later, when you hang some of these parts on the “real” bus, you can replace the bus-emulator module with a thin bus-interface module that does real tri-state for the external pins. That way, no changes to your core modules are necessary and you minimize the risk of introducing new bugs. Also, if you decide you need more than one part left in the FPGA, a slightly thicker bus-interface module could combine the mux and tri-state functions to make an interface between the internal and external busses.

    Verilog and its warnings drive me nuts, too. Thanks for describing the problems so well.

  4. Steve - September 10th, 2011 6:35 am

    Thanks everyone. Stephen – I like the sound of that bus emulator approach… I’ll give it a try.

  5. Alex B - September 10th, 2011 1:05 pm

    I’ve found that the “show technology schematic” tool can shed some light on how exactly XST synthesizes the design.

  6. scatterbrained - September 24th, 2011 7:25 am

    I don’t know why you start railing about verilog and then show a bunch of warnings from XST – a /synthesis/ tool. These aren’t any failings of verilog per se – just the tool that turns a subset of verilog into gates. Bad VHDL would give you the same stuff (and take 2x as many lines to do it 🙂

    As for why the tools operates over the whole design, that’s because you told it to. It’s possible to synthesize subsets of logic and stitch them together (ASIC guys have done this for years), but you still end up with some phase at the end where the tool is working at a global level.

  7. Steve - September 24th, 2011 7:59 am

    You’re right. It would be more accurate to call them HDL synthesis errors or something like that, but I still think of them as errors when building a Verilog project -> Verilog errors.

    Unfortunately the free version of the Altera tools doesn’t seem to support using multiple design partitions in the way you suggested (unless I’ve missed it). It also doesn’t support incremental compilation. So every time you change a single line, you have to wait for the entire project to rebuild. I believe those features are unique to the paid version.

Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.