2

My requirement is to read data bits from input file and write data into memory array(output) in vhdl. As i am not aware of the amount of data in input file, i need to declare array of unknown size and assign data to memory at later stages.

My code is as below:

Declarations :

PACKAGE io IS
   type memory is array (natural range<>) of std_logic_vector(3 downto 0); 
END;

entity File_io is
 port (
     clk:             in  std_logic;
     Data_memory:     out   memory
 );
end entity;

architecture behav of File_io is
 signal mem: memory;
begin
 process(clk)
   begin
     for i in 0 to 15 loop  -- Took just 16 values for explaination purpose.
                             -- i may need more values to be written which is unknown.
      mem(i) <= std_logic_vector(to_unsigned(i, 4));
     end loop;
    Data_memory <= mem;
  end process;
end architecture behav;

I have minimized the actual code to exact requiremnet of mine. Ignore if any syntax errors.

The problem is I can not assign values to array which is unconstrained, that is of undefined size. How do i do this ? any suggestions or alternatives? Guide me

5
  • Just wondering: have you tried some search engines? I am not a VHDL guru; but there seem to be various discussions about that topic ... Commented Mar 3, 2017 at 15:47
  • 1
    I have gone through discussion in various links, but all i got is , I should declare the size with some value(may be maximum possible value). Commented Mar 3, 2017 at 15:52
  • What I am wondering: isn't VHDL in the end about building "hardware"? So what does a "unknown sized" array do in real hardware? Commented Mar 3, 2017 at 15:53
  • 1
    @ghostCat, I need it for just simulation purpose. Commented Mar 3, 2017 at 15:54
  • @GhostCat In a real project, not only is the design coded in VHDL (or some other HDL), the test environment is also coded in VHDL (or some other HDL). The test environment is very much software: it only ever executes on a computer. Test environments written in System-Verilog can be quite sophisticated involving OO design and all that entails (inheritance, polymorphism, design patterns and so on). Commented Mar 3, 2017 at 16:08

2 Answers 2

4

Looking at your other question - How to Eliminate whitespaces while Reading a file in VHDL provides an example memory init file as well as a problem reading it.

Incorporating that fix and using the method method J.H. Bonarius suggests gives rise to a Minimal, Complete and Verifiable example:

library ieee;
use ieee.std_logic_1164.all;

PACKAGE io IS
   type memory is array (natural range<>) of std_logic_vector(3 downto 0); 
   function iswhitespace (inpstr: in string) return boolean;
END;

package body io is
    function iswhitespace (inpstr:  in  string) return boolean is
        constant NBSP: character  := character'val(128); 
    begin
        for i in inpstr'range loop
            if inpstr(i) /= ' ' and inpstr(i) /= NBSP and inpstr(i) /= HT then
                exit;
            elsif i = inpstr'RIGHT then
                return TRUE;
            end if;
        end loop;
        return FALSE;
    end function;
end package body;

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

entity File_io is
    generic (
        constant MEMORY_SIZE: natural := 42;
        constant filename:  string := "C:\Users\ChowdaryS\Downloads\topo.bin"
    );
     port (
         clk:             in  std_logic;
         Data_memory:     out   memory (0 to MEMORY_SIZE - 1) 
     );
end entity;

architecture foo of File_io is
    signal mem: memory (0 to MEMORY_SIZE - 1); -- ADDED subtype indication
    use ieee.numeric_std.all;                  -- MISSING cntext item
    use std.textio.all;
    signal mem_inited:     boolean := FALSE;   -- ADDED
begin
    process(clk)
        file f:       text open read_mode is filename;
        variable L:   line;
        variable i:   integer:= 0;
        variable b:   bit_vector(3 downto 0);  
    begin
        if not mem_inited then
            i := 0;
            while not endfile(f) loop
                readline(f, L);
                while L.all'length >= b'length and not iswhitespace(L.all) loop
                    read(L, b);
                    mem(i) <= to_stdlogicvector(b);
                    i := i + 1;
                end loop;
            end loop;
            report "mem values loaded = " &  integer'image(i);
            mem_inited <= TRUE;
        end if;
    end process;
    Data_memory <= mem;
end architecture foo;

There are a changes. A function iswhitespace has been added to package io. You can see the above cited question for trade-offs and whether it's required.

The assignment to the output port has been moved outside the process. It's assumed you'll have some sort of writes to mem included in the process.

There's also a testbench that instantiates file_io and determines the size of the memory array, passing that as a generic.

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

entity file_io_tb is
end entity;

