03-25-2020 03:43 AM
Hi, I am having trouble initialising the contents of RAM from a file. I am targeting a XC7A35TICSG324-1L FPGA (on the Digilent Arty A7 board). I am not an FPGA expert, so the issue could be something silly I am doing or my own misunderstanding. I would greatly appreciate any help to get this working!
I have a text file that stores the data. Each bit is separated by a space, and each new vector is on a new line. For example, the text file sort of looks like this:
1 1 1 1 1 0 0 1 1 0 0 1
which would correspond to "1111", "1001" then "1001" initialised in RAM.
The VHDL that I have written is based off the example given in the Synthesis user guide (UG901) in Chapter 4 HDL Coding Techniques : Initializing RAM Contents. I have reproduced my VHDL below:
type rom_t is array (0 to DEPTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); impure function mem_init(file_name : string) return rom_t is file fp : text open read_mode is file_name; variable image_data : rom_t; variable i_line : line; variable tmp_bit : bit; begin --iterate though rows in file for i in 0 to DEPTH-1 loop readline(fp, i_line); --iterate though individual bits in the row for j in 0 to DATA_WIDTH-1 loop read(i_line, tmp_bit); image_data(i)(j) := to_stdulogic(tmp_bit); end loop; end loop; return image_data; end mem_init; signal rom : rom_t := mem_init("data.txt"); -- I use the absolute file path, just removed it here in the example
The problem is that the memory is not being initialised after running synthesis in Vivado. The tool is (I think) initialising it as all zeros (I get the message "propagating zeros across element") and as such is trimming away the whole module. When I look at the schematic after synthesis/implementation the outputs are all simply tied together and to ground.
When I simulate the design in ModelSim and in Vivado's XSIM, I can see the RAM is being initialised correctly as I expect.
To make sure it is not caused by something else written within or outside the RAM module, I have tried initialising the ram with random constants, for example, replacing the initial signal assignment like shown below:
signal rom : rom_t := (0=> (others=> '1'), 1=> (others=> '0'), 2=>(others=> '0'), others=> (others=> '1') );
This works as expected. The RAM is correctly initialised in synthesis and when I load the design onto the board it works as how I would expect.
I am unsure of what I can do to get it working correctly. If it makes any difference, I am using Vivado 2018.3 on a Windows 10 computer.
Thanks for your help.
03-25-2020 06:06 AM - edited 03-25-2020 06:08 AM
I copied and modified the Initializing Block RAM From an External Data File (VHDL) example found in the Vivado Design Suite Synthesis User Guide (UG901; v2019.2; pp 157-158). I modified to make a ROM. You could modify to automatically calculate the address width but I just filled in manually for testing. I created a 8-bit x 1024-depth.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.textio.all; entity rams_init_file is generic ( DEPTH : integer := 1024; DATA_WIDTH : integer := 8); port ( clk : in std_logic; en : in std_logic; addr : in std_logic_vector(8 downto 0); dout : out std_logic_vector(DATA_WIDTH-1 downto 0)); end rams_init_file; architecture syn of rams_init_file is type RamType is array (0 to DEPTH-1) of bit_vector(DATA_WIDTH-1 downto 0); impure function InitRamFromFile(RamFileName : in string) return RamType is FILE RamFile : text is in RamFileName; variable RamFileLine : line; variable RAM : RamType; begin for I in RamType'range loop readline(RamFile, RamFileLine); read(RamFileLine, RAM(I)); end loop; return RAM; end function; signal RAM : RamType := InitRamFromFile("C:/X/Forums/2020_03_25/data.txt"); begin process(clk) begin if rising_edge(clk) then if (en='1') then dout <= to_stdlogicvector(RAM(to_integer(unsigned(addr)))); end if; end if; end process; end syn;
I have attached the data.txt file used to initialize the ROM.
You can see the properties of the BRAM in the Synthesized Design Checkpoint.
03-25-2020 05:00 PM
Thank you. I know that it works when reading in the whole vector from the line at once. I had since modified the data file so that the bits were not separated by a space and read in the data as in your example.
My original data file had each bit separated by a space so I was trying to read in each bit at a time, which I couldn't get working correctly. I'm still curious as to why that was not working.