通过测试平台添加常量数组元素

Add constant array element through test bench

我目前正在使用 VHDL 学习 ROM 建模。现在,我已经建模了一个 32x8 ROM,并且在我的主模块上将它实例化为一个空的 cons 数组,因为我计划通过包含每行数据的测试台代码导入一个文件。我的问题是,在导入并从文件中读取一行之后,您应该如何将此信号添加到 ROM 组件中?到目前为止,我的测试平台的当前代码如下:

library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use STD.textio.all;
use IEEE.STD_LOGIC_textio.all;

entity ROM_tb is
end;

architecture bench of ROM_tb is

  component ROM
      Port ( 
             address : in STD_LOGIC_VECTOR (4 downto 0);
             data : out STD_LOGIC_VECTOR(7 downto 0));
  end component;

  signal address: STD_LOGIC_VECTOR (4 downto 0);
  signal data: STD_LOGIC_VECTOR(7 downto 0);
  signal content : STD_LOGIC_VECTOR(7 downto 0); -- signal file content holder

   -- file objects instantiation
  file file_VECTORS : text;

begin

  uut: ROM port map ( address => address,
                      data    => data );

  stimulus: process
  --file objects declarations
  variable f_LINE      : line; -- file pointer
  variable f_CONTENT    : STD_LOGIC_VECTOR(7 downto 0); -- file content holder
  variable f_i          : INTEGER := 0; -- ROM MA location index
  
  variable i : INTEGER := 0;
  
  begin
  
    file_open(file_VECTORS, "ROM-data.txt", read_mode);
    
    while not endfile(file_VECTORS) loop
        readline(file_VECTORS, f_LINE);
        read(f_LINE, f_CONTENT);
        
        content <= f_content;

        --ROM(f_i) <= content; I was hoping to do something like this...
        
        f_i := f_i + 1;
    end loop;
  
        while i < 32 loop
           wait for 35 ns;
           address <= conv_STD_LOGIC_VECTOR(i, 5);
           i := i+1;
        end loop;
        
    wait;
  end process;

end;

我实例化了必要的文件对象并处理了一个 while 循环,它将每行读取我的 8 位数据。对于每一行,我计划将变量内容传递给一个信号,并将该信号存储到 ROM 数组,但我不确定如何。

我不知道是否还有其他方法,但我通过在我的主模块上添加一个 r/w 引脚解决了我的问题,并通过将 r/w 设置为 LOW 来从测试平台传输内容, 并在 HIGH 上进行阅读。很简单。我希望这对未来的设计师有帮助。

library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use STD.textio.all;
use IEEE.STD_LOGIC_textio.all;

entity ROM_tb is
end;

architecture bench of ROM_tb is

  component ROM
      Port ( 
             rd      : in STD_LOGIC;
             data_in   : in STD_LOGIC_VECTOR (7 downto 0);      
             address : in STD_LOGIC_VECTOR (4 downto 0);
             data_out : out STD_LOGIC_VECTOR(7 downto 0));
  end component;

  signal rd: STD_LOGIC;
  signal data_in: STD_LOGIC_VECTOR (7 downto 0);
  signal address: STD_LOGIC_VECTOR (4 downto 0);
  signal data_out: STD_LOGIC_VECTOR(7 downto 0);
  
  signal content : STD_LOGIC_VECTOR(7 downto 0);

   -- file objects instantiation
  file file_VECTORS : text;

begin

  uut: ROM port map ( 
                      rd        => rd,
                      data_in   => data_in,
                      address   => address,
                      data_out  => data_out );

  stimulus: process
  --file objects declarations
  variable f_LINE      : line;
  variable f_CONTENT    : STD_LOGIC_VECTOR(7 downto 0);
  variable f_i          : INTEGER := 0;
  
  variable i : INTEGER := 0;
  
  begin
  
    file_open(file_VECTORS, "ROM_data.txt", read_mode);
    
    while not endfile(file_VECTORS) loop
        readline(file_VECTORS, f_LINE);
        read(f_LINE, f_CONTENT);
        content <= f_CONTENT;
        
        rd <= '0';
        data_in <= content;
        address <= conv_STD_LOGIC_VECTOR(f_i, 5);
        
        f_i := f_i + 1;
        wait for 35 ns;
    end loop;
  
        while i < 32 loop
           wait for 35 ns;
           rd <= '1';
           address <= conv_STD_LOGIC_VECTOR(i, 5);
           i := i+1;
        end loop;
        
    wait;
  end process;

end;

没有 ROM 的实体和体系结构,也没有 ROM_data.txt 的内容,您的问题和答案无法得到验证。除了在未公开的 ROM 体系结构中的信号或变量值数组中包含的“ROM”之外,工具套件允许您以编程方式提供 RAM 的初始值或 ROM 的值的任何地方(例如 Xilinx,而不是 Intel),您还可以使用非纯函数在声明中提供数组类型常量的值:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;  -- to_integer instead of std_logic_arith conv_integer
use ieee.math_real.all;   -- for ceiling, log2

