Instantiate vector of custom modules in Verilog with additional parameters - verilog

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.

Related

Vivado Error named: [Synth 8-6859] multi-driven net on pin

module top(
input [59:0] first,
input [59:0] second,
output out
);
wire [14:0] out_wire;
assign first[19:0]= 20'b1111111111111111111;
assign first[39:20]= 20'b0000000000000000000;
assign first[59:40]=20'b11001100110011001100;
.....
...
..
I am getting the error in the title when synthesizing if I include the assign statements. How do I initialize these 3 assignment values to first[59:0] properly?
The whole design is combinational.
You say
You want to inialise the values.
The whole design is combinational.
That is contradictory. Combinational signals always have a value assigned to them. you can't initialise them, not even with an initial statement.
Thirdly: Your first is an input.
If you want to assign a value to that it must be done outside the module. Thus you must make sure that whatever is driving your 'first' has the correct initial value. If that is a testbench you have to solve the problem there.

Continus assignment to verilog module instance

Is it possible to use assign keyword with module instances?
Lets assume I have a module logarithm which works as it's intended. In some other module, I want to have: A = log(B) + log(C).
Is there any efficient way other than the following to do so?
wire [3:0] logB;
wire [3:0] logC;
Logarithm log(logB, B);
Logarithm log(logC, C);
assign A = logB + logC;
And is it known as a gate-level design or a data-flow one?
If it is not data-flow, would you please present a data-flow alternative to this code?
Well your assign keyword in the code is not working on module instances. Rather, it is working on the outputs of those module instances.
The way you are assigning to A should help you get the desired output provided you have set its width accordingly. And it is a data flow representation
There is one mistake in your given lines of code though. You can not use the same instance name log for both the instantiations of the module Logarithm. They have to be unique.

Can I use generate-endgenerate block inside initial in SystemVerilog?

For e.g.
initial
begin
generate
for(genvar i; i < 4; i++)
//Code
endgenerate
end //initial
I'm getting error using QuestaSim with the concept. "Near generate: syntax error, unexpected generate "
No. generate blocks are evaluated during elaboration time. While initial,always and other procedural blocks start at zero simulation time, that is, run-time. Referring to Systemverilog IEEE 1800-2012 :
Generate schemes are evaluated during elaboration of the design.
Although generate schemes use syntax that is similar to behavioral
statements, it is important to recognize that they do not execute at
simulation time.
They are evaluated at elaboration time, and the
result is determined before simulation begins. Therefore, all
expressions in generate schemes shall be constant expressions,
deterministic at elaboration time.
In Verilog, instantiating a module means adding extra hardware to the board.
This hardware must be added before simulation starts(i.e. at compile time). You can not add/remove hardware during run time. You can either conditionally instantiate a module or multiply instantiate it, but never at run time.
Refer generate block syntax error question for an idea about your error. Also, refer this question for generate and genvar understanding. Referring IEEE 1800-2012 Chapter 27 for more information.
EDIT:
To create and pass multiple interface instances, the total number of interface instances must be governed by some parameter or macro. You can use this parameter in for loop in generate block to create distinct instances and set each of them using different key as follows:
// Generate multiple instances of interface
genvar i;
generate
for(i=0;i<NUM_OF_INTERFACES;i++)
begin
// Generate clk with different period for each instance
always #(i+1) clk[i] = ~clk[i];
inter in(clk[i]); // Create multiple instances here
initial
begin
// Set each and every instance
uvm_config_db#(virtual inter)::set(null,"*",$sformatf("in_%0d",i),in);
end
end
endgenerate
A complete example is created at EDAPlayground Multiple Interface link. Creating multiple instances can be referred from this question.

Verilog module instantiation

I am having a bit of trouble instantiating a module in verilog. I am using the Altera Quartus platform to develop and simulate the verilog code.
I have followed this example (among several others):
http://www.asic-world.com/verilog/verilog_one_day4.html
I have written a module (maximum) which finds the maximum between two signed inputs.
Another module I am developing is a systolic array for genetic sequence alignment. The details are not important, however when I try to instantiate a maximum module I get an error.
This is my code so far:
module maximum (a, b, out);
input signed [15:0] a;
input signed [15:0] b;
output reg signed [15:0] out;
always #* begin
if (a>b)
assign out = a;
else
assign out = b;
end
endmodule
and I instantiate in another module systolic_PE (all of this is in the same file seqalign.v)
maximum m0(.a(tempB), .b(diag), .out(tempA));
And I get the error :
'Verilog HDL syntax error at seqalign.v(139) near text "m0"; expecting
"<=" or "="'
I checked everything I have done so far, and I cant seem to see anything I have missed out on.. could anyone be kind enough to guide me?
Also on a side note:
Instantiation of a module in verilog
I was trying to instantiate my module in a if statement, so I tried outside of the if statement in a always #(posedge clk) block, and I get the error
HDL syntax error at seqalign.v(88) near text "("; expecting ";"
Looking over the code you posted in your comment, the issue is from instantiating your module inside your always #(posedge clk) block on line 70. You never instantiate modules inside of procedural blocks (always, initial, etc).
As Verilog is a Hardware Descriptive Language, you have to be in the mindset of designing hardware when writing your code. Module instantiation is like soldering a chip onto a PCB, at design time you either do it, or you dont, and that component stays there for all time. You dont say, well, I want this chip here some of the time, but take it off the PCB when the system gets into these states. In your code, you conditionally instantiate your module if state is 3. However, state changes over time. So that is akin to saying, when the register containing state reads 3, place down this chip into the system, otherwise, it doesnt exist and take it out. On a code level, think of instantiated modules as their own procedural blocks, just as you dont put always inside of other always, dont put modules in always blocks (of course, module definitions/declarations can have always blocks inside them).
Modules are persistent and compile time constant, so you can use generates to conditionally instantiate modules at compile time (ie, decide whether or not to include the module in the design when building the system). But in your code, you are conditionally instantiating at simulation time, which is not allowed as described above.
You can do one of two things to solve your problem. One would be to move your task from your submodule maximum into the systolic_PE module and use it to get the maximum of your variables tby calling it (line 123 would become something like tempA <= convert(.a(0), .b(diag+match)); with a and b added as inputs to your task). Or, instantiate the module outside the always block, but youll need to change your task to be a procedural block like you have in the actual post.

Why is there no assign statement in this Verilog function?

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 = &in; 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.

Resources