【问题标题】:How to increment std_logic_vector within an array type using index? VHDL如何使用索引在数组类型中增加 std_logic_vector?高密度脂蛋白
【发布时间】:2015-12-27 21:10:59
【问题描述】:

背景:

我有一个由四个 4 位 std_logic_vector 组成的类型数组:

type my_arr_type is array (0 to 3) of std_logic_vector (3 downto 0);

以及相应的信号:

signal my_signal : my_arr_type;

我还有一个 2 位向量用作数组索引:

signal index : std_logic_vector (1 downto 0) := "00";

这允许我像这样动态访问每个 4 位向量:

my_signal(to_integer(unsigned(index))) <= "0001";

在这种情况下,索引的 4 位向量将获得值 b“0001”。

问题:

当某些条件为真时,我想将当前索引的 4 位向量的值增加 1,例如。开关高。

我想我可以这样做:

process(clk)
begin
  if(rising_edge(clk)) then
      if switch = '1' then --switch flicked (increment)
          my_signal(to_integer(unsigned(index)))
          <= std_logic_vector(unsigned( my_signal(to_integer(unsigned(index))) ) + 1);
      else --remain the same
          my_signal(to_integer(unsigned(index))) 
          <= my_signal(to_integer(unsigned(index)));
      end if;
   end if;
 end process;

但是,我一定是做错了什么,因为将结果信号传递给输出会给出错误消息 - 大致如下:

Signal X is connected to multiple drivers. ERROR:HDLCompiler:1401

问题:

在上述尝试中我做错了什么?什么是正确的解决方案?

我在网上找不到任何与索引数组中递增单元格相关的示例。

(在 ISE Proj Nav 中设计合成到 Digilent Nexys 3)

(编辑)更长的代码 sn-p 以便更仔细:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ui_top is
Port (  clk         : in    std_logic;
            buttons     : in    std_logic_vector (4 downto 0); -- centre, left, up, right, down
            switches    : in    std_logic_vector (7 downto 0);
            leds            : out std_logic_vector (7 downto 0);
            digit           : out std_logic_vector (3 downto 0) := "1110";
            segments    : out std_logic_vector (7 downto 0) := (others => '0');
            uart_tx     : out std_logic);
end ui_top;

architecture Behavioral of ui_top is

    type my_arr_type is array (0 to 3) of std_logic_vector(3 downto 0);

    signal my_signal : my_arr_type;
    signal index : std_logic_vector (1 downto 0) := "00";


begin

    -- send indexed signal to leds
    leds(3 downto 0) <= my_signal(to_integer(unsigned(index)));

    -- set other outputs arbitrarily
    leds(7 downto 4) <= (others => '1');
    uart_tx <= '1';
    digit <= "1110";
    segments <= (others => '0');

    -- set index
    index <= "00";

    process(clk)
    begin
        if (rising_edge(clk)) then
            if switches(1) = '1' then -- up
                my_signal(to_integer(unsigned(index)))
                <= std_logic_vector(unsigned( my_signal(to_integer(unsigned(index))) ) + 1);
            end if;
        end if; -- rising clock edge
    end process;

    -- set non indexed values arbitrarily
    my_signal(1) <= "0000";
    my_signal(2) <= "0000";
    my_signal(3) <= "0000";

end Behavioral;

编辑: 所有答案和 cmets 都有帮助。谢谢!

【问题讨论】:

  • 您的综合工具无法识别index 是一个常数值。所以它计算每个信号名称而不是每个索引名称的多个驱动程序。请将您的信号 index 更改为常量,它应该能够识别它(它只是为了测试)。
  • @Paebbels 好的。这就说得通了。你是对的 - 将index 更改为常数值确实可以使代码合成。当索引不是常数时,关于如何克服这个问题的任何建议?
  • 即使索引不变,我的工具也会在“放置和布线”期间停止。
  • 解决方案:将my_signal 的分配移动到进程中。仅分配 index 从未解决的索引。
  • 你用什么工具?

标签: arrays multidimensional-array vhdl synthesis


【解决方案1】:

这与最长静态前缀有关,这不仅仅是一个综合问题,也反映在模拟中。

进程中my_signal的驱动由my_signal的最长静态前缀决定。

通过对数组的索引使用非静态值,您在未标记的进程中为 my_signal(0)、my_signal(1)、my_signal(2) 和 my_signal(3) 创建了驱动程序。

每个并发信号分配都有一个等效的过程,它们有一个最长的静态前缀,其中包括用作 my_signal 数组索引的数字文字。

