在我的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黄金参考指南(临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'
);我真的想使我的测试平台可读性,以便当我看到它6mo。从现在起,我将知道它在做什么,而不必去弄明白“现在bit6是什么?”或者,如果我必须将我的代码交给另一个开发人员,他们可以很容易地了解我想要完成的任务。
如能就如何做到这一点提供任何帮助/建议,将不胜感激。
感谢您的阅读。
编辑:将7 | 0修正为有效:
无效:
7 | 0 => "10",有效:
7 | 0 => '1',发布于 2017-08-03 09:01:20
注意,您的代码是无效的:聚合表示法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。这是有充分理由的,但这是另一个问题。
发布于 2017-08-02 23:39:27
我更喜欢在包中定义全宽度常量:
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 ; 不过,我使用了其他方法,就像您注意到的那样,它们似乎需要了解实现的细节。
https://stackoverflow.com/questions/45470325
复制相似问题