Masking input unpacked array - verilog

I want to "mask" an input unpacked array given a specific signal. If that signal is 1, I want the input to be all zeroes instead of the given array.
module thing (
input clk,
input rst,
input packedBits[`PB_SIZE]
);
// ...
endmodule
module top (
input clk,
input rst
);
logic packedBits[`PB_SIZE];
mod_i thing (
.clk(clk),
.rst(rst),
// I can manually put `PB_SIZE zeroes, but I want the compiler to do it for me
.packedBits(rst ? {0,...,0} : packedBits)
)
endmodule
Putting just {0,0,0,0} when `PB_SIZE is 4 works, but how could I do it in a more generic way?

You can use the replication operator:
.packedBits(rst ? '{`PB_SIZE{0}} : packedBits)
Refer to IEEE Std 1800-2017, section 5.11 Array literals.
Here is a complete example on EDA playground. It runs on Cadence and Synopsys, but there are errors on Mentor. It seems Mentor does not support this syntax yet.
Simulators sometimes struggle with complex expressions connected to module ports. It is usually a good idea to simplify the connection using a separate signal.
`define PB_SIZE 5
module thing (input packedBits [`PB_SIZE]);
initial #1 $display("%m %p", packedBits);
endmodule
module tb;
bit rst = 1;
logic packedBits [`PB_SIZE];
logic packedBitsGated [`PB_SIZE] = rst ? '{`PB_SIZE{0}} : packedBits;
thing mod_i (.packedBits(packedBitsGated));
initial begin
packedBits = '{`PB_SIZE{1}};
#1 $display("%m %p", packedBits);
end
endmodule
This works on all 3 simulators on EDA playground.

