I'm trying to understand following scenario:
typedef enum logic [2:0] {
ONE, TWO, THREE, FOUR, FIVE
} enum_t;
A case statement with enum_t type in case expression:
enum_t case_expression;
logic [2:0] result;
case (case_expression)
ONE: result = 3'b000;
TWO: result = 3'b001;
THREE: result = 3'b010;
FOUR: result = 3'b011;
FIVE: result = 3'b100;
endcase
I'm not sure or clear about following :
Is it okay not to have a default case statement for result? The case_expression is an enum with only 5 valid values. However it's 3 bits. So how the synthesis tool will evaluate this logic? Is it going to infer latch ?
All case items are mutually exclusive. So can I use unique keyword here to aid synthesis tool to optimize the design?
I don't have much expereince in synthesis. So I would appreciate any feedback. Thanks!
This depends on how strongly typed your synthesis tool is. Unfortunately, there are a number of ways that your case_expression could have the value 3'b111 (through casting and poor error checking in some simulation tools). So its best to put the default in for safety's sake.
If "case_expression" takes the value "x", the case statement will not be able to resolve which case to enter. If default case were to be mentioned, it would gracefully enter the default case. You will see runtime error if case_expression takes value of "x" if default is not mentioned.
I believe "unique case" is a directive to synthesis tool mentioning all cases are enumerated. This would prevent a latch. If in simulation if none of the ENUM values are on the case expression, then during simulation a runtime error will be reported.
Related
Below piece of logic is doing 2^(3+x), where x is 2 bit value and can have max 2'b11, according to the below logic, RHS will be 1 << 6, which is 7'b1000000. MSB will be discarded as LHS is of 6 bits.
Checked this code in Spyglass Lint, VCS compile elab, Synthesis results etc, couldn't find any violation. Is there a tool that can find mistakes like below?
module module_test (
input wire [1:0] x,
output wire [5:0] y
);
assign y = 6’d1 << (3 + x);
endmodule
The problem is discarding some or all the bits of a value when shifting is a perfectly valid thing to want to do. A static linting tool checker is not designed to catch all possible functional bugs.
If you had an assertion that y must always have a one-hot value, then a formal property checker can statically determine that the result could be 0 and generate a violation. Assertions are what you use to capture design intent, and either a static formal tool or dynamic simulation tool can catch differences between intent and what got implemented in RTL.
I am trying to code and synthesize in Verilog. Sometimes I am still getting confused with using Verilog as a typical C like programming language, I am trying to understand if there will be a difference between 2 different codes:
always # (a1,a0,b1,b0)
begin
case ({a1,a0,b1,b0})
4'b0000 : s= 7'b1110111 ;
4'b0001 : s= 7'b1110111 ;
....
....
4'b1110 : s= 7'b0101111 ;
4'b1111 : s= 7'b1111010 ;
endcase
end
and
using the above code logic with assign, instead of always block.
Will the above code generate a latch? In which case would it generate a latch? Will there be any delay difference between using the 2 codes?
PS we are trying to create a 2bit binary multiplier, which outputs to a 7 segm display.
Thank you.
Latches are generated when one or more paths through a conditional statement are unassigned. For example:
reg [1:0] a;
reg b;
always#(*)
case (a)
0: b=0;
1: b=0;
2: b=1;
endcase
would generate a latch, because I did not cover the a=3 case. You can avoid this by either explicitly covering each case (like it appears you have done) or by using the default case.
For assign statements, it depends on how you format them, but you're significantly less likely to accidentally infer a latch. For example, if you you the ternary operation (i.e. assign b = a? 1:0;) both halves of the if are inferred.
As for delay, case vs. assign should create the same netlist, so they should produce similar or identical results, provided they're logically identical.
(As a side note, it's good practice to use always#(*), rather than always # (a1,a0,b1,b0); The synthesis tool can figure out the correct sensitivity list.)
I have this SV code :
module m1 (input int a);
always begin #1; force a=a+1; end
endmodule
module m ();
int a;
m1 m1(a);
endmodule
Is this statement in above code valid force a=a+1;?
It might work in your simulator, however it is not recommended.
In the IEEE std 1800-2009 section 10.6 defines a force statement as a "procedural continuous assignment." There is an example in the LRM stating that if a value on the right hand side of the equation is changes, then it will force the new value to the right hand variable. In this case a=a+1 should technically cause an infinite loop but likely does not because of a scheduling rule.
In general force should be used sparingly and be used in a test bench and behavioral modeling. Functional expressions are allowed with force however circular dependance needs to be avoided. Best to assign a constant expression with force is possible.
Yes, I believe the behavior is well defined in this case. Module m1 will see the forced value but the enclosing module will not.
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[index+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.
I'm reading some third party Verilog, and found this:
function [31:0] factorial;
input [3:0] operand;
reg [3:0] index;
begin
factorial = operand ? 1 : 0;
for(index = 2; index <= operand; index = index + 1)
factorial = index * factorial;
end
endfunction
It seems that the begin and end keywords are redundant here. Are they? What is their use?
I don't know about the general case, but in this specific case:
If a function contains more than one statement, the statements must be
enclosed in a begin-end or fork-join block.
Source: Verilog Golden Reference Guide
Both answers are correct. If the Verilog task or function had multiple statements, they were also required to have begin-end statements. Starting in SystemVerilog-2005, we removed the requirement to put begin-end inside of something that already had a begin-end. Most of us on the committee thought it was silly to require a begin-end inside of something that was already going to have endfunction/endtask. I mean, come-on! Don't you think a compiler could figure out that when it got the endtask/endfunction statement that it was at the end of the task or function?? Removing the begin-end from tasks and functions cuts out a surprising amount of useless code. Score another point for SystemVerilog!
According to the SystemVerilog extension (IEEE Standard 1800-2009), begin/end are optional inside a function. However, your toolset (simulator, etc.) must be capable of understanding this syntax, which was introduced in 2005.