论文:
Xilinx在连接这些矢量后反转矢量的方向。
我有一个SATAController和一个PicoBlaze软核处理器。此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;编辑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 declaredT_SLV_<n>代表"type;std_logic_vector;n位-> (n-1下降到0)“。
发布于 2015-02-11 07:33:26
使用它作为一个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";请注意本地函数最小值,而不是伊明函数(未提供)和to_string的本地副本(此ghdl符合-1993 )。还请注意带有本地最小值的最小上下文子句。
这给了:
ghdl -a sync.vhdl ghdl -e同步 ghdl -r同步 :sync.vhdl:75:9:@0ms:(报告注):Address_LB = :sync.vhdl:76:9:@0ms:(报告注):BlockCount_LB = 000000000000000001101111010101101101111100000000 :sync.vhdl:75:9:@0ms:(报告注):Address_LB = 000000000000000001111111011101101111110100000000 :sync.vhdl:76:9:@0ms:(报告注):BlockCount_LB =
0000 0000 0000 0000 0 1101 1110 1010 1101 1011 1110 000 0000
D E A D B EAddress_LB看起来是对的。
0000 0000 0000 0000 0 1111 1110 1110 1101 1111 1010 000 0000
F E E D F ABlockCount_LB也是如此。
如果没有下降呼叫(原始作业):
Address_LB <= resize(sync_Offset & "0000000", Address_LB'length);
BlockCount_LB <= resize(sync_Length & "0000000", BlockCount_LB'length);110111101010110110111110000000000000000000000000 :sync.vhdl:75:9:@0ms:(报告注):Address_LB = 111111101110110111111010000000000000000000000000 :sync.vhdl:76:9:@0ms:(报告注):BlockCount_LB =
这就是
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)。
哈?再试一次,波培尔。赋值是从左到右结合,左元素到左元素,.(右元素为right_element)。没有保留的数据,这将需要在下降循环(或接口列表中的子类型指示形式,但然后它将不能与任何长度)。
就我个人而言,我不认为编写函数可以做到这一点。简单地使用级联应该是综合安全的。
发布于 2015-02-11 15:14:40
级联操作符(&)是在VHDL标准中定义的,例如VHDL-2008节"9.2.5添加运算符“,其中有关方向和范围的相关信息是:
a) ..。设S是结果的基类型的索引子类型。级联结果的方向是S的方向,结果的左界是S‘左。
对于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参数放在结果的左边,并填充fill,因此我希望得到以下结果:
resize(sync_Offset & "0000000", Address_LB'length);将是:
sync_Offset & "000...000"如果结果中的sync_Offset值左边有0,那么在您的结果解释或XST (不太可能)中,这听起来是个问题。
顺便说一句。使用resize的resize以外的其他操作重用unsigned名称可能会导致混淆。
https://stackoverflow.com/questions/28444810
复制相似问题