You can use a default in an assignment patterns. Then there is no need to know its size.
.packedBits(rst ? '{default:0} : packedBits)

Related

what is the purpose #(10) in verilog instance?

Now I'm trying to understand some verilog code as the below,
dataproc #(10) proc01
(
.dout (dout01[9:0]),
.clk (clkin01),
.rst_n (rst_in01_n),
.din (dout[9:0])
);
actually I didn't get the purpose of this
#(10)
what is this? and what is the purpose in the verilog?
I'm usually using as the below way
dataproc u_dataproc
(
...
...
)
But I never been seen the before
#(10)
update
I've update the module.
module dataproc
#(parameter w = 1)
(
input clk,
input rst_n,
input [w-1:0] din,
output wire [w-1:0] dout
);
reg [w-1:0] NP_dout;
assign dout = NP_dout;
endmodule
It's a parameter, which you are overriding while making the instance of the module.
Suppose you have a module like below.
module temp();
parameter a = 2;
bit [a-1:0] b1;
endmodule
Now if you take instance of the above module and want to change the default parameter value (which in turn change the underlying hardware of that module), then you can do something like follow.
module abc();
temp t1();
temp #(4) t2(); // Changes the default parameter value
initial
begin
$display("Size of t1.b1 - %0d", $size(t1.b1));
$display("Size of t2.b1 - %0d", $size(t2.b1));
end
endmodule
// Output
Size of t1.b1 - 2
Size of t2.b1 - 4
Please note that parameters must be having a value before runtime or
in elaboration time. So you can't change parameters during simulation
run.

call by reference in verilog code

I am trying to change a c++ code into verilog HDL.
I want to write a module that changes one of its inputs. (some how like call by reference in c++)
as I know there is no way to write a call by reference module in verilog (I can't use systemverilog)
Here is a code that I wrote and it works. are there any better ways to do this?!
my problme is that the register I want to be call by reference is a big array. this way duplicates the registers and has a lot of cost.
module testbench();
reg a;
wire b;
reg clk;
initial begin
a = 0;
clk = 0;
#10
clk = 1;
end
test test_instance(
.a(a),
.clk(clk),
.aOut(b)
);
always#(*)begin
a = b;
end
endmodule
module test(
input a,
input clk,
output reg aOut
);
always #(posedge clk) begin
if (a == 0)begin
a = 1;
aOut = a;
end
end
endmodule
Verilog is not a software programming language; it is a hardware description language. The inputs to a module are pieces of metal (wires, tracks, pins); the outputs from a module are pieces of metal. If you want a port that is both an input and an output you can use an inout. However, inout ports are best avoided; it is usually much better to use separate inputs and outputs.
A Verilog module is not a software function. Nothing is copied to the inputs; nothing is copied from the outputs. A Verilog module is a lump of hardware: it has inputs (pieces of metal carrying information in) and outputs (pieces of metal carrying information out).
Your are right to say that you can use either pass-by-copy or pass-by-reference in SystemVerilog. If you wish to pass a large data structure into a function or into/out of a task, then passing by reference may save simulation time.
By reference means by address, so to translate this to hdl directly you would either need to provide a way for the module to get on that bus and perform transactions based on that address.
Or better, if you need this as an input take each of the items in the struct and make individual inputs from them. If it is pass by reference because it is an output or is also an output, then you create individual outputs for each of the items in the struct. The module then distinguishes between the input version of that sub item and output version of that sub item.
my.thing.x = my.thing.x + 1;
becomes something like
my_thing_x_output = my_thing_x_input + 1;

Designing a 3-bit counter using T-flipflop

module tff(t,i,qbprev,q,qb);
input t,i,qbprev;
output q,qb;
wire q,qb,w1;
begin
assign w1=qbprev;
if(w1==1)begin
not n1(i,i);
end
assign q=i;
not n2(qb,i);
end
endmodule
module counter(a,b,c,cin,x0,x1,x2);
input a,b,c,cin;
output x0,x1,x2;
reg a,b,c,x0,x1,x2,temp,q,qb;
always#(posedge cin)
begin
tff t1(.t(1) ,.i(a),.qbprev(1),.q(),.qb());
x0=q;
temp=qb;
tff t2(.t(1) ,.i(b),.qbprev(temp),.q(),.qb());
x1=q;
temp=qb;
tff t3(.t(1) ,.i(c),.qbprev(temp),.q(),.qb());
x2=q;
a=x0;
b=x1;
c=x2;
end
endmodule
This is my code in verilog. My inputs are - the initial state - a,b,c and cin
I get many errors with the first of them being "w1 is not a constant" What doesn this mean?
I also get error "Non-net port a cannot be of mode input" But I want a to be an input!
Thank you.
Modules are instantiated as pieces of hardware. They are not software calls, and you can not create and destroy hardware on the fly therefore:
if(w1==1)begin
not n1(i,i);
end
With that in mind I hope that you can see that unless w1 is a constant parameter, and this is a 'generate if' What your describing does not make sense.
instance n1 is not called or created as required, it must always exist.
Also you have the input and output connected to i. i represent a physical wire it can not be i and not i. these need to be different names to represent different physical wires.
In your second module you have :
input a,b,c,cin;
// ...
reg a,b,c; //...
Inputs can not be regs as the warning says, just do not declare them as regs for this.
input a,b,c,cin;
output x0,x1,x2;
reg x0,x1,x2,temp,q,qb;

Tasktop.v(10): (vlog-2110) Illegal reference to net "b"

I am writing a program in verilog. Total 3 AND Gates, the output of first 2 AND Gates is input to the 3rd Gate, and i am required the output of 3rd Gate. Please let me know what is the problem with my program. I am attaching my Program
//enter Top Module
module TOP;
wire a,b;
reg out;
initial
begin
#3 a=1;
#3 b=1;
#3 b=0;
end
Two_AND s(a,b,out);
endmodule
//.....................
//Main Program
module Two_AND (a,b,out);
input a,b;
output out;
reg out;
and g1(out1,a,b);
and g2(out2,b,c);
and g3(out3,out1,out2);
endmodule
In module Two_AND (a,b,out); you have these lines:
and g2(out2,b,c);
c is not defined.
out1, out2 and out3 are also not defined but are outputs and will be created as 1 bit wires by default which is ok in this instance.
but your output out is not driven, where you have used out3 you need to use out.
module Two_AND (
input a,
input b,
input c,
output out
);
wire out1,out2;
and g1(out1,a,b);
and g2(out2,b,c);
and g3(out,out1,out2);
endmodule
#Morgan is right.
However, the error you get is because there is something wrong with your TOP module.
You should have defined a and b as reg and out as wire.
Only regs can be assigned within an initial or always block.
And outputs of modules should be connected to wires.
Also, since an input c is added to your module, you should consider it while you are instantiating your Two_AND in your TOP module.
I think the previous answers were very instructive and helpful. I only want to add a small tip. I recommend you that always add `default_nettype none to your verilog codes. for example you have used "out1" and "out2" wires but you haven't define them. if you don't want to be confused, you should add that to your codes.

How to write a module with variable number of ports in Verilog

I would like to write a module with a variable number of inputs, i.e. depending on some parameter, the result would be:
module my_module #(LENGTH)(
input clk,
input rst_n,
input [LENGTH-1:0] data_1
);
//...
endmodule
or
module my_module #(LENGTH)(
input clk,
input rst_n,
input [LENGTH-1:0] data_1,
input [LENGTH-1:0] data_2,
input [LENGTH-1:0] data_3
);
//...
endmodule
Would it be possible to do this in Verilog or Systemverilog or would I have to write a script, let's say in Python, in order to generate the code for a specific module with fixed number of inputs? (it might be more than 1000 inputs)
There are no variable number of ports in SystemVerilog, but you could use a port that is a parameterized array.
module my_module #(int LENGTH, DEPTH)(
input clk,
input rst_n,
input [LENGTH-1:0] data[DEPTH]
);
//...
endmodule
Otherwise, you would need to use a script to generate the code.
Use a two dimensional input with a parameterized size. Added a generate for loop that can be used to set signals individually. Although many operations can be done with smart array operations.
module my_module #(SIZE, LENGTH)(
input clk,
input rst_n,
input [SIZE-1:0][LENGTH-1:0] data_in_array,
output [SIZE-1:0][LENGTH-1:0] data_out_array
);
genvar N;
generate for (N=0; N<SIZE; N++) begin :la_coolOps
//Do cool operations here. For example instantiate a module for every data_in
end
//...
endmodule
Edit:
As Mehran Torki points out: The syntax above will work for SystemVerilog only. Verilog does not allow for multiple packed arrays. Use input [LENGTH*SIZE-1:0] data_in_array.
I would add to these other answers that ports are just groupings of wires. While having 3, 1-bit wires named a, b, and c might be easier to read and understand, there is no physical/logical difference between a single, 3-bit wire abc, where abc[0] corresponds to a, abc[1] corresponds to b, and abc[2] corresponds to c.
So, you can always just expand or shrink a single (or multiple) signal(s) to get however many bits you need. It may not be as neat, but it will work. In the receiving module, you can then part-select the bus in whatever manner you like. So, you could have one really long wire the shrinks or expands (wire [(SOME_PARAM*8)-1:0] my_input_wire), or with SystemVerilog an array (wire [7:0] my_input_wire[0:SOME_PARAM-1])
If this is just testbench/verification code, the other thing you could do in SystemVerilog is use a dynamic array
As others said, there is no direct way to do this, but another workaround is to use SystemVerilog interfaces, where you define all the inputs that you want in the interface definition and inside the module only use the ones that correspond to the parameter. Below is a sample:
module my_module #(LENGTH)(
input clk;
input rst_n;
output o;
interface i_data;
);
logic outValue;
generate
case (LENGTH) //Based on the value of LENGTH, use corresponding data
1: outValue = i_data.data_1;
2: outValue = i_data.data_1 + i_data.data_2;
3: outValue = i_data.data_1 + i_data.data_2 + i_data.data_3;
endcase
endgenerate
always #(posedge clk) begin
if (~rst_n)
o <= '0;
else
begin
o <= outValue;
end
endmodule
You can still use a parameterized array for data and a for-generate loop if your outputs are similar.
With System verilog we can import a package instead of having parameterization and define types in the package to be used in the portlist.
module mymodule
import mymodule_pkg::*;
(
input portlist_t portlist
);
endmodule
And define multiple copies of the package with different variants of the port list and compile whichever version is required. eg
package mymodule_pkg;
localparam LENGTH=5;
typedef struct packed {
logic [LENGTH-1:0] data_1,
logic [LENGTH-1:0] data_2,
logic [LENGTH-1:0] data_3
} portlist_t;
endpackage
As with the interface solution there will be situations where you run into issues, like having different iterations of the module instantiated together.

Resources