Harry
Harry

Reputation: 936

Loading configuration parameters from file in a SystemVerilog testbench

I'm trying to write a SystemVerilog testbench, which loads pre-calculated configuration parameters from a file.

My problem is that SystemVerilog seems to be rather strict regarding "constant expressions". If I understand the LRM correctly, typical configuration (such as module parameterization, and range specifications in vector declarations) must be elaboration-time constant. However, things like file accesses happen later, at simulation time.

I'm coming from a VHDL background, where my typical workflow involves loading test configurations (for many thousands of pre-computed test cases) from files. Have I missed a simple trick, or is it not possible to do the same in SystemVerilog?

Assuming it is not possible, how would a SystemVerilog expert do this? The only idea I could think of was to auto-generate SystemVerilog packages containing the configuration data (instead of raw data files). That way, everything would be accessible at elaboration time.

However, that would be quite an ugly hack. And I couldn't think of a neat way to programmatically access thousands of different test cases. (A nice thing about using files was that file names could be constructed programmatically using simple string manipulations).

Minimal example

Here's a minimal example, showing that a parameter read from a file cannot be used in some of the ways I would like.

example.txt (just contains a number, in ASCII):

123

example.sv:

////////////////////////////////////////////////////////////////////////////////
// Module
////////////////////////////////////////////////////////////////////////////////
module my_module #(int PARAM);
endmodule

////////////////////////////////////////////////////////////////////////////////
// Testbench
////////////////////////////////////////////////////////////////////////////////
module tb;
    
    function automatic int read_file(input string filename);
        const int fid = $fopen(filename, "r");
        var int value;
        $fscanf(fid, "%d", value);
        $fclose(fid);
        return value;
    endfunction
    
    // Load a number from a file.
    const int PARAM = read_file("example.txt");
    
    // ERROR: Ranges must be bound by constant expressions.
    const bit [PARAM-1:0] x = 0;
    
    // ERROR: Parameter expressions must be constant.
    my_module #(PARAM) M();
endmodule

Upvotes: -1

Views: 401

Answers (2)

dave_59
dave_59

Reputation: 42738

A const variable is not a compile time constant; it is a write once at run-time initialization. For static variables, that happens once at time 0. For automatic variables, that happens each time you enter the procedural scope where the variable is declared.

Compile time constants are a literal like 1234, or a parameter that can be set with a constant expression of other parameters and literals. Constants are required for values that define things like data type widths.

You can use compiler `define macros that can be set from a file or the command line. But is the file is automatically generated then best thing to do is generate a SystemVerilog package with these parameter defined.

Upvotes: 1

Tudor Timi
Tudor Timi

Reputation: 7573

You would normally pass the parameters from the tool command line. These are specific to each simulator. For example, something like -g tb.PARAM=10.

You'd have a script that reads the configuration file and converts is to the appropriate list of command line args.

Upvotes: 2

Related Questions