未标记进程和每个并发赋值语句的每个等效进程之间的两个共同驱动程序会产生一个已解析的信号值,在模拟中将为 std_logic 元素的冲突值生成“X”或“U”值。您的综合中断并报告您已将驱动程序短接在一起。

参见 IEEE Std 1076-2008 8. Names, 8.1 General (longest static prefix, para 8), 14.7 Execution of a Model, 14.7.2 Drivers para 1, 14.7.3 Propagation of signal values, 14.7.3.1 General,第 5 段。

如果您使用了未解析的元素类型(BIT、BIT_VECTOR),您会在详细说明信号网络上的多个驱动程序期间收到一个或多个错误的报告。这相当于您的综合工具报告的内容。

【讨论】:

    【解决方案2】:

    您的问题是多驱动器问题。 This post and its answer 可能有助于理解它。当您使用已解析的类型 (std_logic) 时,您在编译或模拟时不会收到错误或警告。您使用的工具 (ISE) 是一个逻辑合成器。它尝试将您描述的行为映射到现有的硬件资源。由于您的硬件目标不支持多个驱动器,因此您会遇到错误。我的建议:

    • 不要在不需要时使用已解析的类型,
    • 使用适当的类型(Brian Drummond 明智地建议)。

    类似下面的代码应该会更好。使其适应您的特定需求。请注意,不幸的是,ieee.numeric_stdunsigned 类型是已解析的类型。因此,请谨慎使用并避免多次驾驶情况。或者,更好的是,如果您的工具支持它,请使用 unresolved_unsigned 的未解析版本 unsigned

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity ui_top is
      Port(clk         : in  std_ulogic;
           buttons     : in  std_ulogic_vector (4 downto 0); -- centre, left, up, right, down
           switches    : in  std_ulogic_vector (7 downto 0);
           leds        : out std_ulogic_vector (7 downto 0);
           digit       : out std_ulogic_vector (3 downto 0);
           segments    : out std_ulogic_vector (7 downto 0);
           uart_tx     : out std_ulogic);
    end ui_top;
    
    architecture Behavioral of ui_top is
    
      constant n: positive := 4;
      type my_arr_type is array (0 to 3) of unsigned(n-1 downto 0);
      -- type my_arr_type is array (0 to 3) of unresolved_unsigned(n-1 downto 0);
    
      signal my_signal : my_arr_type;
      signal index : natural range 0 to n-1;
    
    begin
    
      -- send indexed signal to leds
      leds(n-1 downto 0) <= std_ulogic_vector(my_signal(index));
    
      -- set other outputs arbitrarily
      leds(7 downto n) <= (others => '1');
      uart_tx <= '1';
      digit <= "1110";
      segments <= (others => '0');
      -- set index
      index <= 0;
    
      process(clk)
      begin
        if (rising_edge(clk)) then
          -- set non indexed values arbitrarily
          for i in 0 to n-1 loop
            if i = index then
              if switches(1) = '1' then -- up
                my_signal(i) <= my_signal(i) + 1;
              end if;
            else
              my_signal(i) <= (others => '0');
            end if;
          end loop;
        end if; -- rising clock edge
      end process;
    
    end Behavioral;
    

    【讨论】:

    • 使用未解析的类型通常是一个好建议,但在这里没有帮助。无论使用std_logic_vectorstd_ulogic_vector作为my_signal的元素,ISE 14.7的合成器都会抱怨同样的错误。列出了多个驱动程序,但不幸的是,它们的来源并不明显。
    • @MartinZabel 使用未解析的类型不会阻止您编写虚假代码。它只是帮助您避免多种驾驶情况:您的模拟工具会引发错误并告诉您出了什么问题。无论如何,用合成器调试 VHDL 代码是个坏主意。
    【解决方案3】:

    原因(可能)是另一个进程或并发分配驱动(分配给)my_signal,因此请查看您的整个代码,或将其发布在此处以进行进一步审查。

    注意驱动(assign)可能是给另一个索引的;看看this answer

    顺便说一句。你可以删除

    else --remain the same
        my_signal(to_integer(unsigned(index))) 
        <= my_signal(to_integer(unsigned(index)));
    

    因为my_signal 将保留当前值,直到给出新值。

    【讨论】:

    • 这是我对错误的理解,但我看不到分配给 my_signal 的任何其他内容(至少不是索引的 4 位向量,我认为对这种复杂性的一些误解是我的问题) .如果您愿意,我已经添加了我的整个代码供您仔细检查。同时,我会阅读您的其他答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    相关资源
    最近更新 更多