I am in the process of writing some Verilog modules for an FPGA design. I looked around the internet to find out how I best parametrize my modules. I see two different methods occurring often. I included an example hereunder of the two different methodologies.
Which of these methods is the best way to parametrize modules?
What is the difference?
Is it vendor-dependent (Altera vs Xilinx)?
The first method:
Module definition:
module busSlave #(parameter DATA_WIDTH = 1) (
input [DATA_WIDTH-1:0] bus_data,
input bus_wr,
...
);
endmodule
Module instantiation:
module top;
//DATA_WIDTH is 32 in this instance
busSlave #(.DATA_WIDTH(32)) slave32(
.bus_data(data_0),
.bus_wr(wr_0),
...
);
//DATA_WIDTH is 64 in this instance
busSlave #(.DATA_WIDTH(64)) slave64(
.bus_data(data_1),
.bus_wr(wr_1),
...
);
endmodule
The second method:
Module definition:
module busSlave(
parameter DATA_WIDTH = 1;
input [DATA_WIDTH-1:0] bus_data,
input bus_wr,
...
);
endmodule
Module instantiation:
module top;
//DATA_WIDTH is 32 in this instance
busSlave slave32(
.bus_data(data_0),
.bus_wr(wr_0),
...
);
defparam slave32.DATA_WIDTH = 32;
//DATA_WIDTH is 64 in this instance
busSlave slave64(
.bus_data(data_1),
.bus_wr(wr_1),
...
);
defparam slave32.DATA_WIDTH = 64;
endmodule
Thanks in advance
EDIT: a few corrections in the examples
The defparam statement is scheduled for deprecation. The IEEE Std 1800-2012, Annex C (Deprecation), section "C.4.1 Defparam statements" states:
users are strongly encouraged to migrate their code to use one of the
alternate methods of parameter redefinition.
Many features of Verilog are vendor-dependent.
Related
I have 4 files all in the same directory: main.rakumod, infix_ops.rakumod, prefix_ops.rakumod and script.raku:
main module has a class definition (class A)
*_ops modules have some operator routine definitions to write, e.g., $a1 + $a2 in an overloaded way.
script.raku tries to instantaniate A object(s) and use those user-defined operators.
Why 3 files not 1? Since class definition might be long and separating overloaded operator definitions in files seemed like a good idea for writing tidier code (easier to manage).
e.g.,
# main.rakumod
class A {
has $.x is rw;
}
# prefix_ops.rakumod
use lib ".";
use main;
multi prefix:<++>(A:D $obj) {
++$obj.x;
$obj;
}
and similar routines in infix_ops.rakumod. Now, in script.raku, my aim is to import main module only and see the overloaded operators also available:
# script.raku
use lib ".";
use main;
my $a = A.new(x => -1);
++$a;
but it naturally doesn't see ++ multi for A objects because main.rakumod doesn't know the *_ops.rakumod files as it stands. Is there a way I can achieve this? If I use prefix_ops in main.rakumod, it says 'use lib' may not be pre-compiled perhaps because of circular dependentness
it says 'use lib' may not be pre-compiled
The word "may" is ambiguous. Actually it cannot be precompiled.
The message would be better if it said something to the effect of "Don't put use lib in a module."
This has now been fixed per #codesections++'s comment below.
perhaps because of circular dependentness
No. use lib can only be used by the main program file, the one directly run by Rakudo.
Is there a way I can achieve this?
Here's one way.
We introduce a new file that's used by the other packages to eliminate the circularity. So now we have four files (I've rationalized the naming to stick to A or variants of it for the packages that contribute to the type A):
A-sawn.rakumod that's a role or class or similar:
unit role A-sawn;
Other packages that are to be separated out into their own files use the new "sawn" package and does or is it as appropriate:
use A-sawn;
unit class A-Ops does A-sawn;
multi prefix:<++>(A-sawn:D $obj) is export { ++($obj.x) }
multi postfix:<++>(A-sawn:D $obj) is export { ($obj.x)++ }
The A.rakumod file for the A type does the same thing. It also uses whatever other packages are to be pulled into the same A namespace; this will import symbols from it according to Raku's standard importing rules. And then relevant symbols are explicitly exported:
use A-sawn;
use A-Ops;
sub EXPORT { Map.new: OUTER:: .grep: /'fix:<'/ }
unit class A does A-sawn;
has $.x is rw;
Finally, with this setup in place, the main program can just use A;:
use lib '.';
use A;
my $a = A.new(x => -1);
say $a++; # A.new(x => -1)
say ++$a; # A.new(x => 1)
say ++$a; # A.new(x => 2)
The two main things here are:
Introducing an (empty) A-sawn package
This type eliminates circularity using the technique shown in #codesection's answer to Best Way to Resolve Circular Module Loading.
Raku culture has a fun generic term/meme for techniques that cut through circular problems: "circular saws". So I've used a -sawn suffix of the "sawn" typename as a convention when using this technique.[1]
Importing symbols into a package and then re-exporting them
This is done via sub EXPORT { Map.new: ... }.[2] See the doc for sub EXPORT.
The Map must contain a list of symbols (Pairs). For this case I've grepped through keys from the OUTER:: pseudopackage that refers to the symbol table of the lexical scope immediately outside the sub EXPORT the OUTER:: appears in. This is of course the lexical scope into which some symbols (for operators) have just been imported by the use Ops; statement. I then grep that symbol table for keys containing fix:<; this will catch all symbol keys with that string in their name (so infix:<..., prefix:<... etc.). Alter this code as needed to suit your needs.[3]
Footnotes
[1] As things stands this technique means coming up with a new name that's different from the one used by the consumer of the new type, one that won't conflict with any other packages. This suggests a suffix. I think -sawn is a reasonable choice for an unusual and distinctive and mnemonic suffix. That said, I imagine someone will eventually package this process up into a new language construct that does the work behind the scenes, generating the name and automating away the manual changes one has to make to packages with the shown technique.
[2] A critically important point is that, if a sub EXPORT is to do what you want, it must be placed outside the package definition to which it applies. And that in turn means it must be before a unit package declaration. And that in turn means any use statement relied on by that sub EXPORT must appear within the same or outer lexical scope. (This is explained in the doc but I think it bears summarizing here to try head off much head scratching because there's no error message if it's in the wrong place.)
[3] As with the circularity saw aspect discussed in footnote 1, I imagine someone will also eventually package up this import-and-export mechanism into a new construct, or, perhaps even better, an enhancement of Raku's built in use statement.
Hi #hanselmann here is how I would write this (in 3 files / same dir):
Define my class(es):
# MyClass.rakumod
unit module MyClass;
class A is export {
has $.x is rw;
}
Define my operators:
# Prefix_Ops.rakumod
unit module Prefix_Ops;
use MyClass;
multi prefix:<++>(A:D $obj) is export {
++$obj.x;
$obj;
}
Run my code:
# script.raku
use lib ".";
use MyClass;
use Prefix_Ops;
my $a = A.new(x => -1);
++$a;
say $a.x; #0
Taking my cue from the Module docs there are a couple of things I am doing different:
Avoiding the use of main (or Main, or MAIN) --- I am wary that MAIN is a reserved name and just want to keep clear of engaging any of that (cool) machinery
Bringing in the unit module declaration at the top of each 'rakumod' file ... it may be possible to use bare files in Raku ... but I have never tried this and would say that it is not obvious from the docs that it is even possible, or supported
Now since I wanted this to work first time you will note that I use the same file name and module name ... again it may be possible to do that differently (multiple modules in one file and so on) ... but I have not tried that either
Using the 'is export' trait where I want my script to be able to use these definitions ... as you will know from close study of the docs ;-) is that each module has it's own namespace (the "stash") and we need export to shove the exported definitions into the namespace of the script
As #raiph mentions you only need the script to define the module library location
Since you want your prefix multi to "know" about class A then you also need to use MyClass in the Prefix_Ops module
Anyway, all-in-all, I think that the raku module system exemplifies the unique combination of "easy things easy and hard thinks doable" ... all I had to do with your code (which was very close) was tweak a few filenames and sprinkle in some concise concepts like 'unit module' and 'is export' and it really does not look much different since raku keeps all the import/export machinery under the surface like the swan gliding over the river...
For example, is the following code legal (with regard to the way that the modules signals are mapped), or do I have to define explicit wires to connect the modules?
module A(
output logic x;
);
module B(
input logic y;
);
A instanceOfA();
B(
.y(instanceOfA.x)
);
You can for simulation, but most synthesis tools do not accept hierarchical references.
Yes you can do that. But it's better to take a common net, which which will be driven by multiple modules.
module top ();
wire common;
A instance_a (common);
B instance_b (common);
endmodule
I have a module which holds global variables. To declare some global variables, I need to use HDF5. I am also using a library, so I also need to include a header file. So the preamble of global_variable.F90 looks like this.
module global_variables
use HDF5
#include "finclude/petscsys.h"
#include "finclude/petscvec.h"
integer(HID_T) id_file
integer(HID_T) id_plist
Vec M, C, K
...
end module
Vec is a data type defined in the header file and HID_T is a data type defined in HDF5 module.
Now, I have a file which holds subroutines for I/O. This file also uses HDF5 and the same library used in global_variables.F90. So IO.F90 looks like this.
module io
use global_varibles
contains
subroutine read_input_file( vector )
Vec vector
integer HDF5err
call H5open_f( HDF5err )
...
end subroutine
end module
Question 1: compiler returns error when compiling IO.F90, saying that Vec is undefined data type. But it does not complain about HID_T. I thought global_variables module already contains both HDF5 modules and header files, using global_variables module in IO.F90 will handle every data type declaration but it seems not. Could you please help me understand what I am understanding wrong?
Question 2: Is there a way to restrict the effect of #include to the module where it is declared?
PS. If I include #include "finclude/petscvec.h" in IO.F90, which declares Vec, then it compiles well.
The syntax
Vec vector
is completely alien to Fortran. It works only because Vec is a C pre-processor (CPP) macro defined in the header file "finclude/petscvec.h" as
#define Vec PetscFortranAddr
That means that you must include the header file in every Fortran file in which you use the above syntax with Vec. The macro cannot be inherited using the Fortran use because it is not a part of Fortran.
The PetscFortranAddr is in the end defined in "finclude/petscdef.h" as an integer with 4 or 8 bytes depending on your system.
There is probably nothing you can do except reverse engineering what it in the end the pre-processor makes to be, but I wouldn't go that way, it may be unportable.
I want to write a testbench for a module that instantiates several components but has no significant outputs. To test the correctness I'd have to access variables of components of the uut. At least being able to access variables of the uut would be helpful.
I would imagine that to work a little like this:
uut: top_module port map(
i_clk => clk,
i_reset => reset
);
testbench: process
begin
wait for CLK_PERIOD;
report STD_LOGIC'image(top_module.flag) severity note;
end process;
Of course I can write the testbench in a way that it replaces the top module but then I wouldn't be able to test that model. Expanding the output of the top module/uut is also not really an option.
With VHDL 2008 you can use the new external names syntax:
alias int1 << signal .tb_top.u_ioc.int1 : std_logic >>;
With an earlier VHDL standard you have to use vendor-specific tools, e.g. signal_spy for Questa/ModelSim.
Another method would be to write your testbench at a lower level, e.g. connect your sub-components inside the testbench instead of testing the highest-level entity.
While inside a module A I'm trying to use the output of a module B as the input of another module C. Essentially this is a "go" switch that is flipped in module B after certain conditions are met and then this is supposed to be the trigger for module C to activate. Is it possible to link an output and input like this?
I've been reading around and found this image particularly helpful - however, I don't quite understand the concept of nets or if they will be helpful. Would wiring the output of module B to a reg that's used as input to module C work? Thanks.
EDIT:
I'm looking for something like this (involving 3 different modules) where I'm instantiating a module B and a module C within a module A. I want to connect B's output to C's input.
Your three modules example (image), using wire outB_to_inC to connect output to input:
//A.v
module A(inA, outA);
input wire inA;
output wire outA;
wire outB_to_inC;
B B_inst(.inB(inA), .outB(outB_to_inC));
C C_inst(.inC(outB_to_inC), .outC(outA));
endmodule
/////
//B.v
module B (inB, outB);
input wire inB;
output wire outB;
//... more code here
endmodule
/////
//C.v
module C (inC, outC);
input wire inC;
output wire outC;
//... more code here
endmodule
you can make those connections
For example:
module my_moduleA (inA, outA)
input inA;
output reg outA; //If you want to assign something to out inside an always block, it has to be output reg, otherwise you will have to use assign out from an always block.
//Put your logic here
endmodule
module my_moduleB (inB, outB)
input inB;
output reg outB; //If you want to assign something to out inside an always block, it has to be output reg, otherwise you will have to use assign out from an always block.
//Put your logic here
//Instantiation of module A
my_moduleA instance( //Here is the connection made between module A and B
.inA (inB),
.outA (outB));
endmodule
This is how the connections are made, if you want to make those connections on internal signals, then you can use wire type