Testing multiple configurations of parameterizable modules in a Verilog testbench - verilog

Say I have a Verilog module that's parameterizable like the below example:
// Crunches numbers using lots of parallel cores
module number_cruncher
#(parameter NUMBER_OF_PARALLEL_CORES = 4)
(input clock, ..., input [31:0] data, ... etc);
// Math happens here
endmodule
Using Verilog 1364-2005, I want to write a testbench that runs tests on this module with many different values NUMBER_OF_PARALLEL_CORES.
One option that I know will work is to use a generate block to create a bunch of different number_crunchers with different values for NUMBER_OF_PARALLEL_CORES. This isn't very flexible, though - the values need to be chosen at compile time.
Of course, I could also explicitly instantiate a lot of different modules, but that is time consuming and won't work for the sort of "fuzz" testing I want to do.
My questions:
Is there a way to do this by using a plusarg passed in from the command line using $value$plusargs? (I strongly suspect the answer is 'no' for Verilog 1364-2005).
Is there another way to "fuzz" module parameterizations in a testbench, or is using a generate block the only way?

Since $value$plusargs is evaluated at runtime, it can not be used to set parameter values, which must be done at compile-time.
However, if you use generate to instantiate multiple instances of the design with different parameter settings, you might be able to use $value$plusargs to selectively activate or enable one instance at a time. For example, in the testbench, you could use the runtime argument to only drive the inputs of a specific instance.

Related

Allowing re-declaration of certain parameters inside package for simulation

I have a system that has some timeouts that are on the order of seconds, for the purpose of simulation i want to reduce these to micro- or milli-seconds.
I have these timeouts defined in terms of number of clock cycles of my FPGAs clock. So as an example
package time_pkg
parameter EXT_EN_SIG_TIMEOUT = 32'h12345678;
...
endpackage
I compare a counter against the constant global parameter EXT_EN_SIG_TIMEOUT to to determine if it is the right time to assert an enable signal.
I want have this parameter (as well as a bunch of others) defined in a package called time_pkg in a file called time_pkg.v and I want to use this package for synthesis.
But when I simulate my design in Riviera Pro (or Modelsim) i'd like to have a second parameter defined inside a file called time_pkg_sim.v that is imported after time_pkg.v and overwrites the parameters that share the same name as already defined in time_pkg.
If I simply make a time_pkg_sim.v with a package inside it with the same name (time_pkg) then Riviera complains since i'm trying to re-declare a package that's already been declared.
I don't particularly want to litter my hdl with statements to check if a simulation flag is set in order to decide whether to compare the counter against EXT_EN_SIG_TIMEOUT or EXT_EN_SIG_TIMEOUT_SIM
Is there a standard way to allow re-definition of paramters inside packages when using a simulation tool?
No, you can't override parameter in packages. What you can do is have two different filenames that declare the same package with different parameter values, and then choose which one to compile for simulation or synthesis.
It may be a better idea to have a massive ifdef with the simulator falg inside the package. That way your code would not be littered with ifdef everywhere, just concentrated in one place. Moreover, the code inside the modules itself would not need to change.

Metaprogramming in Verilog

I would like to generate some combinatorial logic, and I would like to use recursive functions for this (with predefined preprocessor arguments, of course).
Simple example: Factorial function
I have a reg [10:0] number; and I want to have the logic for counting it's factorial, but I want some predefined variable msb to be determine the MSB and have number[msb:0] as a starting number, and go on from there.
And module would receive the number and call fact_func(number) which would calcuate the factorial, but only the shortened one.
Is something like this possible in Verilog? Have functions generate logic?
I'm not totally sure what you're asking, but building logic with recursive function calls is very much possible in Verilog. You'll need to build a parameterized module that includes a generate block instantiating itself with a progressively smaller (or larger) parameter value, until you get to the base case.
Here's an example of it in action. You could easily modify this to generate the Fibonacci sequence.
Keep in mind, however, that generating blocks this way can synthesize very, very large. You will need to ensure the tools you're using are succeeding in optimizing it to a reasonable size.

How to share constants between many files in Verilog?

I'm using a simple UART in Verilog that has as part of some definitions of ASCII values. For example:
parameter ASCII_a = 8'h61;
parameter ASCII_b = 8'h62;
parameter ASCII_c = 8'h63;
parameter ASCII_d = 8'h64;
parameter ASCII_e = 8'h65;
parameter ASCII_f = 8'h66;
etc. I'm trying to find the best way to create these parameters just once and then get access to them in multiple files. I'm used to VHDL when you can create a package and include that package where you like. I know that Verilog can use the include directive, but then I believe I need to surround it with ifdefs.
I would like to just create a SystemVerilog package, but I don't want to deal with Synthesis compatibility issues between vendor tools. (I know that Microsemi has this weird thing where you can include SV files, but they need to end in .v for example).
For you long-time Verilog coders, what's the preferred approach for this?
I wish I could say SystemVerilog packages would be the ideal choice, but like you, I have found compatibility issues with synthesis and formal verification tools that claim to be SystemVerilog compliant.
In lieu of that, I have seen two approaches commonly used:
1) Global `define statements, sourced once (or gratuitously sourced by every file that uses them):
`define ASCII_a 8'h61
I do not recommend this approach because of the risk of name collision, i.e. different IP modules using the same parameter name to represent different values. In this case, the effective value of the parameter is dependent on compile order, which is not what you want in most cases.
2) Parameter include files, commonly with a different extension (e.g. .vh, .vinc) to prevent them from being accidentally compiled outside a `include statement. For example:
my_params.vh:
localparam ASCII_a = 8'h61;
...
my_module.v:
`include "my_params.vh"
Some designers wrap their params file with ifdef, which is a good practice to use in cases where the IP includes multiple files and those files in turn include the parameter file.
`ifndef _my_params_h
`define _my_params_h
localparam ASCII_a = 8'h61;
...
`endif

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.

Resources