icarus verilog specify delays not respected if there are conditionals - delay

Trying to model a 74245 with delays representative of the HCT device.
I am finding that the timings I'm providing in a specify block are not respected.
I have added an extra route A->C (not part of my orig design) to illustrate that the delays can work, just not where there are conditionals in the expression ie none of the other delays are effective.
If I put a delay inline on the assign then this is always respected.
My code is here : https://www.edaplayground.com/x/hDa
Any ideas?
I am a noob.

It was an icarus bug and it's just been fixed on master.
https://github.com/steveicarus/iverilog/issues/315#issuecomment-607800126
Thanks all

Related

Sequential element is unused and will be removed from module in vivado

I am getting a warning that says [Synth 8-3332] Sequential element (\i_data_1_vect_1_reg[31] ) is unused and will be removed from module cg_top in vivado. But the simulation is working fine. I would be great if someone shares why these warnings occur even though I am using these registers and how to solve it.
There are two possibilities:
The register is not needed and hence can be removed. The most common reasons for that are:
The output is not used.
The output always has the same value and can be replaced with a constant 1 or 0.
There is another (often adjacent) register which always has the same value and thus the output of that one is replicated.
Unfortunately there are some rare cases where Vivado reports removal, but actually nothing is removed. The only way to find out for certain is to open the synthesised design and check the schematic (visually, which may take you a long time) if the register has indeed been removed.
As I said these are rare cases. if your are inexperienced with HDL my money is that the register really is not needed.
Whatever the message, I have always found that the actual generated logic was correct.

How is a verilog function translated to hardware

I know that that when you make multiple instances of a module, separate hardware is created for each instance. But what about functions. What exactly happens when I call the same function from different parts of a code?
Synthesizable verilog functions will be inferred to a combinational circuit usually as a series of multiplexers.
Basically, the function will be 'inlined' each time it is called. What happens afterwards is up to the synthesis software. It is possible that some of these instances will be redundant and will be removed. It is possible that some that are not entirely redundant can be combined by inserting multiplexers. Logic path length, complexity, timing requirements, etc. will all affect the result.
This sort of optimization can take place across modules. Synthesizers can be very good about removing or even duplicating logic as necessary to reduce the overall size and to meet timing constraints.

What SystemVerilog features should be avoided in synthesis?

SystemVerilog introduced some very useful constructs to improve coding style. However, as one of my coworkers always says, "You are not writing software, you are describing hardware." With that in mind, what features of the language should be avoided when the end result needs to be synthesized? This paper shows what features are currently synthesizable by the Synopsys tools, but to be safe I think one should only use the features that are synthesizable by all of the major vendors. Also, what constructs will produce strange results in the netlist which will be difficult to follow in an ECO?
In summary: I like compact and easy to maintain code, but not if it causes issues in the back end. What should I avoid?
Edit: In response to the close vote I want to try to make this a bit more specific. This question was inspired by this answer. I am a big fan of using the 'sugar' as Dave calls it to reduce the code complexity, but not if some synthesis tools are going to mangle signal names and make the result difficult to deal with. I am looking for more examples like this.
Theoretically, if you can write software that is synthesized into machine code to run on a piece of hardware, that software can be synthesized into hardware. And conversely, there are hardware constructs in Verilog-1995 that are not considered synthesizable simply because none of the major vendors ever got around to supporting it (e.g. assign/deassign). We still have people using //synopsis translate on/off because it took so long for them to support `ifdef SYNOPSYS.
Most of what I consider to be safe for synthesis in SystemVerilog is what I call syntactic sugar for Verilog. This is just more convenient ways of writing the same Verilog code with a lot less typing. Examples would be:
data types: typedef, struct, enum, int, byte
use of those types as ports, arguments and function return values
assignment operators: ++ -- +=
type casting and bit-streaming
packages
interfaces
port connection shortcuts
defaults for function/tasks/macro arguments, and port connections
Most of the constructs that fall into this category are taken from C and don't really change how the code gets synthesized. It's just more convenient to define and reference signals.
The place it gets difficult to synthesize is where there is dynamically allocated storage. This would be class objects, queues, dynamic arrays, and strings. as well as dynamically created processes with fork/join.
I think some people have a misconception about SystemVerilog thinking it is only for Verification when in fact the first version of the standard was the synthesizable subset, and Intel was one of the first users of it as a language for Design.
SystemVerilog(SV) can be used both as a HDL (Hardware Description Language) and HVL (Hardware Verification Language) and that is why it is often termed an "HDVL".
There are several interesting design constructs in SV which are synthesizable and can be used instead instead of older Verilog constructs, which are helpful in optimizing code and achieving faster results.
enum of SV vs parameter of Verilog while modelling FSM.
Use of logic instead of reg and wire.
Use of always_ff, always_comb, always_latch in place of
single always blocks in Verilog.
Use of the unique and priority statements instead of Verilog's
full and parallel case statements.
Wide range of data types available in SV.
Now what I have discussed above are those constructs of SystemVerilog which are used in RTL design.
But, the constructs which are used in the Verification Environment are non-synthesizable. They are as follows:
Dynamic arrays and associative arrays.
Program Blocks and Clocking blocks.
Mailboxes
Semaphores
Classes and all their related features.
Tasks
Chandle data types.
Queues.
Constrained random features.
Delay, wait, and event control statements.