entity rom is  -- generic ROM with std_logic_vector address and output
    generic (  -- default values supplied for plugin to OPs usage
            filename:       string := "ROM_DATA.txt";
            rom_width:      natural := 8;
            rom_depth:      natural := 32
    );
    port ( 
        address:    in  std_logic_vector 
            (integer(ceil(log2(real(rom_depth)))) - 1 downto 0);
        data:       out std_logic_vector (rom_width - 1 downto 0)
    );
end entity;

architecture foo of rom is
    type rom_array is array
        (0 to rom_depth - 1) of std_logic_vector (rom_width - 1 downto 0);
    impure function initromfromfile (romfilename: in string) 
                return rom_array is
        use std.textio.all;
        file romfile:  text open read_mode is romfilename; 
        variable romfileline:   line;
        variable vrom:           rom_array;
        variable rom_value:     bit_vector(7 downto 0);
    begin 
        for i in vrom'range loop  -- contents of file are ordered
            if endfile(romfile) then   -- file can be shorter than rom array
                vrom(i) := (others => '0');
            else
                readline(romfile, romfileline); -- 1 datum per line
                read(romfileline, rom_value);
                vrom(i) := to_stdlogicvector(rom_value);
            end if;
        end loop;
        return vrom;
    end function;
    constant romval: rom_array := initromfromfile(filename);
begin
    data <= romval(to_integer(unsigned(address)));   -- read 
end architecture;

这里有通用 ROM 的宽度、深度和初始化文件名​​的默认值。

对于文件 ROM_DATA.txt:

11111110
11101101
11111010
11001110
11011110
10101101
10111110
11101111

数据值少于 ROM 数组大小的数据值将被零填充。

在保存ROM值(和数组类型)的对象的声明中进行初始化。

可以轻松测试功能:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity rom_tb is
end entity;

architecture foo of rom_tb is
    signal address:     std_logic_vector (4 downto 0);
    signal data:        std_logic_vector (7 downto 0);
    -- for IEEE Std 1076 revisions earlier than 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
ROM0:
    entity work.rom  -- no generic map and generic values will default
        port map (
            address => address,
            data => data
        );
ROM_DUMP:
    process
    begin
        for i in 0 to 2 ** address'length - 1 loop
            address <= std_logic_vector (to_unsigned(i, address'length));
            wait for 0 ns; -- delta cycle for address to update
            wait for 0 ns; -- delta cycle for data to update
            report "rom(" & integer'image(i) & ") = " & to_string(data);
        end loop;
        wait;
    end process;
end architecture;

当运行:

ghdl -a rom.vhdl
ghdl -e rom_tb
ghdl -r rom_tb
../../src/ieee/v93/numeric_std-body.vhdl:2098:7:@0ms:(assertion warning): NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
rom.vhdl:80:13:@0ms:(report note): rom(0) = 11111110
rom.vhdl:80:13:@0ms:(report note): rom(1) = 11101101
rom.vhdl:80:13:@0ms:(report note): rom(2) = 11111010
rom.vhdl:80:13:@0ms:(report note): rom(3) = 11001110
rom.vhdl:80:13:@0ms:(report note): rom(4) = 11011110
rom.vhdl:80:13:@0ms:(report note): rom(5) = 10101101
rom.vhdl:80:13:@0ms:(report note): rom(6) = 10111110
rom.vhdl:80:13:@0ms:(report note): rom(7) = 11101111
rom.vhdl:80:13:@0ms:(report note): rom(8) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(9) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(10) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(11) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(12) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(13) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(14) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(15) = 00000000
...
rom.vhdl:80:13:@0ms:(report note): rom(31) = 00000000

可以看到ROM在时间0(经过细化)初始化并可用。

警告来自没有默认值的地址,该默认值在初始化期间可以解释为二进制数(全部为“U”)。一旦分配了地址,警告就不再出现。

使用 IEEE 包 numeric_std 而不是 Synopsys 包 std_logic_arith 请记住,IEEE 包得到维护(并在修订版中扩展),而 Synopsys 包则没有。

bit_vector变量的使用允许使用std.standard.read而不求助于Synopsys包std_logic_textio。

IEEE Std 1076-2008 及以后的修订版提供了一个 std_logic_1164 包,它提供了一个与 std_logic_vector 子类型兼容的 READ 过程以及八进制和十六进制读取过程。修订版 -2008 及更高版本还为所有一维数组类型以及 IEEE 包 numeric_std_unsigned 取代 Synopsys 包 std_logic_unsigned.

提供了预定义的 to_string 函数

通用 ROM 实体声明允许通过提供深度和宽度值来支持其他大小的 ROM。为文件名提供的通用常量允许使用不同的文件名支持多个 ROM。

有几种不同的方法可以通过搜索为 Whosebug 上的 标签提供可用的 ROM 和 RAM 的初始值。

一般来说,只读存储器 (ROM) 不应该是可写的。