论文:
Xilinx XST连接后可以反转向量的方向。
我有一个SATAController和一个PicoBlaze软核CPU。该CPU使用寄存器接口+交叉时钟来读/写测试数据。 CPU写入6个8位寄存器,为读取请求存储24位偏移量和24位长度字段。这些地址和长度字段扩展为48位(关键字:LBA-48寻址模式)。
它看起来如何?
-- register values after cross clocking with double FFs
signal sync_Offset : T_SLV_24; -- std_logic_vector(23 downto 0)
signal sync_Length : T_SLV_24;
-- output signals for LBA-48 addressing
signal Address_LB : T_SLV_48; -- std_logic_vector(47 downto 0)
signal BlockCount_LB : T_SLV_48;
-- [...]
begin
-- [...]
-- SLL 7 -> granularity for logical blocks is 1 MiB
Address_LB <= resize(sync_Offset & "0000000", Address_LB'length);
BlockCount_LB <= resize(sync_Length & "0000000", BlockCount_LB'length);
通常人们会猜测调整大小会导致结果
Address_LB == "0000_0000_0000_0000_0" & sync_Offset & "000_0000"
BlockCount_LB == "0000_0000_0000_0000_0" & sync_Length & "000_0000"
但是,事实并非如此。经过三个小时的调试后,我发现合成结果如下:
Address_LB = "0000_000" & sync_Offset & "0_0000_0000_0000_0000"
BlockCount_LB = "0000_000" & sync_Length & "0_0000_0000_0000_0000"
那会发生什么?
信号sync_*
是降序矢量。在与运算符&
连接后,向量处于上升方向,这会导致调整大小以在向量的另一边界对齐sync_ *。
所以我在网上搜索了这个现象,但我找不到任何东西。我还搜索了std_logic_1164,但是并没有为std_logic(_vector)显式定义连接运算符。
以下是我的问题:
&
定义在哪里?解决方案:
descend(..)
。上面的固定示例:
Address_LB <= resize(descend(sync_Offset & "0000000"), Address_LB'length);
BlockCount_LB <= resize(descend(sync_Length & "0000000"), BlockCount_LB'length);
subtype T_SLV_24 is STD_LOGIC_VECTOR(23 downto 0);
subtype T_SLV_48 is STD_LOGIC_VECTOR(47 downto 0);
调整大小功能:
-- Resizes the vector to the specified length. The adjustment is make on
-- on the 'high end of the vector. The 'low index remains as in the argument.
-- If the result vector is larger, the extension uses the provided fill value
-- (default: '0').
-- Use the resize functions of the numeric_std package for value-preserving
-- resizes of the signed and unsigned data types.
function resize(vec : std_logic_vector; length : natural; fill : std_logic := '0') return std_logic_vector is
constant high2b : natural := vec'low+length-1;
constant highcp : natural := imin(vec'high, high2b);
variable res_up : std_logic_vector(vec'low to high2b);
variable res_dn : std_logic_vector(high2b downto vec'low);
begin
if vec'ascending then
res_up := (others => fill);
res_up(vec'low to highcp) := vec(vec'low to highcp);
return res_up;
else
res_dn := (others => fill);
res_dn(highcp downto vec'low) := vec(highcp downto vec'low);
return res_dn;
end if;
end function;
function imin(arg1 : integer; arg2 : integer) return integer is
begin
if arg1 < arg2 then return arg1; end if;
return arg2;
end function;
function descend(vec : std_logic_vector) return std_logic_vector is
variable res : std_logic_vector(vec'high downto vec'low);
begin
res := vec;
return res;
end function;
涉及的包裹:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library PoC;
use PoC.utils.all; -- here are resize, imin and descend declared
T_SLV_<n>
代表&#34;类型; std_logic_vector; n位 - &gt; (n-1 downto 0)&#34;
答案 0 :(得分:2)
以此作为MCVe:
library ieee;
use ieee.std_logic_1164.all;
entity sync is
end entity;
architecture mcve of sync is
subtype T_SLV_24 is std_logic_vector(23 downto 0);
subtype T_SLV_48 is std_logic_vector(47 downto 0);
-- register values after cross clocking with double FFs
signal sync_Offset : T_SLV_24 := x"deadbe";
signal sync_Length : T_SLV_24 := x"feedfa";
-- output signals for LBA-48 addressing
signal Address_LB : T_SLV_48; -- std_logic_vector(47 downto 0)
signal BlockCount_LB : T_SLV_48;
function MINIMUM (l,r: integer) return integer is
begin
if l > r then
return r;
else
return l;
end if;
end function;
-- [...]
-- Resizes the vector to the specified length. The adjustment is make on
-- on the 'high end of the vector. The 'low index remains as in the argument.
-- If the result vector is larger, the extension uses the provided fill value
-- (default: '0').
-- Use the resize functions of the numeric_std package for value-preserving
-- resizes of the signed and unsigned data types.
function resize(vec : std_logic_vector; length : natural; fill : std_logic := '0') return std_logic_vector is
constant high2b : natural := vec'low+length-1;
constant highcp : natural := MINIMUM(vec'high, high2b); -- imin
variable res_up : std_logic_vector(vec'low to high2b);
variable res_dn : std_logic_vector(high2b downto vec'low);
begin
if vec'ascending then
res_up := (others => fill);
res_up(vec'low to highcp) := vec(vec'low to highcp);
return res_up;
else
res_dn := (others => fill);
res_dn(highcp downto vec'low) := vec(highcp downto vec'low);
return res_dn;
end if;
end function;
function descend(vec : std_logic_vector) return std_logic_vector is
variable res : std_logic_vector(vec'high downto vec'low);
begin
res := vec;
return res;
end function;
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;
begin
-- [...]
-- SLL 7 -> granularity for logical blocks is 1 MiB
-- Address_LB <= resize(sync_Offset & "0000000", Address_LB'length);
-- BlockCount_LB <= resize(sync_Length & "0000000", BlockCount_LB'length);
Address_LB <= resize(descend(sync_Offset & "0000000"), Address_LB'length);
BlockCount_LB <= resize(descend(sync_Length & "0000000"), BlockCount_LB'length);
Process (Address_LB, BlockCount_LB)
begin
report "Address_LB = " & to_string(Address_LB) Severity NOTE;
report "BlockCount_LB = " & to_string(BlockCount_LB) Severity NOTE;
end process;
end architecture;
有两个初始值:
signal sync_Offset : T_SLV_24 := x"deadbe";
signal sync_Length : T_SLV_24 := x"feedfa";
注意本地函数MINIMUM而不是imin(未提供)和to_string的本地副本(此ghdl符合-1993)。另请注意带有本地MINIMUM的最小上下文子句
这给了:
ghdl -a sync.vhdl
ghdl -e sync
ghdl -r sync
sync.vhdl:75:9:@ 0ms :(报告说明):Address_LB = uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu sync.vhdl:76:9:@ 0ms :(报告说明):BlockCount_LB = uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu sync.vhdl:75:9:@ 0ms :(报告单):Address_LB = 000000000000000001101111010101101101111100000000
sync.vhdl:76:9:@ 0ms :(报告单):BlockCount_LB = 000000000000000001111111011101101111110100000000
0000 0000 0000 0000 0 1101 1110 1010 1101 1011 1110 000 0000
D E A D B E
Address_LB看起来正确。
0000 0000 0000 0000 0 1111 1110 1110 1101 1111 1010 000 0000
F E E D F A
BlockCount_LB也是如此。
没有下降调用(原始作业):
Address_LB <= resize(sync_Offset & "0000000", Address_LB'length);
BlockCount_LB <= resize(sync_Length & "0000000", BlockCount_LB'length);
sync.vhdl:75:9:@ 0ms :(报告单):Address_LB = 110111101010110110111110000000000000000000000000
sync.vhdl:76:9:@ 0ms :(报告单):BlockCount_LB = 111111101110110111111010000000000000000000000000
哪个是
D E A D B E 0000 0000 0000 0000 0000 0000
和
F E E D F A 0000 0000 0000 0000 0000 0000
并不是一个问题,它真的说你应该提供一个MCVe。 (这些看起来就像你阅读调整大小函数所期望的那样)。
在ghdl工作。特定工具。我还仔细研究了XST支持的VHDL结构。
&
定义在哪里?定义类型后定义,以及单维数组类型和基本操作的其他预定义运算符。注意我使用了一个子类型,所以在这种情况下,这些隐式声明发生在包std_logic_1164中,遵循std_logic_vector(std_ulogic_vector,-2008)的声明。
咦?再试一次paebbels。赋值是从左到右的关联,左边的元素到左边的元素,...右边的元素到right_element)。没有保留数据,这需要在下降循环(或接口列表中的子类型指示正式,但它不会在任何长度上工作)。
就我个人而言,我没有看到编写函数的重点。简单地使用连接应该是合成安全的。
答案 1 :(得分:2)
串联运算符(&
)在VHDL标准中定义,例如
VHDL-2008部分&#34; 9.2.5添加运算符&#34;,其中的相关信息
关于方向和范围是:
a)...设S为结果基类型的索引子类型。 连接结果的方向是方向 S的结果左边界是S&#39; LEFT。
TYPE std_logic_vector IS ARRAY (NATURAL RANGE <>) OF std_logic;
(或
类似地),索引子类型S是具有上升方向的NATURAL
(NATURAL'ASCENDING = TRUE
)和左边界0(NATURAL'LEFT = 0
)。
std_logic_vector
的连接结果因此以0的左边界升序,sync_Offset & "0000000"
的情况也是如此。 (只有例外是两个零长度数组的连接,它返回正确的参数。)
您编写的resize
函数会将vec
参数放入。{1}}
留在结果中,并填入fill
,所以我希望结果来自:
resize(sync_Offset & "0000000", Address_LB'length);
是:
sync_Offset & "000...000"
如果结果中sync_Offset
值左侧有任何0,那么
这听起来像是你的结果解释或XST中的一个问题(少
可能的)。
顺便说一下。重复使用resize
名称作为其他操作的函数
resize
的{{1}}可能会导致混淆。