How to share constants between many files in Verilog? - 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

Related

Testing multiple configurations of parameterizable modules in a Verilog testbench

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.

How to create buffer gate with Vivado Schematic?

I am learning Verilog with Vivado for the first time. I am trying to create simple buffer gate with it.
Here is the code I've tried. The first one is Design Source file with name 'inv.v'.
`timescale 1ns / 1ps
module inv(
input a,
output x
);
IBUF buffer(x, a);
endmodule
This code does create buffer gate, but it creates 2 of them.
I've also tried the following code.
`timescale 1ns / 1ps
module inv(
input a,
output x
);
assign x = a;
endmodule
However, this creates nothing. What I want is to create only one buffer gate, which is shown in above image. Does anyone know how?
p.s. I am using Vivado 2017.3 HLx Edition.
IBUF and OBUF are IO buffers: one drives into the logic array from the input pin; the other drives the output pin from the logic array. These are put in by the tool, because they are necessary for electrical reasons (ie reasons of voltage, current etc rather than reasons of boolean arithmetic).
This is why you are struggling to put in your own buffer. A buffer has no function at the boolean level, it is only necessary for electrical reasons. Your Verilog does not concern itself with such detail: such things are added automatically by logic synthesis/layout tools should they feel they are necessary for these electrical reasons (eg to drive a long track or to drive many inputs).
If you want to try something basic to see how your Verilog gets turned into (ie synthesised to) real gates, you'll need to try something that has some function at the boolean level, for example an AND gate. Or, if you want to make it as basic as possible, an invertor.
See the 7-series libraries guide for more info on ibuf & obuf primitives.
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_3/ug953-vivado-7series-libraries.pdf
Here is a quote from around page 341 of the file at the link.
"In general, IBUFs are inferred by the synthesis tool for top-level input ports to the design, so it is not necessary to specify them in the source code. However, if desired, they can be manually instantiated by copying the code from the appropriate Libraries Guide HDL template and it into the top-level of your code.
Your first example is the instantiation referred to in the libraries guide. For your second example, there is no component instance and Vivado determined no buffer is needed.

Defining different parameter value for simulation and synthesis

I'm using systemVerilog and I have a package that holds some of my modules parameter values (for example parameter SPI_RATE = 2_000_000;). Is there any way I can set one value for simulation and a different one for synthesis? (I'm using ModelSim).
For example I would like something like:
if(IN_SIM) begin
parameter SPI_RATE = 2_000_000;
end
else begin
parameter SPI_RATE = 1_000_000;
end
Thanks!
Yes, that's possible. SystemVerilog supports conditional compiler directives such as `ifdef, `ifndef, `else, `elsif, and `endif. Note that those directives are using a grave accent (ASCII 0x60) and not a normal apostrophe (ASCII 0x27).
Furthermore, most synthesis tools support the macro identifier SYNTHESIS. So, you could do the following:
`ifdef SYNTHESIS
parameter SPI_RATE = 1_000_000;
`else
parameter SPI_RATE = 2_000_000;
`endif
Yes. You can set a macro from the command line in any simulation using the +define plusarg, eg:
+define+SPI_RATE=2_000_000
Then somewhere in your code, you can say
parameter SPI_RATE = `SPI_RATE;
And in your synthesiser there will be a mechanism for setting the value of a macro: read the instructions for your synthesiser.
IMHO -
Using the first answer
`ifdef SYNTHESIS
is much preferred over the 3rd answer
/* synthesis translate_off */
The last form is a variation of /* synopsys translate_off */, which was unique to one synthesis tool.
The macro SYNTHESIS has been in common use for more than a decade, and should be defined by any synthesis tool, without any extra command line options.
If you want to run equivalence checking (rtl vs gate level netlist), you will probably need to define the SYNTHESIS macro by the method recommended for that equivalence tool.
With Synplify Pro, you can use the /*synthesis translate_off */ /*synthesis translate_off */ to accomplish this, a similar construct is usable in VHDL with appropriate syntax/comment changes. Xilinx Vivado uses // synthesis translate_off and // synthesis translate_on
const logic IN_SIM = 1'b0
/*synthesis translate_off */
|| 1'b1
/*synthesis translate_on */
;
The advantage of this construct is that it doesn't require any external scripting changes.

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.

Creating a 2-D net array in verilog

I was trying to write a program using 2-D net array. But when the code is checked it shows an error (expecting ';', found '['). How should I declare a 2d net array and how to use it ?
Below is the simple code for I written for verification (shows the above error).
module bin(a);
input [0:1] a[0:2];
endmodule
Multidimensional arrays and unpacked arrays as ports are not supported in Verilog. The only arrays Verilog supports in port lists are simple packed arrays (aka vectors).
SystemVerilog does support multidimensional arrays in all variations. All modern Verilog simulators are actually SystemVerilog simulators with backward comparability.
The preferred method to differentiate Verilog and SystemVerilog files is with the file extension. SystemVerilog files should use .sv while Verilog uses the the traditional .v.
Alternativly, simulators have an option to force .v files to be compiled as SystemVerilog. Several use -sv as the compiler option but some use a differnt identifier so you will need to refer to your manual or help-file. The disadvantage to this is approach happens when you are mixing legacy verilog files that happen to use variable/net names that became keep words in SystemVerlog. Using the proper file extension mitigates this risk by compiling each file based in the extension name.
You can't have an unpacked array in ports. Please note that Verilog is a Hardware Description Language, not a Software Language. Only those things will be supported in Verilog, which can be mapped into real hardware.
You can have a packed array in port, not an unpacked array.
Packed array, can be thought of as a bunch of wires in simplest terminology. However, unpacked arrays are not stored consecutively and hence they can't be treated as simple bunch of wires.
module bin(a);
input a[2:0][1:0];
endmodule
This should work, since it is a packed array dimension.Or else you can use a bus to represent your inputs and break it.
module bin(a);
input a[5:0];
wire [1:0] a1, a2, a3;
assign {a1,a2,a3} = a;
endmodule

Resources