What does it mean for hardware synthesised from Verilog code to be correct

I have read "Nonblocking Assignments in Verilog Synthesis, Coding Styles that Kill!" by Clifford Cummings. He says that the code at the bottom of this question is "guaranteed" to be synthesised into a three flip-flop pipeline, but it is not guaranteed to simulate correctly (example pipeb3, page 10; the "guaranteed" comment is on page 12). The document won a best paper award, so I assume the claim is true. http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
My question: How is the correctness of Verilog synthesis defined if not by reference to the simulation semantics? Many thanks.
I suppose the bonus points question is: give the simplest possible Verilog program that has well-defined synthesis semantics and does not have well defined simulation semantics, assuming it is not the code below. Thanks again.
In fact, can someone give me a piece of Verilog thatis well defined when both simulated and synthesised, yet the two produce different results?
The code:
module pipeb3 q3, d, clk);
output [7:0] q3;
input [7:0] d;
input clk;
reg [7:0] q3, q2, q1;
always #(posedge clk) q1=d;
always #(posedge clk) q3=q2;
always #(posedge clk) q1=d;
endmodule
PS: in case anyone cares, I though a plausible definition of a correct synthesis tool might be along the lines of "the synthesised hardware will do something that a correct simulator could". But this is inconsistent with the paper.
[I now think the paper is not right. Section 5.2 of the 1364-2001 standard clearly says that the meaning of a Verilog program is defined by its simulation that the standard then proceeds to define (non-determinism and all). There is no mention whatsoever of any "guarantees" that synthesis tools must provide over and above simulators.
There is another standard 1364.1-2002 that describes the synthesisable subset. There is no obvious mention that the semantics of synthesised hardware should somehow differ from simulation. Section 5.2.2 "Modelling edge-sensitive storage devices" says that non-blocking assignments should be used to model flip-flops. In standard-speak that means that the use of anything else is unsupported.
As a final note, the section referred to in the previous paragraph says that blocking assignments can be used to calculate the RHS of the non-blocking assignment. This appears to violate Cummings' recommendation #5.
Cliff Cummings is listed as a member of the working group of the 1364.1-2002 standard. This standard is listed as replaced on the IEEE website but I cannot tell what it was replaced by.]
All -
Time for me to chime in with useful background information and my own opinions.
First - The IEEE-1364.1-2002 Verilog RTL Synthesis Standard was never fully implemented by any vendor, which is why none of us were in any hurry to update the standard or to provide a SystemVerilog version of the synthesis standard. To my knowledge, the standard was not "replaced," and has just expired. To my knowledge, the attributes described in the Standard were never fully implemented by any vendor. The only useful feature in the Standard that I believe was implemented by all vendors was that a vendor is supposed to set the macro `define SYNTHESIS before reading any user code, so that you can now use `ifndef SYNTHESIS - `endif as a generic replacement for the vendor-specific // synopsys translate_on - // synopsys translate_off pragma-comments.
Verilog was invented as a simulation language and was never intended to be a synthesis language. In the late 1980's, Synopsys recognized that engineers really liked this Verilog-simulation language and started to define a subset of the language that they (Synopsys) would recognize and convert through synthesis into hardware. We now refer to this as the RTL synthesis subset, and that subset can grow over time as synthesis tool vendors discover unique and creative ways to convert a new type of description into hardware.
There really is no "correctness of Verilog synthesis defined." Don Mills and I wrote a paper in 1999 entitled, "RTL Coding Styles That Yield Simulation and Synthesis Mismatches," to warn engineers about legal Verilog coding styles that could infer synthesized hardware with different behavior.
http://www.sunburst-design.com/papers/CummingsSNUG1999SJ_SynthMismatch.pdf
Consider this, if synthesized results always matched the behavior of Verilog simulations, there would be no need to run gate simulations. The design, as RTL-simulated, would be correct. Because there is no guaranteed match, engineers run gate-sims to prove that the gate behavior matches the RTL behavior, or they try to run equivalence checking tools to mathematically prove that the pre-synthesis RTL code is equivalent to the post-synthesis gate models, so that gate-sims are not required.
As for the bonus question, this is really hard, because Verilog semantics are rather well defined, even if the definition is that it is a legal race condition.
As far as well-defined code in simulation and synthesis with different results, consider:
module code1c (output reg o, input a, b);
always
o = a & b;
endmodule
In simulation, you never get past time-0. Simulation will loop forever because of the missing sensitivity list. Synthesis tools do not even consider the sensitivity list when inferring combinational logic, so you will get a 2-input and-gate and a warning about missing sensitivity list items that could cause a mis-match between pre- and post-synthesis simulations. In Verilog-2001 we added always #* to avoid this common problem, and in SystemVerilog we added always_comb to remove the sensitivity list and inform the synthesis tool of the designer-intended logic.
As far as whether the paper should offer guarantees on correct synthesis behavior, it probably should not, but the guarantees described in my paper define what an engineer can expect from a synthesis tool based on experience with multiple synthesis tools.
"As a final note, the section referred to in the previous paragraph says that blocking
assignments can be used to calculate the RHS of the non-blocking assignment. This
appears to violate Cummings' recommendation #5."
You are correct, this does violate coding guideline #5 and in my opinion should not be used.
Coding guideline #5 is frequently violated in VHDL designs because VHDL variables cannot trigger another process. I find the VHDL-camp evenly divided on this issue. Half say that you should not use variable assignments and the other half use variables to improve simulation performance but then are required to mix variable assignments with a final signal assignment to trigger other processes.
If you violate coding guideline #5 and if your code is correct, the simulation will work and the synthesis will also work, but if you have any mistakes in your code, it is very difficult to debug designs that violate coding guideline #5 because the waveform display for the combinational piece does not make sense. The output of the combinational logic in a waveform display only updates when reset is not asserted and on a clock edge, which is not how real combinational hardware behaves, and this has proven to be a difficult issue when debugging these designs using waveform displays (I did not include this information in the paper).
Regards - Cliff Cummings - Verilog & SystemVerilog Guru
I believe the reason that will synthesize correctly is because in real silicon there's no difference between 'blocking' and 'nonblocking'.
Synthesis will read that and create three flip flops chained back to back, as you've described.
This won't be a problem in synthesis (assuming you're not violating flop hold time), because real gates exhibit delays. On the rising edge of clk, it will take several ns for the value d to propogate to q1. By the time d propagates to q1, q1 will have already been sampled by the second flop, similarly with q2 and q3.
The reason this doesn't work in simulation is because there are no gate delays. On the positive edge of clock, q1 will be instantly replaced with d, possibly before q1 was sampled by the second flop. In a real circuit (with proper setup and hold time), q1 is guaranteed to be sampled on the positive edge of clock before the first flop can change its output value.
I know this 3 years old, but your post was just flagged up when someone tried to edit it. Cliff's answer is, of course, comprehensive, but it doesn't really answer your question. The other answer is also plain wrong.
My question: How is the correctness of Verilog synthesis defined if
not by reference to the simulation semantics?
You're right, of course. Synthesis is only 'correct' if (a) the result (output) simulates in the same way as the original (input), after possibly making some allowance for timing/etc issues, and/or (b) the synthesiser output can be formally proved to be equivalent to the synthesiser input.
give the simplest possible Verilog program that has well-defined
synthesis semantics and does not have well defined simulation
semantics
In principle, this shouldn't be possible. The synthesiser vendors tried to define templates that were based on code that had well-defined simulation semantics. However, Verilog was (and is) poorly defined, and NBAs didn't initially exist in the language, so you have oddities like the pipeline example. Best to forget about them.
In fact, can someone give me a piece of Verilog that is well defined
when both simulated and synthesised, yet the two produce different
results?
The only definition of 'well defined' (as opposed to 'correct') in synthesis is that multiple vendors will produce exactly the same incorrect result. This is pretty unlikely. I guess the classical async reset and async set clocked F/F would be close.

Should you remove all warnings in your Verilog or VHDL design? Why or why not?

In (regular) software I have worked at companies where the gcc option -Wall is used to show all warnings. Then they need to be dealt with. With non-trivial FPGA/ASIC design in Verilog or VHDL there are often many many warnings. Should I worry about all of them? Do you have any specific techniques to suggest? My flow is mainly for FPGAs (Altera and Xilinx in particular), but I assume the same rules would apply to ASIC design, possibly more so due to the inability to change the design after it is built.
Update 4/29/2010: I was originally thinking of synthesis and P&R (Place & Route) warnings, but the simulation warnings are valid too.
Here is my perspective from the ASIC world (99% Verilog, 1% VHDL).
We make an effort to eliminate all warnings from our log files, because in general, we interpret warnings as the tool telling us that we should not expect predictable results.
Since there are many types of tools which can generate warnings (simulation/debugger/linter/synthesis/equivalence-checking, etc.), I will focus this discussion on simulator compiler warnings.
We analyze warnings and categorize them into two main groups: ones which we deem will not affect the results of our simulation, and others which may affect the results. First, we use a tool's options to explicitly enable as many warnings as possible. For the first group, we then use a tool's options to selectively disable those warning messages. For the second group, we fix the Verilog source code to eliminate the warnings, then we promote the warnings to errors. If any warnings are later introduced in those categories, we force ourselves to fix them before we are allowed to simulate.
An exception to the above methodology is for third-party IP, whose Verilog code we are not allowed to modify.
That method works fairly well for RTL simulations, but it gets much more difficult when we run gate simulations using back-annotated SDF. There is simply not enough time to analyze and eliminate the literally millions of warnings. The best we can do is to use scripts (Perl) to parse the log files and categorize the warnings.
In summary, we try our best to eliminate the warnings, but it is not always practical to do so.
Here's what I do, for reference. I inspect all the log files from the tool(s).
For Altera Quartus II that includes the map, fit and merge reports. I also turn on the Design Rule Check (DRC) option and check that file. For some messages that are easy to fix, e.g. port missing from the instantiation or incorrect constant width, I fix them. Other ones I look into. For ones that are in the cores, e.g. a width mismatch because I'm not using the full output deliberate, I mark them to be suppressed in the .srf file. I only suppress the specific messages, not all of the "similar messages" since there may be others, either now or in the future, which are problems.
I wrote a script which applies a set of regexps to the logfile to throw away lines which I "know are OK". It helps, but you have to be a bit careful with the regexps - what did jwz say about them :)
The most important reason that I can think of is simulation-synthesis mismatch. Synthesis tools do a lot of optimizations (as they rightly should) and if you leave loopholes in your design you are asking for trouble. Refer to IEEE 1364.1-2002 for details about the synthesis standard.
There is no need to remove all warnings, but all should be reviewed. To make this possible for big designs, some warnings can be suppressed by its type or id.
For example, some synthesis tools give a warning if a Verilog parameter is defined and no value assigned during the module instantiation. For me, this warning is just an advice to use localparam. It's a good idea to suppress it by its id (e.g. LINT-01).
In some cases, I want to see the warnings and don't suppress them. For example, my tool gives a warning whenever I define a virtual clock by constraints. The warning doesn't mean there is a problem, but I can catch a missing source of a clock that wasn't intended to be virtual.
Sometimes non-existence of warnings points out a problem. For example, if I change an application variable, there should be a warning.
There are too many cases. Sometimes the warning is unavoidable. Sometimes it's nice to have warnings to be able to review some critical stuff. If the designer knows what he/she does, there is no problem.
Some warnings are expected and there is a problem if you don't get a warning.
for example if you really really want a latch but there is no warning about inferring a latch then your synthesis might not have made what you intended.
so no, you don't always want to 'deal' with all warnings.

Resources