verilog coding style for synthesizable code - verilog

I coded something like the following:
always #(state or i1 or i2 or i3 or i4) begin
next = 5'bx;
err = 0; n_o1 = 1;
o2 = 0; o3 = 0; o4 = 0;
case (state) // synopsys full_case parallel_case
IDLE: begin
if (!i1) next = IDLE;
else if ( i2) next = S1;
else if ( i3) next = S2;
else next = ERROR;
end
S1: begin
if (!i2) next = S1;
else if ( i3) next = S2;
else if ( i4) next = S3;
else next = ERROR;**strong text**
...
My manager, of course I don't want to argue with him before I have some strong argument, but he reviewed my code and said writing
next = 5'bx;
err = 0; n_o1 = 1;
o2 = 0; o3 = 0; o4 = 0;
in a combinational logic without putting the right side in the sensitivity list will cause problems in synthesis.By not having these 3 lines, I need to explicitly write the else part inside each individual case, and he said yes.
I am wondering is there anything wrong with this coding style? And will it cause a synthesis problem or any sort of problem(maybe some version or old synthesis tool won't synthesize?) by initializing these values in the combinational logic? What he said does make sense to me and I actually never thought about it because he said this is software logic, and every wire gets its initial value from the logic before it with the initial condition. I told him school taught us this, he was like school cares less any synthesis but industry does.
Thank you for your help! Guess I am not trying to convince him anything even I have a answer, since the team need to stick with one style anyways, but i am confused by him since I have seen others doing this all the time and he is also a guy with tons of experience, so...confused

First of all, you should be using always #(*) from Verilog-2001 or even better always_comb from SystemVerilog so the sensitivity list get constructed automatically for you.
The problem with your code is the use of the full case synthesis pragma as described in this paper. Your coding style removes the need for full case as long as you are sure you made assignments to every variable in the always block for all possible flows through the block.

I think what your boss means by "software logic" is that your coding style requires the designer to think sequentially. In other words, when I read your always block, I am first forced to think about all the values being initialized to their default values, then I must evaluate the case logic. In reality, the logic will synthesize into the equivalent of a default case. This causes a disparity between the logic that represents the RTL and the logic of how I evaluate your expression in my mind. If you know what your doing, then this should be fine most of the time. But you are working for a company, so your code should be considerate of the other engineers working on a project. Each different team in the design flow is going to view the same logic through a potentially different lens (for example, the physical design team is not concerned with Verilog but the synthesized RTL). If we write our Verilog to reflect the final RTL (i.e. "hardware logic"), then everyone is analyzing the logic in a similar fashion. If I look at an output in a circuit and I know all the values of the inputs at a given time step, then I can visually trace the output through the circuit and determine its value without giving any consideration to the other logic. Your Verilog code should be written in the same way.
To summarize, your initialization statements are nothing more than another case in the selection mux in the RTL. So, you should write it that way. Use a default case and explicitly assign every output of the block in each case. This is generally considered best practice. It may not be the most clever or elegant way to write Verilog, but it is the most readable and results in far fewer errors (and in industry, people are more concerned with design verification to reduce costs than the cleverness of Verilog).
Also, as #dave_59 brought up, if you use the full_case Synopsis directive, then it will create default output drivers for you where the outputs are set to "don't cares." This is not a result that anyone wants, and it would be flagged by the verification team. To fix it, you would need to make sure every output is being assigned by adding them to all the cases like your boss mentioned. If you are forced to do this anyways, then full_case is redundant because you have explicitly made the case statement full. As for older synthesis tools, I don't see that being as big of an issue for this particular subject, but it is a consideration that is always given in industry. What would be more of an issue is if your company has configured downstream tools to force older constructs in an effort to reduce verification costs.
Trust your manager's experience on this issue. Coding style in industry is largely affected by collaboration with other engineers, costs, and legacy than by technical details. This is where your manager's experience will be valuable.

Related

syntax error, unexpected '=', expecting IDENTIFIER

I'm creating a sudoku game in verilog(2001) to eventually be put onto an FPGA, I found code for it in java and have been trying to convert it but have run into some errors.
Here's the link for the java code
www.geeksforgeeks.org/program-sudoku-generator
I have very little verilog experience and am learning as I go.
task automatic removeKDigits()
reg count = K;
while (count != 0)
begin
integer cellId = randomGenerator(N*N-1);
// System.out.println(cellId);
// extract coordinates i and j
i = (cellId/N);
j = cellId%9;
// System.out.println(i+" "+j);
if (mat[i][j] != 0)
begin
count = count-1;
mat[i][j] = 0;
end
else
count=count;
end
endtask
K is the amount of digits to be removed from the mat[i][j] board, N=9 since its a 9x9 sudoku board. For the lines containing "count=count-1" and "count=count" I'm getting the error
syntax error, unexpected '=', expecting IDENTIFIER
what does it mean? how do I fix it?
Unfortunately, it's unlikely you'll be able to port java code to synthesizable Verilog code, without at least a decent knowledge of the principles behind RTLs (Register transfer languages).
Programming languages like Java are a high level descriptions of some logic, that will get converted into machine instructions, and run on a processor. They operate sequentially, one line at a time, in a particular order.
RTLs on the other hand, describe actual hardware. They tend to operate in parallel, on a trigger, typically a clock. Instead of 'variables', you tend to work with 'registers' representing actual flip flops, and the Verilog programme will describe the transfer of data between these registers.
As for the actual issues with your code, it's impossible to point out the errors, because it simply isn't Verilog.
I recommend this answer: https://stackoverflow.com/a/5121853/10719567, for a more eloquent description of the differences between programming languages and RTLs, and why it's not that easy to port between the two.

Cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct

This code fails to compile and gives the error as in the title at the "if(overflow)" line.
always #(posedge clk or negedge overflow) begin
if(overflow)
count_posedge = count_posedge + 1;
else
count_posedge = 0;
end
I've somewhere on the internet that I must change it like this:
always #(posedge clk or negedge overflow) begin
if(~overflow)
count_posedge = 0;
else
count_posedge = count_posedge + 1;
end
...and it works perfectly.
From my understanding, the 2 code should behave the same. What's the problem with the first one?
This is more likely an issue with your synthesizer then your simulator. The likely problem is that the first code does not match any of it's templates for a synchronous flip-flop with asynchronous reset.
The common coding practice is to assign your reset logic before any other logic. This coding practice has been around for decades. I assume the rational behind this particular coding practice stems from:
Reset logic is critical from many designs; especially as designs get larger and more complex. It is put at the top for it importance and the fact that it usually fewer lines of code then the synchronous logic.
Early synthesizers were very limited and could only synthesize specific code structures.
The coding style has become a precedence. No one is going to change it unless you can convince and prove something else is superior or has specific advantages.
In your case, your synthesizer is doing a lint check and has determined your code is not following the conventional coding practices. The creator of your synthesizer has decided to only support the common coding structure and there is little incentive to change.
FYI: you should be assigning synchronous logic with non-blocking assignments (<=). Blocking assignments (=) should be used for combinatonal logic. If you do not follow proper coding practices you increase the risk of introducing race-conditions, RTL vs gate mismatch, and other bugs.

If statements causing latch inference in Verilog?

I am writing a Verilog code for synthesis of an algorithm, I am a little confused on what cases might cause latches to be inferred. Below is one such section of the code, though it works fine in simulation, I am worried it might cause problems on hardware.
always#(b1 or b2)
.....
// b1_map,b2_map,m1_map & m2_map are derived from combinational functions using b1 & b2
.....
if(b1_map<=20 && m2_map<=20 && b1_map>=0 && m2_map>=0)
begin
accumulator1[b1_map][m2_map]= accumulator1[b1_map][m2_map] + 1;
end
if(b2_map<=20 && m2_map<=20 && b2_map>=0 && m2_map>=0)
begin
accumulator2[b2_map][m2_map]= accumulator2[b2_map][m2_map] + 1;
end
//accumulator1 & accumulator2 are 2d registers mapped like 2d arrays
So, In this case I want the data to be mapped only if it is in the specified limits. Will a latch be inferred because there is no "else" scenario defined? I didn't add an else statement because there is nothing I want to do with that data if it's not in the limits.
If you write your if statements correctly, you will be fine. Latches are generated when there are paths through the if statement that do not update one or more of the outputs. Code like the following will generate a latch:
always #* begin
if (a) begin
b <= c & d;
e <= f;
end else begin
b <= c | d;
end
end
Notice that e is assigned only when a is true? This requires a latch to implement correctly.
Another posibility that will generate a latch is when the sensitivity list does not contain a signal used in the code.
always #(a) begin
if (a) begin
b <= c & d;
end else begin
b <= c | d;
end
end
This code will generate latches on c and d or on b because it will only allow b to be updated when a changes.
You've misunderstood your problem (and you shouldn't have accepted an answer)
- the issue isn't fundamentally related to 'latches'. Your code doesn't make
sense (for synthesis). Quartus knows this, and it's basically telling you to
rewrite your code.
You've got a combinatorial block that increments a number (immediately) when a
signal changes. Two problems: (1) this is certainly not what you want in real
hardware, and (2) the number must remain the same, and not increment, when b1
and b2 don't change. The second isue is the one Quartus is reporting - your
circuit needs memory of some sort, which it's reporting as a 'latch'. It's not
smart enough to report the first problem, which is the real issue.
Try to draw your circuit as a schematic with real hardware. What does 'any
change on b1 or b2' actually mean? How are you going to maintain the value of
the accumulators when b1 and b2 don't change? The circuit isn't impossible,
but it's way beyond an SO question.
Make you circuit synchronous, triggering on a clock edge, with only a clock
(and possibly a reset) in the sensitivity list, and keep the innards exactly
the same. There's nothing wrong with your if statement, since you actually
want the accumulator to remain unchanged if nothing interesting is happening
on b1/b2.
Inferred latches can come from an incomplete sensitivity list or incomplete assignments.
Sensitivity lists for combinatorial blocks should generally be written with always #*. This avoid coding bugs when updating code. Combinatorial blocks (those not including an edge sensitivity) are once synthesised will perform in the manner of always #*. Specifically naming signals adds more work and will likely lead to RTL to gate level (post synthesis) errors.
Incomplete assignments which imply the value has to be held will infer a latch. Latches are not inherently bad but require careful consideration. Inferred one in this manner removes the thought fullness and control you would otherwise have over it. This can lead to complex timing issues. As the latch is level sensitive rather than edge sensitive. Ideally you want the latch to be open for the first have of the clock cycle so that it is closed when the data will be read from it. Inferred latches remove this control.
Completing if statements with an else, of default for case castanets which sets a sensible value (0's) can help avoid these accidental latches.

Verilog always block

I just want to use some if else statement in verilog.
So I have to use always block.
integer count,index;
reg a=0;
always#(a) begin
a=1;
for(count=0;count<7;count=count+1) begin
index=4*count;
if((significand[index]==1'b0)&&(significand[index+1]==1'b0)&&
(significand[ind‌​ex+2]==1'b0) &&(significand[index+3]==1'b0))
lzero=lzero+1;
end
end
This code does make some sense now. I was able to get the correct simulation result, but I failed to get the correct synthesis on the board. Please help
This is a very typical problem with people who know how to program in C or C++ but forget that Verilog and VHDL are not the same as those.
EVERY signal line of Verilog code inside the ALWAYS block are 'executed' at the same time. The same goes with the combinatorial logic outside of the ALWAYS block.
In your code, both the
assign a=1'b1;
assign a=1'b0;
Will happen at the same time, no matter what.
The only way to change that is to put the last line inside your always block,after the end statement of the for loop.
One page that will give you some help on understanding the difference between C and Verilog is the page:EE-Times: The C Programmers Guide to Verilog
Neither assign 1'b1; nor assign 1'b0; are valid assignments. If you want to constantly drive some net with 1'b1, then you have to write something like assign myvar = 1'b1;.
Also, if your intent was to actually assign to a, then always block doesn't make sense since a is the only thing in its sensitivity list meaning that that block must be executed whenever a changes its value. Since a will essentially never change its value, that block should never be executed.
It is hard to help you out unless you provide a minimal working example demonstrating your problem. The only thing that I can recommend is to use ternary operator in assign right hand side statement. That way you can model a behavioural logic without using always block. For example:
assign a = (b == 1'b1 ? c : 1'b0);
Hope it helps.
UPDATE:
Your second code example is neither complete nor legal as well. You cannot have two combinatorial assignments for the same net.
However, a sensitivity list in always block is now a star, which is Verilog 2001 notation to include all right hand side operands into a sensitivity list automatically. In your case, the block will get executed every time significand or lzero changes.

Verilog Best Practice - Incrementing a variable

I'm by no means a Verilog expert, and I was wondering if someone knew which of these ways to increment a value was better. Sorry if this is too simple a question.
Way A:
In a combinational logic block, probably in a state machine:
//some condition
count_next = count + 1;
And then somewhere in a sequential block:
count <= count_next;
Or Way B:
Combinational block:
//some condition
count_en = 1;
Sequential block:
if (count_en == 1)
count <= count + 1;
I have seen Way A more often. One potential benefit of Way B is that if you are incrementing the same variable in many places in your state machine, perhaps it would use only one adder instead of many; or is that false?
Which method is preferred and why? Do either have a significant drawback?
Thank you.
One potential benefit of Way B is that if you are incrementing the same variable in many places in your state machine, perhaps it would use only one adder instead of many; or is that false?
Any synthesis tool will attempt automatic resource sharing. How well they do so depends on the tool and code written. Here is a document that describes some features of Design Compiler. Notice that in some cases, less area means worse timing.
Which method is preferred and why? Do either have a significant drawback?
It depends. Verilog(for synthesis) is a means to implement some logic circuit but the spec does not specify exactly how this is done. Way A may be the same as Way B on an FPGA but Way A is not consistent with low power design on an ASIC due to the unconditional sequential assignment. Using reset nets is almost a requirement on an ASIC but since many FPGAs start in a known state, you can save quite a bit of resources by not having them.
I use Way A in my Verilog code. My sequential blocks have almost no logic in them; they just assign registers based on the values of the "wire regs" computed in the combinational always blocks. There is just less to go wrong this way. And with Verilog we need all the help we can get.
What is your definition of "better" ?
It can be better performance (faster maximum frequency of the synthesized circuit), smaller area (less logic gates), or faster simulation execution.
Let's consider smaller area case for Xilinx and Altera FPGAs. Registers in those FPGA families have enable input. In your "Way B", *count_en* will be directly mapped into that enable register input, which will result in less logic gates. Essentially, "Way B" provides more "hints" to a synthesis tool how to better synthesize that circuit. Also it's possible that most FPGA synthesis tools (I'm talking about Xilinx XST, Altera MAP, Mentor Precision, and Synopsys Synplify) will correctly infer register enable input from the "Way A".
If *count_en* is synthesized as enable register input, that will result in better performance of the circuit, because your counter increment logic will have less logic levels.
Thanks

Resources