0

Ok, so I have a problem with a ROM initialization function. Before I get into the problem let me explain a bit the nature of my problem and my code.

What I want to do is generate N number of ROMs which I have to use as an input for a module that runs a matching algorithm. My problem is that I have a file with my signatures (let's say 64 in total) which I want to load in my different ROMs depending on how many I've generated (powers of 2 in my case, e.g. 8 roms of 8 signatures each).

I figured the best way to do it is load the whole text file into an array (using a function outside of the architecture body) which I will then use (again in a function) to load the data into a smaller array which will then be my ROM.

It seemed to me that the synthesizer would then just ignore the big array since I don't actually use it in my architecture.

Problem now is that since the second array input arguments are signal dependent, the synthesizer just ignores them and ties my array to zero (line 57).

Does anyone know how else if there's a way to make this architecture synthesize-able?

library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use std.textio.all;

entity signatures_rom_partial is 

generic(
        data_width : integer := 160;
        cycle_int  : integer :=32;
        rom_size   : integer := 4
        );

    port (  clk : in std_logic;
            reset : in std_logic;
            readlne: in integer range 0 to cycle_int-1;                     -- user input for array data initialization
            address: in integer range 0 to rom_size-1;                      -- address for data read
            data: out std_logic_vector(data_width-1 downto 0)               -- data output
         );
end signatures_rom_partial;

architecture rom_arch of signatures_rom_partial is

type rom_type is array (0 to cycle_int-1) of bit_vector (data_width-1 downto 0);            -- big array for all signatures, not used in arch
type test_type is array (0 to rom_size-1) of std_logic_vector (data_width-1 downto 0);      -- smaller ROMs used in arch

--Read from file function--
----------------------------------------------------------------------------------------------------------  
impure function InitRomFromFile (RomFileName : in string) return rom_type is                            --
    file RomFile : text is in RomFileName;                                                              --
    variable RomFileLine : line;                                                                        --
    variable rom : rom_type;                                                                            --
                                                                                                        --
begin                                                                                                   --
    for i in rom_type'range loop                                                                        --
        readline (RomFile, RomFileLine);                                                                --
        read (RomFileLine, rom(i));                                                                     --
    end loop;                                                                                           --
    return rom;                                                                                         --
end function;                                                                                           --
----------------------------------------------------------------------------------------------------------

--Function for smaller ROM initialization--
----------------------------------------------------------------------------------------------------------
impure function initPartRom (rom : rom_type; readlne : integer) return test_type is                     --
    variable test_array : test_type;                                                                    --
                                                                                                        --
begin                                                                                                   --
    for j in test_type'range loop                                                                       --
        test_array(j) := to_stdlogicvector(rom(j+readlne));                                             --
    end loop;                                                                                           --
    return test_array;                                                                                  --
end function;                                                                                           --
----------------------------------------------------------------------------------------------------------

constant rom        : rom_type  := InitRomFromFile("signatures_input.txt");
signal test_array   : test_type := initPartRom(rom , readlne);                      --(LINE 57) SYNTHESIZER IGNORES THESE INPUT ARGUMENTS

begin

    process(clk,reset)
    begin
        if reset='1' then
            data<=(others=>'0');
        elsif (clk'event and clk='1') then
            data <= (test_array(address));
        end if;
    end process;

end rom_arch;

Synthesis is done using Xilinx ISE, simulation is done with Modelsim in which, my creation works fine :)

Thanks for any help!

Nailtha
  • 5
  • 1
  • 3
  • I would convert your "signatures" into constant strings in a VHDL package ... or write a script to process the text file into the right format, if they are generated elsewhere. –  Nov 20 '15 at 20:14
  • XST supports initializing RAM from VHDL file read and ROM (as a signal) is RAM that's not written. However that wouldn't get you a smaller read only memory as the initial array value extracted from another signal. Extracting the smaller 'ROM' values from the bigger ROM array requires index arithmetic (readlne + address) if both readlne and address are signals. That index arithmetic could impact the clock period. And that makes us think of a two dimensional index. –  Nov 20 '15 at 22:15

1 Answers1

2

With Xilinx ISE (14.7) it is possible to synthesize ROMs and RAMs even if the initial data is read from an external file by function.

The only requirement is, that the reading function must be computable at synthesis time. This is not true for your code because readlne is not static at the point the function is called. You should change it to a generic instead of an input and assign a different value to this generic for every other ROM instance. Then it should work as intended.

A sample implementation of how to read initialization data from a text file in (Xilinx) .mem format can be found in VHDL Library PoC in the namespace PoC.mem.ocrom or PoC.mem.ocram

Martin Zabel
  • 3,589
  • 3
  • 19
  • 34
  • Thanks for the clarification about ISE, wasn't too sure how the initialization works. The thing is now that assigning a different value to a generic might be a solution but my problem is that I do generate the ROMs in a higher level module depending on the parallelism I choose (generic value). Thus I am thinking that the "line value" has to be an input of some kind. Is there another way to bypass that? – Nailtha Nov 21 '15 at 16:04
  • @Nailtha If `readlne` needs to be a signal, then you have to include it in the read-out statement and always read from the whole ROM like this `data <= (rom(address+readlne));` Of course, this would require a lot of BlockRAM. In this case, use the dual-port feature to save half of them. – Martin Zabel Nov 21 '15 at 16:22