如何使用索引在数组类型中增加std_logic_vector? VHDL

时间:2015-12-27 21:10:59

标签: arrays multidimensional-array vhdl synthesis

背景

我有一个四个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&#34; 0001&#34;。

问题:

当某些条件为真时,我想将当前索引的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设计合成)

(编辑)更长的代码段,以获得更大的灵活性:

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;

修改 所有答案和评论都很有帮助。谢谢!

3 个答案:

答案 0 :(得分:2)

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

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

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

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

未标记进程与每个并发赋值语句的每个等效进程之间的两个驱动因素共同产生一个已解析的信号值,在模拟中将生成&#39; X&#39;或者&#39; U&#39; std_logic元素的冲突值的值。您的综合报道并报告您将驱动程序短缺在一起。

参见IEEE Std 1076-2008 8.名称,8.1一般(最长静态前缀,第8段),14.7模型的执行,14.7.2驱动程序第1,14.7.3信号值的传播,14.7.3.1概述,第5段。

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

答案 1 :(得分:1)

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

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

以下代码应该更好。根据您的特定需求进行调整。请注意,遗憾的是,unsigned类型的ieee.numeric_std是已解决的类型。因此,请小心使用,避免多种驾驶情况。或者,更好的是,如果您的工具支持它,请使用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;

答案 2 :(得分:0)

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

请注意,驱动程序(assign)可能是另一个索引;看看this answer

顺便说一下。

可以删除

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

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