论文:
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) 明确定义连接运算符。
所以这是我的问题:
- 这是特定于语言的功能或工具吗?
(我使用 Xilinx XST 进行这些测试。) - 在哪里
&
定义? - 连接两个后得到的向量方向是什么:
- 相等的有向向量或两个
- 反向向量?
解决方案:
- 可以使用已知方向的中间信号。
- 可以编写一个函数来强制某个方向。见功能
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;
编辑1:
涉及的包:
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>
代表“类型;std_logic_vector;n 位 -> (n-1 downto 0)”