2

Background:

I have a type array of four 4-bit std_logic_vector's:

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

and a corresponding signal:

signal my_signal : my_arr_type;

I also have a 2-bit vector to be used as an array index:

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

This allows me to access each 4-bit vector dynamically like so:

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

In this case the indexed 4-bit vector will get the value b"0001".

The problem:

I would like to increment the value of the currently indexed 4-bit vector by 1, when some condition is true eg. switch is high.

I thought I could this with something like:

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;

However, I must be doing something wrong since passing the resulting signal to an output gives an error message - along the lines:

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

The question:

What am I doing wrong in the above attempt? What would be a correct solution?

I cannot find any examples online which relate to incrementing cells in an indexed array.

(Designing for synthesis to Digilent Nexys 3 in ISE Proj Nav)

(edit)Longer code snippet for greater scrunity:

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;

edit: All answers and comments have been helpful. Thank you!

8
  • Your synthesis tool does not recognize that index is a constant value. So it calculates the multiple drivers on a per signal name not on a per index name. Please change your signal index to a constant and it should recognize it (it's just for testing). Commented Dec 27, 2015 at 22:42
  • @Paebbels Okay. That makes sense. And you are right - changing index to a constant value does make the code synthesis-able. Any advice on how to overcome this problem when index is not a constant? Commented Dec 27, 2015 at 22:48
  • Even with a constant index my tool stalls during 'Place & Route'. Commented Dec 27, 2015 at 23:03
  • Solution: Move the assignments to my_signal into the process. Assign only indices which are never addressed by index. Commented Dec 27, 2015 at 23:09
  • What tool do you use? Commented Dec 27, 2015 at 23:12

3 Answers 3

2

This is associated with longest static prefix, it's not just a synthesis issue but is also reflected in simulation as well.

The drivers for my_signal in a process are determined by the longest static prefix of my_signal.

By using a non-static value for the index into the array you have created drivers for my_signal(0), my_signal(1), my_signal(2) and my_signal(3) in your unlabeled process.

Each of the concurrent signal assignments have an equivalent process, and these have a longest static prefix that includes the numeric literals uses as the index into your my_signal array.

The two drivers in common between the unlabeled process and each equivalent process for each concurrent assignment statement results in a resolved signal value, which in simulation will produce 'X' or 'U' values for conflicting values of std_logic elements. Your synthesis balks and reports you've shorted drivers together.

See 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, para 5.

If you used an unresolved element type (BIT, BIT_VECTOR) you'd get reports of one or more errors during elaboration for multiple drivers on a signal net. This is the equivalent of what your synthesis tool reports.

Sign up to request clarification or add additional context in comments.

Comments

1

Your problem is a multiple drive problem. This post and its answer may help understanding it. As you are using resolved types (std_logic) you will not get errors or warnings when compiling or simulating. The tool you are using (ISE) is a logic synthesizer. It tries to map the behaviour you described to existing hardware resources. As your hardware target does not support multiple drives, you get errors. My advices:

  • do not use resolved types when they are not necessary,
  • use appropriate types (as wisely suggested by Brian Drummond).

Something like the following code should be better. Adapt it to your specific needs. Note that the unsigned type of ieee.numeric_stdis, unfortunately, a resolved type. So, use it carefully and avoid multiple drive situations. Or, even better, if your tools support it, use unresolved_unsigned the unresolved version of 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 Comments

Using the unresolved types is generally a good advice, but it is not helpful here. The synthesizer of ISE 14.7 complains about the same error whether one uses std_logic_vectoror std_ulogic_vector for the elements of my_signal. The multiple drivers are listed, but unfortunatly, it is not obvious where do they come from.
@MartinZabel Using unresolved types does not prevent you from writing bogus code. It simply helps you avoiding multiple drive situations: your simulation tool will raise errors and tell you what's wrong. Anyway, debugging a VHDL code with a synthesizer is a bad idea.
0

Reason (probably) is that there is an another process or concurrent assign that drives (assigns to) my_signal, so look through your entire code, or post it here for further scrutiny.

Note that the driver (assign) may be to another index; take a look at this answer.

Btw. you can remove the

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

since my_signal will keep the current value until given a new.

1 Comment

That was my understanding of the error, but I can't see anything else which assigns to my_signal (at least not the 4-bit vector indexed, I assume some misconception in this complexity is my problem). I have added my entire code for you to scrutinize, if you will. Meanwhile, I'll read your other answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.