So, the following ROM initialization code should be entirely synthesizable. Not so, according to the latest version of Vivado, which proudly declares "ignoring unsynthesizable construct: non-synthesizable procedure call", zeros out my ROM, and then optimizes it away.
And yes, I have ways to work around this (though they force me to carry far too much of the policy from my VHDL back into my coefficient generating code). I just wanted to call out, in a public forum, that the inability to handle something as trivial as this points out how fundamentally brain-damaged this software is. I'd submit a WebCase, but the bean-counters at Xilinx have decided to no longer accept those for fear that customers may want support, or worse yet report bugs.
----
function create_index( filter : integer range 0 to 1; phase : integer range 0 to 63; tap : integer range 0 to 14 ) return natural is begin return (filter * 1024) + (tap * 64) + phase; end function create_index;
constant LONGFILTER : integer := 0; constant SHORTFILTER : integer := 1;
type t_coef is record c : signed(17 downto 0); -- S1.17 dc : signed(17 downto 0); -- S1.17 end record; type t_coef_rom is array(0 to 2047) of t_coef;
impure function GetCoefROM return t_coef_rom is -- Load up our filter coefficients from a file. The file format is -- 960 lines of (c dc) pairs, all as real numbers. -- variable rv : t_coef_rom;
procedure GetFilterData ( filename : string; filter : integer ) is file src : text open READ_MODE is filename; variable ln : line; variable c : integer range -(2**17) to (2**17)-1; variable dc : integer range -(2**17) to (2**17)-1; variable r : real; variable phase : integer range 0 to 63 := 0; variable tap : integer := 0; variable idx : integer range rv'range; variable lines : natural := 0; begin while not endfile(src) loop readline(src, ln); read(ln, r); c := INTEGER(round(r * 2.0**17)); read(ln, r); dc := INTEGER(round(r * 2.0**17)); idx := create_index(filter, phase, tap); rv(idx).c := TO_SIGNED(c, 18); rv(idx).dc := TO_SIGNED(dc, 18); if phase = 63 then phase := 0; tap := tap + 1; else phase := phase + 1; end if; lines := lines + 1; end loop; deallocate(ln); write(ln, string'("Read ")); write(ln, lines); write(ln, string'(" lines from ")); write(ln, filename); writeline(OUTPUT, ln); end procedure GetFilterData; begin for i in rv'range loop rv(i) := (others => (others => '0')); end loop; GetFilterData("longfilter.txt", LONGFILTER); GetFilterData("shortfilter.txt", SHORTFILTER); return rv; end function GetCoefROM;
-- Giant table of FIR coefficients. signal coef_rom : t_coef_rom := GetCoefROM;