Auto generation of memory files

Hi,

I was wanting to know if there was a way to auto-generate a mif or hexout file in quartus (or in general verilog) based on the set parameters in a verilog file?

The application is for a NCO function that used a memory lookup (for sin table) approach rather that cordic. The sin table can be auto generated by a perl script that I can write in which I can manually set the memory depth and amplitude resolution (which are parameters of the NCO) however I would like the module to allow the end user to set an arbitrary bit width and phase angle width and at synthesis time have a script or some other clever code generate the required memory file for me.

If anyone has any ideas how to achieve this kind of trickery I would apreciate the advise.

Regards

Paul Solomon

Reply to
Paul Solomon
Loading thread data ...

Or at the very least, if there was a way to select a memory file which is set in a

defparam blah.init_file = "sin_lut_32_16.mif";

further up in the file there is a parameter A = 32, B = 16; etc so it would be nice to be able to do something like...

defparam blah.init_file = "sin_lut_$(PARAMETER_A)_$(PARAMETER_B).mif";

is there any form of string substitution such as above available in verilog?

Regards,

Paul Solomon

Reply to
Paul Solomon

Here's just one possible idea - not tested, but I think it will work.

Here's your parameterisable module:

module Wotsit(a,d); parameter nA = 8; // number of address bits parameter nD = 10; // number of data bits input [nA-1:0] a; output [nD-1:0] d;

always @a d = ;

`ifndef SYNTHESIS // this line is executed for simulation only initial $display("Wotsit_instance %m: nA=%0d, nD=%0d", nA, nD); `endif

endmodule

Now, when you simulate, you get a line in the transcript that has all the relevant information in it. Get a Perl or Tcl script to process the transcript to extract those lines and munge them to construct the appropriate memory file, with an appropriate file name.

There's an urgent need for a little Perl or Tcl utility that will convert among all the various memory-image formats that we EDA folk need - Verilog $readmemb, Xilinx and Altera memory formats, Intel hex and so on. Perhaps someone has already done it?

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223          mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573                Web: http://www.doulos.com

The contents of this message may contain personal views which 
are not the views of Doulos Ltd., unless specifically stated.
Reply to
Jonathan Bromley

Hi Johnathan,

Thanks for this, this is good. I have already got a perl and a tcl script to generate the memory files, and I think I could adopt them to use this method.

There is one other missing peice though..

in my top level design I want to create 2 instances of this module with different parameters, I will then need to create 2 different memory files with different names (one for each instance that has different parameters). In the definition of this nco module I need a clever way to reference the different files. I know I could make a string parameter filename = "sin_lut_A_B.mif" etc however, I would much rather a way I can auto generate this string within the verilog code so that it automaticcaly looks for the correct file based on the parameters.

this filename needs to be passed to another module (the rom) as a defparam.

If you have any ideas here I would love to hear them, and thanks for your help so far!

Regards,

Paul Solomon

Reply to
Paul Solomon

I think you'll find that my suggestion deals with this. The idea is that the module contains a $display statement that writes out the value of its parameters (nA, nD in my example) and also its hierarchical instance name using the %m specifier in $display. This $display statement won't get executed until the whole thing is elaborated in the simulator, so somewhere early in the transcript you should see lines that look like this...

Wotsit_instance top.widget.coarse_nco.LUT: nA=7, nD=4 Wotsit_instance top.widget.fine_nco.LUT: nA=12, nD=16

Because these lines start with a really unusual string (Wotsit_instance) and have a fixed format, you could easily grep through the transcript looking for them and pulling out the information from those lines. Because the lines also contain the full hierarchical path names to the LUT instances, you can patch-up the memory files to deal with those specific instances.

Apologies if I've missed the point, but I think it will work.

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223          mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573                Web: http://www.doulos.com

The contents of this message may contain personal views which 
are not the views of Doulos Ltd., unless specifically stated.
Reply to
Jonathan Bromley

I am not sure that we are on the same page here.. I am trying to have this work for synthesis, not simulation, the mif file will be a rom image. I kind of have it working now the way I want with this code...

module nco(clk, clk_en, reset, phi, sin, cos); parameter ACC = 18; parameter PHA = 17; parameter PHA2 = "17"; parameter AMP = 12; parameter AMP2 = "12";

--- skipped various lines to get to interesting bit----

altsyncram sin_lut( .address_a(phase), .clock0(clk), .q_a(sin_out));

defparam sin_lut.OPERATION_MODE = "ROM"; defparam sin_lut.WIDTH_A = AMP-1; defparam sin_lut.WIDTHAD_A = PHA-3; defparam sin_lut.INIT_FILE = {"sin_lut_",PHA2,"_",AMP2,".mif"};

I would ideally like to defing this last line here in terms of PHA and AMP without having to use the additional dodgy PHA2 and AMP2, this would also prevent the wrong file from being used.

Regards,

Paul Solomon

Reply to
Paul Solomon

Sorry, I had quite badly misunderstood you.

OK. What I was trying to get at was this: Suppose the upper-level module instantiates

nco #( 22, 19, "19", 10, "10") this_nco (....); // ACC, PHA, PHA2, AMP, AMP2

You need to prepare, in advance, the file "sin_lut_19_10.mif". My $display trick was intended to make it possible to automate that step, based on the design itself.

Understood.

Verilog-2001 $sformat() will do the job, but it's fairly certain that the synth tool won't accept that.

Here's another idea: Use the numbers to build an ASCII code... again this depends on a Verilog-2001 feature, sized parameters.

parameter PHA = 17; parameter AMP = ...

// Don't let users mess with the following: // parameter [7:0] PHA2 = "A" + PHA; // 0 -> "A", 1 -> "B", .... 25 -> "Z"

Now PHA2 is an automatically-generated 1-character string and your file name will be something like sin_lut_Q_M.mif - a Perl script can presumably easily infer the numbers from that. I don't know whether Quartus will accept sized parameters, but most tools are OK with it.

Sorry to be so stupid about your original problem.

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223          mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573                Web: http://www.doulos.com

The contents of this message may contain personal views which 
are not the views of Doulos Ltd., unless specifically stated.
Reply to
Jonathan Bromley

Thanks Jonathan,

I have now got it working more or less that way I would like, I will auto generate all the various mif files ahead of time and then select the correct one using the following method (which is a variation on your suggestion).

module nco(clk, clk_en, reset, phi, sin, cos); parameter ACC = 18; parameter PHA = 17; parameter AMP = 12;

localparam [7:0] PHA1 = "0" + (PHA % 10); localparam [7:0] PHA2 = "0" + ((PHA / 10) % 10); localparam [15:0] PHA_NUM = {PHA2,PHA1}; localparam [7:0] AMP1 = "0" + (AMP % 10); localparam [7:0] AMP2 = "0" + ((AMP / 10) % 10); localparam [15:0] AMP_NUM = {AMP2,AMP1};

--- skipped various lines to get to interesting bit----

defparam sin_lut.INIT_FILE = {"sin_lut_",PHA_NUM,"_",AMP_NUM,".mif"};

This seems to be working fine,

I have tried a number of different approaches to get it down to fewer lines such as

localparam [15:0] PHA_NUM {("0" + ((PHA / 10) % 10)),("0" + (PHA % 10))};

and

'define NUM(a) {("0" + ((a / 10) % 10)),("0" + (a % 10))} then using defparam sin_lut.INIT_FILE = {"sin_lut_",`NUM(PHA),"_",`NUM(AMP),".mif"};

but neither of these approaches work, which is a shame as the solution I have seems unnecessarily large and messy.

Thanks again for your help

Regards,

Paul Solomon

Reply to
Paul Solomon

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.