architecture foo of file_io_tb is

    constant MEMSIZ:    natural := 16;
    constant filename:  string := "topo.bin";  -- found locally.
    signal clk:         std_logic := '0';
    signal Data_memory: memory (0 to MEMSIZ - 1);
    use std.textio.all;

    impure function getarraysize return natural is
        variable L:     Line;
        variable i:     natural;
        variable b:     bit_vector (3 downto 0);
        file f:         text  open read_mode is filename;
    begin
        i := 0;
        while not endfile(f) loop
            readline(f, L);
            while L.all'length >= b'length and not iswhitespace(L.all) loop
                read(L, b);
                i := i + 1;
            end loop;
        end loop;
        report " memory size = " & integer'image(i);
        return i;
    end function;
begin
DUT:
    entity work.file_io
        generic map (MEMORY_SIZE => getarraysize, filename => filename)
        port map (
            clk => clk,
            Data_memory => Data_memory
        );

CLOCK:
    process
    begin
        wait for 10 ns;
        clk <= not clk;
        if now > 50 ns then
            wait;
        end if;
    end process;

end architecture;

The function is performs the file read at elaboration time to set a generic.

And we see this initializes mem:

file_io_tb.png

The copy of topo.bin used has four trailing spaces on the first line:

10101100 11010100 10101100 11010100   

11111110 10111001 11111110 10111001

The values shown in the waveform match the above two lines from topo.bin.

(And all this got written to find the issue with whitespace in the other question).

Sign up to request clarification or add additional context in comments.

Comments

2

Read the file twice and determine the amount of lines the first time. For example

edit: finally had access to a vhdl simulator. Fixed the code. I've been switching between VHDL, C++, C#, matlab and python so much lately, that I keep mixing syntaxes.

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

entity file_io is
    generic (
        data_width : positive := 4;
        file_name  : string
    );
    port (
        clk         :  in std_logic;
        file_output : out std_logic_vector(data_width-1 downto 0) := (others => '0')
    );
end entity file_io;

architecture behaviour of file_io is
    impure function get_line_count return positive is
        file file_pointer : text;
        variable line_data : line;
        variable lineCount : natural := 0;
    begin
        file_open(file_pointer, file_name, read_mode);
        while not endfile(file_pointer) loop
            readline(file_pointer, line_data);
            lineCount := lineCount + 1;
        end loop;
        file_close(file_pointer);
        return lineCount;
    end function get_line_count;

    constant memory_size : positive := get_line_count;

    subtype data_type is std_logic_vector(data_width-1 downto 0);
    type memory_type is array (0 to memory_size-1) of data_type;

    impure function get_data return memory_type is
        file file_pointer : text;
        variable line_data : line;
        variable line_value : bit_vector(data_width-1 downto 0);
        variable memory : memory_type;
        variable index : natural := 0;
    begin
        file_open(file_pointer, file_name, read_mode);
        while not endfile(file_pointer) loop
            readline(file_pointer, line_data);
            read(line_data, line_value);
            memory(index) := to_stdlogicvector(line_value);
            index := index + 1;
        end loop;
        file_close(file_pointer);
        return memory;
    end function get_data;

    constant memory : memory_type := get_data;
    signal index : natural := 0;
begin
    process(clk)
    begin
        if rising_edge(clk) then
            file_output <= memory(index);
            if (index < memory_size-1) then
                index <= index + 1;
            else
                index <= 0;
            end if;
        end if;
    end process;
end architecture behaviour;

and test bench:

library IEEE;
use IEEE.std_logic_1164.all;

entity file_io_tb is
end entity file_io_tb;

architecture behaviour of file_io_tb is
    signal clk : std_logic := '0';
    constant data_width : positive := 4;
    signal data : std_logic_vector(data_width-1 downto 0);
begin
    file_io_inst : entity work.file_io
        generic map(
            data_width => 4,
            file_name => "data_file.txt"
            )
        port map(
            clk => clk,
            file_output => data
            );

    clk_prc : process
    begin
        loop
            clk <= '0', '1' after 1 ns;
            wait for 2 ns;
        end loop;
    end process;
end architecture behaviour;

data_file.txt just contains

0101
1010
1100
0011
...

this works fine for me...

1 Comment

A parameter interface list in mast have at least one interface_element. IEEE Std 1076-2009 6.5.6.1, interface_list ::= interface_element { interface_element }. The formal parameter list is optional in a subprogram declaration. 4.2.1 function_specification ::= [ pure | impure ] function designator subprogram_header [ [ parameter ] ( formal_parameter_list ) ] return type_mark . 1.2.1 Square brackets [ ] enclose optional items on the right-hand side of a production.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.