I am trying to make a synthesizable filter in verilog. I have the fixed-point filter coefficients in a text file. I am looking for an elegant and scalable way to pass on these filter coefficients. The filter will not be a simple beast: it will contain multiple sub-modules, and each of which may need a single co-efficient.
Since the filter coefficients will be constant, I would like them to be hardcoded, i.e., not consume any registers in implementation.
I have a few options/wishes below, along with their possible downsides:
readmemh
or some similar trick to read the coefficients into a memory (reg [15:0] coeff [0:1023]
) in the enclosing module, and pass on the coefficients from memory to FIR stages using a generate block. It should look something like:generate
for (i = 0; i < 3 ; i = i + 1) begin: k
filter_stage(input[k], coeff[k], output[k]);
end
endgenerate
The downside is that the memory must be in the module that encloses the filter stages, otherwise I will have to go through portlist hell.
Use systemverilog packed arrays as module ports. The downside is that systemverilog support for some synthesis tools is sub-optimal.
This is a wish: Some sort of global lookup structure which is accessible to each module, so I don't have to manually wrap modules and adjust portlists just to pass coefficients to the right place.
I would want to know if option 3 is at all possible. If not, what else could I do?
Thanks.
If you are able to use SystemVerilog, then you can put constants (maybe an array of constants) in a package, and import
(not include
) the package in other modules which need access.
Its been written about a lot, here is a starting point include/import.
SystemVerilog packages are synthesizable, they not just for verification.
I have used them for Vivado RTL work for several years, seems like since Vivado 2016.
This link says packages are supported for Quartus Synthesis in 2012 Altera support for SV
The only place you might have synthesis support issues is with ISE; the last release was 2014. I don't know about Microsemi or the other mid-sized or small FPGA vendors.
You don't need option 1, you don't need ports as mentioned in 2, and you don't have to wrap anything or use ports as mentioned in 3.
An array of constants in a package should work well.
The package syntax is lightweight, you could have Matlab or Python or whatever you use for coefficient generation write out the SystemVerilog package with the constants.
Example package defines an array of constants
// Write me out with Python or Matlab generated coefficients
package my_coef_pk;
// type int is 32 bit, treated as signed
localparam int my_coef_array [4:0] =
'{
2**16,
1,
2,
-1,
-(2**16)
};
endpackage
Example testbench imports the package and prints the array
module tb ();
// import the contents of the package here
import my_coef_pk::*;
// example access the localparam array defined in the package
initial
foreach(my_coef_array [i])
$display("my_coef_array = %d", my_coef_array [i]);
endmodule
Produces
my_coef_array = 65536
my_coef_array = 1
my_coef_array = 2
my_coef_array = -1
my_coef_array = -65536