2

Hi there thanks for reading my question,

I don't know if what I'm trying to do is possible, or if it is stupid and there is an easier workaround.

I have a bunch of FIR filters, all of them with different coefficients. So I created a package file with declarations like

        package coeff_list is
            Type Coeff_type is array (0 to (((FIR_length - 1)/2))) of STD_LOGIC_VECTOR(17 downto 0);    
            CONSTANT Coeff_50_100 : Coeff_type := ("list of coefficients");
            CONSTANT Coeff_100_150 : Coeff_type := ( "other list of coefficients");
            ---- and many other lists similarly declared
        end package coeff_list; 

The thing is by doing this way I have to copy all my coefficients in the file myself from the text files... and it's long and boring especially if I need to modify them later.

So my question is... Is there a command or something to take a text file and treat it as a block of VHDL code ?

I know how to read a file in testbench and loading the parameters during the simulation would be easy but I'd like my coefficients to be pre-loaded from the beginning.

I tried googling the thing but didn't find anything relevant,maybe I didn't ask the right question. Anyway, here I am. Thanks for the help, I hope the question makes sense.

Floflow
  • 31
  • 4
  • ... or [How can I read binary data in VHDL/modelsim whithout using special binary formats](https://stackoverflow.com/questions/14173652/how-can-i-read-binary-data-in-vhdl-modelsim-whithout-using-special-binary-format)... etc. – JHBonarius Oct 31 '17 at 12:10
  • Search with *[vhdl] impure function textio* reveals one candidate that is not this question and the answer does not demonstrate textio. (There is no way to provide the value to a constant from a file without an impure function or providing the value of another object of the same type in VHDL using an impure function). Neither the duplicate candidate nor the reference provided in the comment above propose using an impure function, deriving the value of objects during the execution of process statements. –  Oct 31 '17 at 23:02
  • Since I explicitly pointed that what I was looking for didn't work with the code used for testbenches I don't see how "Read textfile in VHDL testbench" could be helpful in this case. Maybe the use of impure function is obvious for everybody, for me it was not. Therefore many thanks to user1155120 for actually reading the question and providing an explanation that works, instead of just pasting a link to an answer to a different problem. – Floflow Nov 01 '17 at 05:09
  • The answer to question this is proposed to be a duplicate uses a different method obtaining the ROM contents from a File. This one uses an impure initialization function to provide the value of the ROM array in it's declaration. The 'duplicate' provides the rom contents in a process statement and does not initialize a rom declaration. –  Mar 27 '21 at 17:16

1 Answers1

4

You can provide the value of your constants of array type Coeff_type with an impure function that uses TextIO to read from a file in the host file system:

library ieee;
use ieee.std_logic_1164.all;

package coeff_list is
    constant FIR_length:    natural := 17;  -- ADDED demo purposes

    Type Coeff_type is array (0 to (((FIR_length - 1)/2))) of 
                                            STD_LOGIC_VECTOR(17 downto 0);  

    --ADDED:
    impure function InitRomFromFile (RomFileNAme:  in string)  
            return Coeff_type;

    -- CONSTANT Coeff_50_100 : Coeff_type := ("list of coefficients");

    constant Coeff_50_100: Coeff_type := InitRomFromFile("file_path_name1");

    -- CONSTANT Coeff_100_150 : Coeff_type := ( "other list of coefficients");

    -- constant Coeff_100_150: Coeff_type := ("file_path_name2");

    ---- and many other lists similarly declared

end package coeff_list; 

package body coeff_list is

    impure function InitRomFromFile ( RomFileName: in string)  -- ADDED
            return Coeff_type is
        use std.TextIO.all;
        FILE romfile:  text open read_mode is romfileName; 
        variable RomFileLine:   line;
        variable rom:           Coeff_type;
        variable rom_value:     bit_vector(17 downto 0);
    begin 
        for i in 0 to (FIR_Length - 1)/2 loop  
            if ENDFILE(romfile) then  -- can get ordered shorter list
                rom(i) := (others => '0');
            else
                readline(romfile, RomFileLine);
                read(RomFileLine, rom_value);
                rom(i) := to_stdlogicvector(rom_value);
            end if;
        end loop;
        return rom;
    end function;
end package body;

For a file who's name is found by the string RomFileName to the impure function InitRomFromFile:

100000000000000000
000000000111111111
001111111111111000
010101010101010101
110011001100110011
001110011100111001

You can demonstrate with:

library ieee;
use ieee.std_logic_1164.all;
use work.coeff_list.all;

entity foo is
end entity;

architecture fum of foo is
    -- if not VHDL-2008:
    function to_string (inp: std_logic_vector) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  std_logic_vector (1 to inp'length) is inp;
    begin
        for i in input_str'range loop
            image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
        end loop;
        return image_str;
    end function;
begin
    process
    begin
        report "Coeff_50_100 contains";
        for i in Coeff_50_100'RANGE loop
            report HT & to_string(Coeff_50_100(i));
        end loop;
        wait;
    end process;
end architecture;

Which when analyzed, elaborated and simulated produces:

coeff_list.vhdl:70:9:@0ms:(report note): Coeff_50_100 contains
coeff_list.vhdl:72:13:@0ms:(report note):     100000000000000000
coeff_list.vhdl:72:13:@0ms:(report note):     000000000111111111
coeff_list.vhdl:72:13:@0ms:(report note):     001111111111111000
coeff_list.vhdl:72:13:@0ms:(report note):     010101010101010101
coeff_list.vhdl:72:13:@0ms:(report note):     110011001100110011
coeff_list.vhdl:72:13:@0ms:(report note):     001110011100111001
coeff_list.vhdl:72:13:@0ms:(report note):     000000000000000000
coeff_list.vhdl:72:13:@0ms:(report note):     000000000000000000
coeff_list.vhdl:72:13:@0ms:(report note):     000000000000000000

Noting the the coefficients are loaded from the file in array order from 0 and if the number of supplied values isn't sufficient you can fill with a default value thanks to evaluating whether or not ENDFILE(romfile) returns true.

You could also read the coefficients in as numeric literals and convert them to your target types element type in the function.

  • Thank you very much, it's much more comfortable with your code. Just to be sure, if I try to implement the code on my FPGA the coefficients will also be implemented or does this only work for simulation purpose ? – Floflow Oct 31 '17 at 07:53
  • Value of constants are assigned at elaboration. Most synthesis tools support TextIO for elaborating values of arrays of constants. Your synthesis vendor's tool documentation is the authority. The topic is initializing memory, which can include RAM as well as ROM. –  Oct 31 '17 at 08:44