使用别名的VHDL聚合分配
我在使用我的VHDL测试工作台中的聚合物时遇到了一些麻烦(如下图所示)。使用别名的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 downto 2
和7|0
的范围,以便代码如下所示:
CONFIG_REG <= (
ENABLE => '1',
MODE => "01",
READY_DONE => '1',
others => '0'
);
我想我可能能够做到这一点使用别名,我一直在寻找的VHDL Golden Reference Guide (p.15)这一直是非常有益的,据了解别名和范围去,但我仍然无法弄清楚如何命名范围本身或值或'或'(|)。
目前,我有下面的“黑客”,我真的不喜欢...
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',
我喜欢在我的包中定义全宽常量:
subtype ConfigRegType is std_logic_vector(7 downto 0) ;
constant CFG_ENABLE : ConfigRegType := B"0_1_000000" ;
constant CFG_MODE0 : ConfigRegType := B"0000_00_00" ;
constant CFG_MODE1 : ConfigRegType := B"0000_00_00" ;
constant CFG_MODE2 : ConfigRegType := B"0000_10_00" ;
constant CFG_MODE3 : ConfigRegType := B"0000_11_00" ;
constant CFG_READY : ConfigRegType := B"1_0000000" ;
constant CFG_DONE : ConfigRegType := B"0000000_1" ;
. . .
现在,当您准备好写,只是“或”值设置你想要的:
CONFIG_REG <= CFG_ENABLE or CFG_MODE1 or CFG_READY or CFG_DONE ;
我也玩过其他的方式,但是,像你注意到他们似乎需要的知识实施细节。
感谢您的建议。你是否发现当你不得不改变道路时这种方法是灵活的? – bgarisn
当事情发生变化时,只需更新软件包中的子类型和常量即可。 –
Imho不是那么简单。试想一下,编辑50行以上的代码决定将另一位添加到配置寄存器中。关于软件设计,这个代码的维护成本相当高。 – JHBonarius
请注意,您的代码无效:汇总记号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'
);
在2008 VHDL是离散范围和聚集体的类型的表达的选择之间的关联现在支持。因此,VHDL 2008中的3 downto 2 => "01"
是OK的。但是由于许多合成器尚未完全支持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
。这有很好的理由,但这是另一个问题。
感谢您的详细回复。我搞砸了'7 | 0'这是真的。我认为可以说'3 downto 2 =>“01”虽然不是吗?我没有使用记录,因为这似乎是一个复杂的方式来在我的注册表中找到一个名字,但我相对VHDL来说是新手/中级,因此我不确定其他开发人员如何执行此操作。 – bgarisn
对不起,但是'3 downto 2 =>“01”'在这种情况下,**不是**有效。任何VHDL编译器/模拟器都会引发错误。记录并不复杂,它们只是大多数体面编程语言的一个非常有用的功能。帮你一个忙:在他们有意义的地方使用它们。主要归功于他们将避免的愚蠢错误的数量,这将大大提高您的生产力。 –
不要后悔。我只是想了解为什么它是无效的,因为Modelsim 10.5c(我用来运行我的测试平台的模拟器)似乎认为它很好 - 也就是说,在模拟中将值更改为“01”如预期。我感谢你指点我的记录。我会确保检查出来并学习如何以更高效的方式使用它们。 – bgarisn
除@ user1155120的答案外,还可以使用索引类型为枚举类型的数组。 – Paebbels
你有没有理由不使用记录类型?他们命名了字段。如果您还需要矢量化版本的数据,则可以非常轻松地在矢量和记录类型之间编写转换函数。 –
@RenaudPacalet我没有使用记录,因为它对我来说没有任何意义,只要寄存器是什么(即一个位的集合)。你通常使用记录来表示设计中的寄存器而不是'std_logic_vector'? – bgarisn