Why is there no assign statement in this Verilog function? - verilog

Coming from a C++ background I'm starting to learn Verilog. This code describes four inputs going into two AND gates. The outputs from those two AND gates go into an OR gate. The output from the OR gate is the final output.
// a user-defined AND gate
module my_and2 (in, out);
input [1:0] in;
output out;
assign out = in[1]&in[0];
endmodule
// a user-defined OR gate
module my_or2 (in, out);
input [1:0] in;
output out;
assign out = in[1]|in[0];
endmodule
// the AND-OR logic built on top of the user-defined AND and OR gates
module and_or (in_top, out_top);
input [3:0] in_top;
output out_top;
wire [1:0] sig;
// instantiate the gate-level modules
my_and2 U1 (.in(in_top[3:2]),.out(sig[1]));
my_and2 U2 (.in(in_top[1:0]),.out(sig[0]));
my_or2 U3 (.in(sig),.out(out_top));
endmodule
The first two modules make sense to me. However, the last one doesn't. The first two modules have an assign statement at the end to set the value for the output variable. However, the last one doesn't. Why is that?

Verilog is 'event driven'. When writing verilog, think in terms of sensitivity lists.
In your example of the AND gate, you've the expression assign out = in[1]&in[0];. Your expression is said to be sensitive to in[0] and in[1]. This means that any time in[0] or in[1] change, the expression will be recomputed, and the value of out will be updated.
So in your toplevel module and_or, you're basically building a big tree of expressions that are sensitive to the outputs of the preceding expressions. This tree is, of course, built using the module connections. So a change in the value of one of the inputs to this toplevel module will ripple through all expressions in its 'logic cone'.
To drive the inputs you'll need higher level testbench module driving signals into your and_or module. This will supply inputs spaced out in time which will trigger the expressions in and below and_or. If not, your sim will have no events, so no expressions will trigger and the sim will time-out at 0ps because it is 'event starved'.
PS: for your AND gate expression, assign out = ∈ will work too... (reduction AND operator)

out_top is driven by the U3 instance output.

To put things simply, I like to think instantiation as just connecting wires.
Modules are blocks of digital circuits. You AND and OR gate modules are where magic happens. You already understand that part. By instantiating those modules, it's like you're connecting the input wires of your top level module with inputs of two blocks AND module. Then taking the outputs of them and taping them to the input wire sticking out of your OR block. And finally you're connecting the output of OR block to the output signal wire of top level.

Related

What does the variable name in the register declaration indicate (Verilog)

