The Verilog standard defines four types of bit values: 0, 1, x, and z where 0 means low, 1 means high, x means unknown, and z means an undriven net.
A couple of questions:
Does x mean that we don't know if the value is 0 or 1? 0 or 1 or z? or that the value is just unknown and can be something else than 0, 1, or z?
Since z represents an undriven net, can a reg type have a z bit? If so, what does it mean?
The value X means a number of things depending on what kind of signal you are referring to and how it got that value.
For a variable with a 4-state data data type, X is the default initial state, meaning its value is unknown and has the potential to be any value. This is a symbolic state as real hardware will be in a particular state 0 or 1 at any specific point in time.
You can also assign variable to the value X because of some operation that you either don't-care what its value is, or want to consider that operation illegal. Synthesis tools use that don't-care information when optimizing your logic and it will produce deterministic logic.
Nets have values that are a resolution functions of one or more drivers or continuous assignments. The built-in net types resolves multiple drivers by looking at their drive strengths, highest strengths wins. When there is a conflict between equal strengths driving 0 and 1, a wire resolves the conflict with an X value. The absence of any strength is called the Z state.
It's possible for a variable to be assigned the X or Z state and have that value drive a net through a continuous assignment. If the wire is being driven with a stronger strength, that strong strength's value prevails.
Typically, x means that we don't know if the value is 0 or 1. I suppose it could also include z. I don't think it ever means anything other than 0/1/z.
x in simulation often means that the signal was not initialized to a 0 or a 1. This common if you are modeling a flip-flop without a reset.
Another common reason for an x is when a net is driven by multiple drivers (contention). If one is driving a 0 and the other a 1, the result is x.
Yes, a reg can have the value z. It is common to use procedural assignments to a reg. Here is a simple example of a tri-state driver:
module tb;
reg en = 0;
reg out;
always #* out = en ? 1 : 'z;
initial begin
$monitor($time, " en=%b out=%b", en, out);
#5 en = 1;
#5 en = 0;
#5 $finish;
end
endmodule
Prints:
0 en=0 out=x
5 en=1 out=1
10 en=0 out=z
This could also be modeled using a continous assignment:
wire out = en ? 1 : 'z;
In both cases (reg and wire), the z means the same thing.
Related
I am studying verilog as part of my university course however my module lecturer left so I was hoping for some help here,
An example we have been given for a parametric n-bit gray to binary code converter, as follows:
module bin_n_gray #(parameter n=4) (input [n-1 : 0] gray, output [n-1 : 0] bin);
integer i;
always # (*)
for(i = 0; i < n; i = i+1)
bin[i] = ^(gray >> i);
endmodule
My question:
As the bin[i] variable is on the left hand side of an assignment statement within an # always block shouldn't this variable be declared as output reg [n-1 : 0] bin?
As I thought that a variable on the left hand side of an assignment statement of a process block i.e always / initial should be declared as a reg datatype?
As the bin[i] variable is on the left hand side of an assignment statement within an '# always' block shouldn't this variable be declared as 'output reg [n-1 : 0] bin?
Yes, it should require the reg as you say, at least according to Xilinx XST. The code as given in your question errs when synthesizing using that tool (and is missing an unrelated semicolon).
First let's begin by understanding what a procedural block in Verilog is, exactly (with the assumption that we're using Verilog to develop hardware, such as an FPGA design). Procedural blocks are always blocks (of two types, combinational and sequential) as well as few other types of blocks we won't cover here. The first thing to know is that in a procedural block, the only assignments allowed are those that have a reg on the left hand side.
This doesn't necessarily mean that a physical register/flipflop will be created. In this case, one will not be. The reason is the declaration of the block as always # (*). This declaration means that the process is combinational (i.e. not sequential, not having any internal state or clock signal). As a result, no physical flip-flops are created.
Alternatively, you can have a procedural block declared as always # (posedge some_clock_signal). This means that sequential logic is created, and physical flip-flops (or other means of storage such as the distributed memory in FPGA lookup tables) may be used. The takeaway is that you're still declaring as reg there, but now you're actually creating registers.
There is one case where you use wire (or output), which is by continuous assignment (for example, assign a = b & c), which falls outside a procedural block. In this example, I'm using generate to do the same thing as the loop in your original code:
module bin_n_gray #(parameter n=4) (input [n-1 : 0] gray, output [n-1 : 0] bin);
genvar i;
generate
for (i=0; i < n; i=i+1)
begin: graydecoder // arbitrary label needed by generate syntax
assign bin[i] = ^(gray >> i);
end
endgenerate
endmodule
I am creating the verilog module that calculate either one of a+b, a-b, a & b or a | b.
The problem is that it does calculate for a+b and a-b.
but it cannot calculate a & b and a | b and return nothing.
input [31:0] a, b;
input [2:0] op;
output [31:0] z;
output ex;
wire[31:0]a0,a1,a2,a3;
assign a0 = a & b;
assign a1 = a | b;
assign a2 = a + b;
assign a3 = a - b;
assign z=a0;
//assign z=a1;
//assign z=a2;
//assign z=a3;
endmodule
the module basically calculate a+b, a-b, a&b, and a|b and assign its calculated value to z.
And it does successfully calculate for a+b and a-b and put calculated value to z.
But for a&b and a|b, it doesn't assign anything to z.
How can I solve this?
Thank you very much if you can help me.
I'm sure it does assign something to z. The problem is that you are trying to assign too much to z.
Each assign statement represents some hardware, which in this case drives the wire z. So, you are driving z 4 times in parallel from 4 separate lumps of hardware. If you like, you have a short circuit. (Remember Verilog is a hardware description language. You are designing hardware here, not writing software. If you assign to a wire from more than one place, you have shorted the outputs of some lumps of hardware together.)
I notice there is an input [2:0] op. This looks like homework to me and I guess you have been asked to design an ALU. An ALU is a lump of hardware (combinational logic in this case) that can perform various operations on it's inputs (its operands), which in this case are a and b. Which operation it performs needs to be selected by some other control input, which in this case is almost certainly supposed to be op.
So, you need some code that tests op and drives z with either a+b, a-b, a&b or a|b. The obvious construct to me for this job is a case statement:
case (op)
3'b000:
z = // some expression, eg a + b, it depends on what op code 000 is supposed to mean
3'b001:
z = // some other expression here
// etc etc
default: // perhaps...
z = // ...something to drive z if none of the other branches are used
endcase
A case statement should go inside an always block. As I suspect this is homework, I won't feed you the answer, I'll let you work out how to do that.
Finally, I see that op is 3 bits wide. This suggests that you ALU has more than 4 different operations to carry out. I also see there is an ex output, which presumably needs to do something.
There's some confusion here. Your original posted code is fine; z will be assigned as you want. The other answer is incorrect - there are no multiple drivers; they're commented out. The delay suggestion is also incorrect - a delay will make no difference whatever to your logic.
From a hardware point of view, what do force and release statements model? What are the uses of these statements?
The force/release statements are generally used to aid in simulations.
One scenario is to avoid X-propagation in gate simulations. The RTL code sometimes contains registers without asynchronous resets. Although the RTL simulations will run cleanly, gate simulations often do not. Either the X's never get resolved, or they take so many cycles to resolve so as to make simulations take an impractical amount of time to run. By forcing and releasing a random known value into the register during reset, the simulation is allowed to proceed cleanly and complete in a timely manner.
Another scenario involves large counters. For example, to see a 32-bit counter roll over, it requires 4 billion cycles. Typically, you want it to roll over several times in one simulation. Again, this could take an impractically long time to simulate. The force/release can be used to deposit a random value into the counter close to the roll-over value.
Another scenario involves boosting code coverage results. It can be difficult to achieve 100% coverage on all metrics, especially when using IP which can not be modified. The force can be used to toggle an unused signal.
The force/release should be used sparingly and only when you are convinced it is valid to do so.
Based on IEEE Std 1364-2005, the force procedural continuous assignment statement shall override all procedural assignments to a variable or net. The release procedural statement shall end a procedural continuous assignment to a variable or net. The value of the variable shall remain the same until the variable is assigned a new value through a procedural assignment or a procedural continuous assignment.
For example:
module test;
reg a, b, c, d;
wire e;
and and1 (e, a, b, c);
initial begin
$monitor("%d d=%b,e=%b", $stime, d, e);
assign d = a & b & c;
a = 1;
b = 0;
c = 1;
#10;
force d = (a | b | c);
force e = (a | b | c);
#10;
release d;
release e;
#10 $finish;
end
endmodule
In the example above and gate and1 is patched to work as or gate. If you simulate it, you'd get following results:
Results:
00 d=0,e=0
10 d=1,e=1
20 d=0,e=0
Without force statement, for t = 10, e should be equal to 0 (since 1 & 0 & 1 = 0). Using force statement overrides result of and1 and force e = 1. But as soon as release is applied to e, the value is change to 0 (the functionality of and gate is restored).
In the example above you can also see that force/release can be applied both to regs (d) and wires (e). This statements are used in testbenches, when you want to force determined value in reg or wire.
module dut ( a,b_out,array,c);
input [2:0] a;
input [3:0] array;
input c;
output reg b_out;
always#( a or c or array) begin
if(c)
b_out = 1'b0;
else
b_out = array[a];
end
endmodule
There is a possible range overflow in the above RTL, how it exactly affects the simulation and synthesis?
When a > 3 and !c then b_out will be undef in simulation because an out-of bounds access to a vector returns undef (i.e. 1'bx). See 5.2.1 in IEEE Std 1364-2005:
A part-select of any type that addresses a range of bits that are
completely out of the address bounds of the net, reg, integer, time
variable, or parameter or a part-select that is x or z shall yield the
value x when read and shall have no effect on the data stored when
written. Part-selects that are partially out of range shall, when
read, return x for the bits that are out of range and shall, when
written, only affect the bits that are in range.
In synthesis this don't care will be transformed into whatever the synthesis tool deems the most efficient. Very likely that means that only the bottom two bits of a are used in array[a], i.e. it is identical to array[a[1:0]]. But there is no guarantee for that whatsoever and it would be equally correct to create a circuit that for example always returns 1 or 0 when a[2] is high.
I have just started learning Verilog and I've seen these three lines from different sources. I am confused about the difference between the three:
c <= a&b;
assign c = ~a;
c = 1'b0;
These lines seem to assign a value to c but what's the difference? Thanks.
1) <=non-blocking and is performed on every positive edge of clock. these are evaluated in parallel so no guarantee of order. An example of this would be a register.
2) assign =continual assignment to wire outside an always statement. value of LHS is updated when RHS changes.
3) =blocking assignment, inside always statements enforces sequential order.