Search code examples
vhdl

Replace code segment by text file content in VHDL


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.


Solution

  • 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.