假设我已经定义了一个记录,其中的字段为std_ulogic_vector
,以代表更大的std_ulogic_vector
。使用串联将记录转换为大向量很简单(无需了解每个字段的大小)。
我该如何反向操作,例如将大的std_ulogic_vector
转换回记录吗?
示例:
architecture RTL of record_conversion is
type data_t is record
top : std_ulogic_vector(4 downto 0);
bottom : std_ulogic_vector(2 downto 0);
end record data_t;
signal record_s : data_t;
signal vector_s : std_ulogic_vector(7 downto 0);
begin
-- vector to record works
--vector_s <= record_s.top & record_s.bottom;
-- record to vector does not work
(record_s.top, record_s.bottom) <= vector_s;
-- tedious solution with knowledge of the field size
record_s.top <= vector_s(7 downto 3);
record_s.bottom <= vector_s(2 downto 0);
end architecture;
答案 0 :(得分:4)
通常最好将此类转换包装在函数中,并使用subtype
作为结果向量,例如:
...
constant LEN : integer := 8; -- Number of bits in data_t
type data_t is record
top : std_ulogic_vector(4 downto 0);
bottom : std_ulogic_vector(2 downto 0);
end record data_t;
subtype vector_t is std_ulogic_vector(LEN - 1 downto 0);
function data_to_vector(data : data_t) return std_ulogic_vector is
variable res_v : vector_t;
begin
res_v := data.top & data.bottom;
return res_v;
end function;
function vector_to_data(vector : vector_t) return data_t is
variable res_v : data_t;
begin
res_v.top := vector(LEN - 1 downto LEN - res_v.top'length);
res_v.bottom := vector(res_v.bottom'length - 1 downto 0);
return res_v;
end function;
signal record_s : data_t;
signal vector_s : vector_t;
begin
record_s <= vector_to_data(vector_s);
vector_s <= data_to_vector(record_s);
...
也许应该添加另一个常量来定义top
和bottom
之间的分隔。
答案 1 :(得分:2)
除了使用子程序调用将一种类型的元素分配给另一种类型的元素之外,还有其他几种方法。
您可以使用限定表达式:
record_s <= data_t'(vector_s(7 downto 3), vector_s (2 downto 0));
其中的聚合包括两个vector_s切片,这些切片的显式类型与记录匹配。参见IEEE Std 1076-2008 9.3.6限定表达式。
在仿真过程中,将验证信号的新值。参见14.7.3.4信号更新:
b)如果S是复合信号(包括数组的一个切片),则S的有效值会隐式转换为S的子类型。子类型转换会检查S的每个元素是否存在匹配元素。有效值,反之亦然。如果此检查失败,则会发生错误。然后,将这种子类型转换的结果分配给代表S当前值的变量。
除了具有匹配元素(subelement,...)子类型转换之外,还可以更改索引范围以匹配目标。
您可以使用子类型索引范围指定切片索引范围:
library ieee;
use ieee.std_logic_1164.all;
entity record_conversion is
end entity;
architecture subtypes of record_conversion is
type data_t is record
top : std_ulogic_vector(4 downto 0);
bottom : std_ulogic_vector(2 downto 0);
end record data_t;
signal record_s : data_t;
signal vector_s : std_ulogic_vector(7 downto 0);
subtype t is std_logic_vector (
vector_s'LEFT downto vector_s'LEFT - record_s.top'length + 1
);
subtype b is std_logic_vector (
vector_s'LEFT - record_s.top'length downto 0
);
begin
record_s <= data_t'(vector_s(t'range), vector_s(b'range));
end architecture;
这是右侧表达式元素的子类型索引范围切片。
您可以使用别名来描述切片:
architecture aliases of record_conversion is
type data_t is record
top: std_ulogic_vector(4 downto 0);
bottom: std_ulogic_vector(2 downto 0);
end record data_t;
signal record_s: data_t;
signal vector_s: std_ulogic_vector(7 downto 0);
alias vector_s_top: std_ulogic_vector(record_s.top'range) is
vector_s(7 downto 3);
alias vector_s_bottom: std_ulogic_vector(record_s.bottom'range) is
vector_s (2 downto 0);
begin
record_s <= data_t'(vector_s_top, vector_s_bottom);
end architecture;
在这里,两个别名描述了vector_s的字段。如果保证始终分配记录复合对象,则实际上可以删除记录而仅使用别名。最接近的VHDL是工会。
以上示例无误地进行了分析,阐述和模拟,表明不存在切片边界问题。
合格的表达式,子类型声明和别名在调用子程序时不会产生额外的仿真开销。