首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >VHDL:协调两个矢量-产生的矢量方向是什么?

VHDL:协调两个矢量-产生的矢量方向是什么?
EN

Stack Overflow用户
提问于 2015-02-11 00:59:28
回答 2查看 2.7K关注 0票数 2

论文:

Xilinx在连接这些矢量后反转矢量的方向。

我有一个SATAController和一个PicoBlaze软核处理器。此CPU使用寄存器接口+交叉时钟来读取/写入测试数据。CPU写入6个8位寄存器,其中存储一个24位偏移量和一个24位长度字段,用于读取请求。这些地址和长度字段被扩展到48位(关键字: LBA-48寻址模式)。

看上去怎么样?

代码语言:javascript
复制
  -- 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。)
  • &是在哪里定义的?
  • 连接两个向量后得到的矢量方向是什么:
    • 等向向量或两个
    • 反向定向向量?

解决办法:

  1. 人们可以使用已知方向的中间信号。
  2. 一个人可以写一个函数来强制某个方向。参见函数descend(..)

固定的例子从上面:

代码语言:javascript
复制
Address_LB    <= resize(descend(sync_Offset & "0000000"), Address_LB'length);
BlockCount_LB <= resize(descend(sync_Length & "0000000"), BlockCount_LB'length);

附录-职能声明:

代码语言:javascript
复制
subtype T_SLV_24  is STD_LOGIC_VECTOR(23 downto 0);
subtype T_SLV_48  is STD_LOGIC_VECTOR(47 downto 0);

调整大小功能:

代码语言:javascript
复制
-- 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:

涉及的一揽子方案:

代码语言:javascript
复制
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>代表"type;std_logic_vector;n位-> (n-1下降到0)“。

EN

回答 2

Stack Overflow用户

发布于 2015-02-11 07:33:26

使用它作为一个MCVe:

代码语言:javascript
复制
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;

有两个初始值:

代码语言:javascript
复制
    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 =

代码语言:javascript
复制
0000 0000 0000 0000 0 1101 1110 1010 1101 1011 1110 000 0000
                        D    E    A    D    B    E

Address_LB看起来是对的。

代码语言:javascript
复制
0000 0000 0000 0000 0 1111 1110 1110 1101 1111 1010 000 0000
                        F    E    E    D    F    A

BlockCount_LB也是如此。

如果没有下降呼叫(原始作业):

代码语言:javascript
复制
  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 =

这就是

代码语言:javascript
复制
D  E   A   D   B   E  0000 0000 0000 0000 0000 0000

代码语言:javascript
复制
F  E   E   D   F   A  0000 0000 0000 0000 0000 0000

也不像这个问题,它真的是说你应该提供一个MCVe。(这些看起来就像阅读调整大小函数时所期望的那样)。

  • 这是一个特定的语言特性或工具吗?(我在这些测试中使用了Xilinx。)

在ghdl工作。特定工具。我还将仔细研究XST支持的VHDL结构。

  • &是在哪里定义的?

一旦定义了该类型,它将与其他预定义的操作符一起定义,用于一维数组类型和基本操作。注意,我使用了一个子类型,因此在本例中,这些隐式声明发生在包std_logic_1164中,在std_logic_vector声明之后(std_ulogic_vector,-2008)。

  • 等向向量和反向有向向量的产生向量方向是什么?

哈?再试一次,波培尔。赋值是从左到右结合,左元素到左元素,.(右元素为right_element)。没有保留的数据,这将需要在下降循环(或接口列表中的子类型指示形式,但然后它将不能与任何长度)。

就我个人而言,我不认为编写函数可以做到这一点。简单地使用级联应该是综合安全的。

票数 2
EN

Stack Overflow用户

发布于 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,因此我希望得到以下结果:

代码语言:javascript
复制
resize(sync_Offset & "0000000", Address_LB'length);

将是:

代码语言:javascript
复制
sync_Offset & "000...000"

如果结果中的sync_Offset值左边有0,那么在您的结果解释或XST (不太可能)中,这听起来是个问题。

顺便说一句。使用resizeresize以外的其他操作重用unsigned名称可能会导致混淆。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28444810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档