I'm a just starting to learn verilog , and I'm having trouble with some things. I've found a few resources to help, but there are some things which aren't clear and I need specified. I have code for a D Flip-flop below. And I understand how the declaration for in and out work. What I dont get is the register.
When it says out is the variable associated with it.Does this association mean, out is the register along with output? Or does it mean out is also the output for the register?
module DFF(quarter, in, out) ;
parameter n = 1; // width
input quarter ;
input [n-1:0] in ;
output [n-1:0] out ;
reg [n-1:0] out ;
always #(quarter=1)
out = in ;
endmodule
In Verilog there are nets and there are variables. The most common kind of net by far is a wire, which you're probably familiar with. You can declare a variable using var, but most people say reg, because that is how it always has been done.
(In Verilog, but not in SystemVerilog), wires have to be driven by
assign statements
the outputs of instantiated modules
and variables have to be driven from
initial and always blocks.
Your output out is driven from an always block and so must be a variable. The line
reg [n-1:0] out ;
declares the output out as being a variable (rather than a wire).
In fact, you are using an old-fashioned way of specifying inputs and outputs. Since 2001, the way to do it is like this:
module DFF #(parameter n = 1)
(input wire quarter,
input wire [n-1:0] in,
output reg [n-1:0] out);
always #(quarter=1)
out = in ;
endmodule
This is the so-called ANSI form and, I think you would agree, is more sensible. I would advise using this form, not the old-fashioned form you are using.
BTW, you code is a bit strange. I'm not entirely sure what it's supposed to do, but this if you're expecting output to be driven by in when quarter is 1, I'd do it more like this:
module DFF // #(parameter n = 1) // you're not using parameter n
(input wire quarter,
input wire [n-1:0] in,
output reg [n-1:0] out);
always #(*)
if (quarter == 1'b1)
out = in ;
else
// IMPORTANT ! : what is out when quarter != 1 ?
// your current code would synthesise to a latch
// is that what you wanted? (And if so, are you
// sure that's what you wanted)
endmodule
initially verilog was though as a language which does behavioral types of operation on state variables (registers, reg) and connects them via nets. So, reg is a variable which is supposed to keep its value between operations, net is just a connection and has no state associated with it, i.e. wire. reg values can be calculated in procedural blocks, i.e. always block, wires can be connected only (using continuous assignments, assign statements (outside of the always blocks)).
There are different rules for using for regs and wires and different behavior of them in simulation, in particular around multiple drivers. See Matthew's reply for more info.

Instantiate vector of custom modules in Verilog with additional parameters

I have a custom module in Verilog that takes several inputs and a few parameters.
module modA (
input inp1, input inp2, ... output out);
parameter my_addr;
...
endmodule
For various reasons associated with the specific hardware that I'm using, I need to create many instances of this module, each time with a different parameter (because my_addr corresponds to a specific location in memory that I am then accessing from the host). Moreover, I would like an easy way to access all of the outputs. I thought of doing something like
wire [9:0] outputs;
modA #(.my_addr) all_modA[9:0](.inp1(inp1), .inp2(inp2), .out(outputs));
So then I would have a vector of elements of all_modA, and the nth element of outputs would correspond to the nth instantiation of modA. That sounds like it would work well, except I need to pass a unique address to each instantiation. When I was just doing one instantiation at a time, it was quite easy to just define a parameter, but I don't see how I could pass a unique identifier each time.
Is there any way to accomplish this? The problem is, if I use a for loop, then I don't see how I can instantiate each modA with a unique identifier. If I don't use a for loop, then I'm not sure how to add a unique identifier.
You can use a generate block over here. Generate blocks are evaluated during elaboration of the design. They do not execute at simulation time and the result is determined before the simulation begins. Therefore, all expressions in generate schemes shall be constant expressions, deterministic at elaboration time.
Give different values to my_addr according to the requirement. Also, you can apply some label identifier to begin-end block. This as an optional feature for generate blocks, but very highly recommended. By doing so, a unique hierarchical path can be seen to every instance of modA is different for each module.
For your code, I have created a testbench that instantiates the module with changing value of my_addr and outputs bus driving the out signal.
module modA #(parameter int my_addr) (input inp1, input inp2,output out);
initial $display("%m: %d",my_addr);
endmodule
module top();
wire [9:0] outputs;
genvar i; // generate iterator
generate
for(i=0;i<9;i++) begin: some_identifier
// my_addr = i+1 for every module
modA #(.my_addr(i+1)) all_modA(.inp1(inp1), .inp2(inp2), .out(outputs[i])); // Multiple modules
end
endgenerate
endmodule
For more information, refer to IEEE 1800-2012 Section 27. Similar questions can be found here and here.

Verilog multiplication through repeated addition

I need help with a Verilog design I'm doing.
the idea is to do multiplication through repeated addition every time the M bit is set to 1/true. then I need to output that value. The assignment statement F=P; is throwing the error.
This is the error I'm getting
Error (10044): Verilog HDL error at Design2.v(13): expression cannot reference entire array "P"
It is my understanding that I can assign a register to an output if they are the same size. If I'm wrong then how can I implement this?
module Design2(A, N, M, F);
input A[7:0];
input N[3:0];
input M;
reg P[15:0];
output F[15:0];
always #(M) begin
repeat(N) begin
P = P + A;
end
F=P;
end
endmodule
Keeping apart the logic side, I can see two issues with your design.
As the comments pointed out, you have used unpacked arrays at wrong place.
Declaration of output port F.
For the first issue, the design needs a 16-bit vector for all the ports and variables. Here, the design takes a bunch of 8-bits as input A which must be declared as input [7:0] A, which is a packed array. Also, P needs to be a vector of size 16-bit in order to have contiguous operations.
This is to be done so that, when the statement P=P+A executes, the addition operation is done with all the variables taken with their respective sizes (size if P=16 and A=8). The overall addition is to be done with 16-bits, padding zeros in MSB side of A.
Hence, convert all the variables to packed array as follows:
input [7:0] A;
input [3:0] N;
input M;
reg [15:0] P;
output reg [15:0] F;
For the second issue, the design assigns output in a procedural always block.
wire elements must be continuously driven by something, and cannot store a value. Henceforth, they are assigned values using continuous assignment statements.
reg can be used to create registers in procedural blocks. Thus, it can store some value.
When an input port is connected, it has to be driven through continuous assignments from parent module, hence input ports are always wire. While output from a module can be driven continuously through a wire, or can be driven through procedural assignments through reg. Following image shows the port connection rules.
To accomplish this in current design, the output port must be declared as output reg [15:0] F. This is the cause of compilation error shown.
Either way, you can have output [15:0] F with no reg and make continuous assignment to F as follows. This will synthesize F to wire:
output [15:0] F;
assign F=P;
SystemVerilog adds a logic datatype to remove confusion between usage of wire and reg declaration. A logic can be driven by both continuous assignment or blocking/non blocking assignment.
// Either continuous assignment
output logic [15:0] F;
assign F=P;
// Or procedural assignment
output logic [15:0] F;
// Inside always block
F=P;
For more information on packed and unpacked array, refer SystemVerilog Arrays link. Regarding port declarations, refer Wire and Net pdf. Refer SystemVerilog IEEE 1800-2012 for more information on logic datatype.

What is the difference between reg and wire in a verilog module?

When are we supposed to use reg and when are we supposed to use wire in a verilog module?
I have also noticed sometimes that a output is declared again as a reg. E.g reg Q in a D flip flop. I have read this somewhere - "The target output of procedural assignment statements must be of reg data type."
What are procedural assignment statements?
I have thoroughly googled this but was not able to find a clear explanation.
Wire:-
Wires are used for connecting different elements. They can be treated as physical wires. They can be read or assigned. No values get stored in them. They need to be driven by either continuous assign statement or from a port of a module.
Reg:-
Contrary to their name, regs don't necessarily correspond to physical registers. They represent data storage elements in Verilog/SystemVerilog. They retain their value till next value is assigned to them (not through assign statement). They can be synthesized to FF, latch or combinatorial circuit. (They might not be synthesizable !!!)
Wires and Regs are present from Verilog timeframe. SystemVerilog added a new data type called logic to them. So the next question is what is this logic data type and how it is different from our good old wire/reg.
Logic:-
As we have seen, reg data type is bit mis-leading in Verilog. System Verilog's logic data type addition is to remove the above confusion. The idea behind is having a new data type called logic which at least doesn't give an impression that it is hardware synthesizable. Logic data type doesn't permit multiple drivers. It has a last assignment wins behavior in case of multiple assignments (which implies it has no hardware equivalence). Reg/Wire data types give X if multiple drivers try to drive them with different values. Logic data type simply assigns the last assignment value. The next difference between reg/wire and logic is that logic can be both driven by assign block, output of a port and inside a procedural block like this
logic a;
assign a = b ^ c; // wire style
always (c or d) a = c + d; // reg style
MyModule module(.out(a), .in(xyz)); // wire style
Procedural blocks refers to always, always_ff, always_comb, always_latch, initial etc. blocks. While procedural assignment statements refers to assigning values to reg, integer etc., but not wires(nets).
wire elements must be continuously driven by something, and cannot store a value. Henceforth, they are assigned values using continuous assignment statements.
reg can be used to create registers in procedural blocks. Thus, it can store some value.
reg elements can be used as output within an actual module declaration. But,reg elements cannot be connected to the output port of a module instantiation.
Thus, a reg can drive a wire as RHS of an assign statement. On the other way round, a wire can drive a reg in as RHS of a procedural block.
For clear idea about declaration of reg or wire, refer the image below:
So, whenever inferring to sequential logic, which stores/holds some value, declare that variable/port as reg. Here, Q is a reg inside a module, but while instantiating this module inside some other module, then this port must be connected to a wire.
Remember, wire can only infer to combinational logic, while reg can infer to either combinational or sequential logic.
Dave's blog is a good source for detailed information. For further information, refer to synthesizing difference and Verilog wire-reg links.
Simple difference between reg and wire is, the reg is used in combinational or sequential circuit in verilog and wire is used in combinational circuit
reg is used to store a value but wire is continuely driven some thing and wire is connected to outport when module initialization but reg is con not connected

What's included in a verilog always #* sensitivity list?

I'm a bit confused about what is considered an input when you use the wildcard #* in an always block sensitivity list. For instance, in the following example which signals are interpreted as inputs that cause the always block to be reevaluated? From what I understand clk and reset aren't included because they dont appear on the right hand side of any procedural statement in the always block. a and b are included because they both appear on the right hand side of procedural statements in the always block. But where I'm really confused about is en and mux. Because they are used as test conditions in the if and case statements are they considered inputs? Is the always block reevaluated each time en and mux change value? I'm pretty much a noob, and in the 3 Verilog books I have I haven't found a satisfactory explanation. I've always found the explanations here to be really helpful. Thanks
module example
(
input wire clk, reset, en, a, b,
input wire [1:0] mux,
output reg x,y, z
);
always #*
begin
x = a & b;
if (en)
y= a | b;
case(mux)
2'b00: z = 0;
2'b01: z = 1;
2'b10: z = 1;
2'b11: z = 0;
endcase
end
endmodule
Any signal that is read inside a block, and so may cause the result of a block to change if it's value changes, will be included by #*. Any change on a read signal used must cause the block to be re-evaluated, as it could cause the outputs of the block to change. As I'm sure you know, if you hadn't used #* you'd be listing those signals out by hand.
In the case of the code you've provided it's any signal that is:
Evaluated on the right hand side of an assignment (a and b)
Evaluated as part of a conditional (en and mux)
...but it's any signal that would be evaluated for any reason. (I can't think of any other reasons right now, but maybe someone else can)
clk and reset aren't on the sensitivity list because they aren't used. Simple as that. There's nothing special about them; they're signals like any other.
In your example, the following signals are included in the implicit sensitivity list:
a
b
en
mux
clk and reset are not part of the sensitivity list.
This is described completely in the IEEE Std for Verilog (1800-2009, for example). The IEEE spec is the best source of detailed information on Verilog. The documentation for your simulator may also describe how #* works.
The simplest answer depends on if you are writing RTL, or a testbench. If you are writing RTL then you should try to forget about the concept of Sensitivity lists, as they don't really exist. There is no logic that only updates when an item on the list is triggered. All sensitivity lists can do in RTL is cause your simulation and actual circuit to differ, they don't do anything good.
So, always use "always #*" or better yet "always_comb" and forget about the concept of sensitivity lists. If the item in the code is evaluated it will trigger the process. Simple as that. It an item is in an if/else, a case, assigned to a variable, or anything else, it will be "evaluated" and thus cause the process to be triggered.
But, just remember, in digital circuits, there is no sensitivity list.

Resources