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!

  • 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). – Paebbels Dec 27 '15 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? – Thomas McKay-Smith Dec 27 '15 at 22:48
  • Even with a constant index my tool stalls during 'Place & Route'. – Thomas McKay-Smith Dec 27 '15 at 23:03
  • Solution: Move the assignments to `my_signal` into the process. Assign only indices which are never addressed by `index`. – Paebbels Dec 27 '15 at 23:09
  • What tool do you use? – Paebbels Dec 27 '15 at 23:12
  • @Paebbels ISE Project Navigator – Thomas McKay-Smith Dec 27 '15 at 23:37
  • Incrementing std_logic_vector is a silly idea anyway, or more politely, a design problem. Using the `numeric_std` library, if it represents an unsigned number, declare it `unsigned`. Or better still, declare your index as a `natural`. Either way you eliminate most of the ugly type conversions at a stroke. –  Dec 27 '15 at 23:45
  • Did you use the latest version of ISE, i.e. 14.7? Because, the error message is a little bit different there and it lists all multiple drivers. Of course, in your example it is not obvious where do they come from. Moreover, if `index` is changed to a constant, synthesis as well as place & route run successfully without errors. – Martin Zabel Dec 29 '15 at 10:39

3 Answers3

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.

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;
Community
  • 1
  • 1
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • 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_vector`or `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. – Martin Zabel Dec 29 '15 at 10:42
  • @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. – Renaud Pacalet Dec 29 '15 at 10:58
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.

Community
  • 1
  • 1
Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49
  • 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. – Thomas McKay-Smith Dec 27 '15 at 22:40