我在我的 VHDL 测试平台(简写如下所示)中使用聚合时遇到了一些问题。
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all
entity TB is
end entity;
architecture RTL of TB is
-- constant(s)
constant CLK_PERIOD : time := 10 ns; -- 100 MHz
-- signal(s)
signal CLK : std_logic := '0';
signal nRST : std_logic := '1';
signal CONFIG_REG : std_logic_vector(7 downto 0) := (others => '0');
begin
-- clock driver
CLK <= NOT CLK after (CLK_PERIOD / 2.0);
-- main process
process
begin
-- reset driver...
nRST <=
'1',
'0' after (CLK_PERIOD * 1);
-- set initial configuration...
CONFIG_REG <= (
6 => '1',
3 downto 2 => "01",
7 | 0 => '1',
others => '0'
);
-- do test-bench stuff...
-- update configuration...
CONFIG_REG <= (
6 => '0',
3 downto 2 => "10",
7 | 0 => '1',
others => '0'
);
-- do more test-bench stuff...
end process;
end architecture;
我真的很想给配置寄存器的各个部分“命名”,这样它实际上读起来很好。
所以我想说:
Bit[6] = ENABLE
Bit[3:2] = MODE
Bit[7|0] = READY_DONE
我知道我可以为 6 使用常量:
constant ENABLE : integer := 6;
然后我的代码如下所示:
CONFIG_REG <= (
ENABLE => '1',
3 downto 2 => "01",
7 | 0 => '1',
others => '0'
);
但我一直难以尝试将范围 3 缩小到 2
和 7|0
命名,以便代码如下所示:
CONFIG_REG <= (
ENABLE => '1',
MODE => "01",
READY_DONE => '1',
others => '0'
);
我认为我可以使用别名来完成此操作,并且我一直在查看 VHDL Golden Reference Guide (p.15)就理解别名和范围而言,这非常有帮助,但我仍然无法弄清楚如何命名范围本身或值的“或”(|)。
目前我有下面的“hack”,我不太喜欢...
constant ENABLE : integer := 6;
alias MODE is CONFIG_REG(3 downto 2);
-- what to do about the OR though???
CONFIG_REG <= (
ENABLE => '1',
MODE'RANGE => "01",
7 | 0 => '1',
others => '0'
);
我真的想让我的测试台可读,这样当我看它时 6 个月。从现在开始,我将知道它在做什么,而不必去弄清楚“现在位 [6] 又是什么???”或者在我必须将代码交给其他开发人员的情况下,他们可以很容易地了解我试图完成的工作。
如有任何帮助/建议,我们将不胜感激。
感谢阅读。
编辑:修复了 7 | 0
有效:
无效:
7 | 0 => "10",
有效:
7 | 0 => '1',
最佳答案
当心,您的代码无效:聚合符号 7 | 0
代表索引组,而不是向量。它应该是关联的 std_logic
值,而不是 std_logic_vector
。此外,在 2008 年之前的 VHDL 版本中,聚合符号 3 downto 2
也应该关联 std_logic
值:
-- set initial configuration...
CONFIG_REG <= (
6 => '1',
3 downto 2 => '1',
7 | 0 => '0',
others => '0'
);
在 VHDL 2008 中,现在支持离散范围的选择与聚合类型的表达式之间的关联。所以,3 downto 2 => "01"
在 VHDL 2008 中是可以的。但是由于 VHDL 2008 仍然没有被许多合成器完全支持,你应该小心,除非这段代码不应该当然是合成。
无论如何,使用记录而不是向量可能是解决您的问题的一种选择。如果您还需要数据的矢量版本,您可以非常轻松地编写矢量和记录类型之间的转换函数。示例:
package foo is
type config_type is record
ready: std_ulogic;
enable: std_ulogic;
foobar: std_ulogic_vector(1 downto 0);
mode: std_ulogic_vector(1 downto 0);
reserved: std_ulogic;
done: std_ulogic;
end record;
function rec2vec(v: config_type) return std_ulogic_vector;
function vec2rec(v: std_ulogic_vector) return config_type;
end package foo;
package body foo is
function rec2vec(v: config_type) return std_ulogic_vector is
begin
return v.ready & v.enable & v.foobar & v.mode & v.reserved & v.done;
end function rec2vec;
function vec2rec(v: std_ulogic_vector) return config_type is
constant vv: std_ulogic_vector(7 downto 0) := v;
begin
return (ready => vv(7), enable => vv(6), foobar => vv(5 downto 4),
mode => vv(3 downto 2), reserved => vv(1), done => vv(0));
end function vec2rec;
end package body foo;
然后您可以使用聚合符号来分配记录:
signal config_reg: config_type;
...
config_reg <= (
ready => '1',
enable => '1',
foobar => "--",
mode => "01",
others => '0'
);
并转换为自向量:
signal config_reg_v: std_ulogic_vector(7 downto 0);
...
config_reg_v <= rec2vec(config_reg);
...
config_reg <= vec2rec(config_reg_v);
...
config_reg <= vec2rec(X"ff");
注意:我使用了 std_ulogic
和 std_ulogic_vector
而不是解析后的 std_logic
和 std_logic_vector
。这有充分的理由,但这是另一个问题。
关于使用别名的 VHDL 聚合分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45470325/