通过测试平台添加常量数组元素
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 上的 vhdl 标签提供可用的 ROM 和 RAM 的初始值。
一般来说,只读存储器 (ROM) 不应该是可写的。
我目前正在使用 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 上的 vhdl 标签提供可用的 ROM 和 RAM 的初始值。
一般来说,只读存储器 (ROM) 不应该是可写的。