Create a module with 3 inputs and 4 outputs that behaves like wires that makes these connections:
a -> w
b -> x
b -> y
c -> zThe diagram below illustrates how each part of the circuit corresponds to each bit of Verilog code. From outside the module, there are three input ports and four output ports.
When you have multiple assign statements, the order in which they appear in the code does not matter. Unlike a programming language, assign statements (“continuous assignments”) describe connections between things, not the action of copying a value from one thing to another.
One potential source of confusion that should perhaps be clarified now: The green arrows here represent connections between wires, but are not wires in themselves. The module itself already has 7 wires declared (named a, b, c, w, x, y, and z). This is because
https://hdlbits.01xz.net/wiki/Wire4input
andoutput
declarations actually declare a wire unless otherwise specified. Writinginput wire a
is the same asinput a
. Thus, theassign
statements are not creating wires, they are creating the connections between the 7 wires that already exist.
This is basically the same as the last exercise, with the only difference being that multiple wires need to be created in this case. If this doesn’t make sense, try drawing a diagram of top_module and its associated ports.
The solution with the fewest lines of code is as follows:
module top_module (
input logic a, b, c,
output logic w, x, y, z );
// Concatenation can be used on either side of an assignment
assign {w, x, y, z} = {a, b, b, c};
endmodule : top_module
Although this is a short solution, I don’t necessarily think that it’s a good one. First, the use of the concatenation operators is permissible here since there isn’t any real logic involved; just connecting ports with wires. However, as the logic gets more complicated, opting for this style of assignment can make code harder to understand and modify quickly. Although it’s nice to have fewer lines of code, I never value this metric more than clarity and readability. In addition, I’m not really a fan of the Verilog-2001 concise port list (forgive me, Clifford Cummings, I have failed you 😞), which is listing multiple inputs or outputs of a given type on a single line, such as:
input logic a, b, c
Although this makes things simpler in this case, I don’t feel that this approach scales as port names get longer and their numbers skyrocket. This largely boils down to personal preference, but I feel that a cleaner general approach is to have separate port declarations and concurrent assignments for each output. There are definitely cases, as you will see, when concatenation makes things much, much easier. My preferred solution is as follows:
module top_module (
input logic a,
input logic b,
input logic c,
output logic w,
output logic x,
output logic y,
output logic z );
// Note that the order of these assignments doesn't matter!
assign w = a;
assign x = b;
assign y = b;
assign z = c;
endmodule : top_module
This solution is definitely more verbose, but as modules get more complicated, I feel that this approach sets you up to have much more easily understood and modifiable code. Someone out there is furious that I wrote this and wants to destroy me. 🤣