Konstanter Wert für VHDL-Array-Indizierung erforderlich?

Ich habe im Grunde eine Zeile wie diese in einem VHDL-Code.

entity my_entity is
   port(x : in std_logic_vector;
        y : in std_logic_vector;
        ...);
end entity my_entity;

architecture arch of my_entity is
   -- declarations...
   signal delta : unsigned(...); --correct sizing
   signal aux_signal : std_logic; -- correct sizing
   signal another_signal : unsigned(...); --correct sizing
begin
   delta <= x - y; -- x > y
   aux_signal <= or_reduce(std_logic_vector(another_signal(to_integer(delta) downto 1)));
   -- other stuff
end architecture arch;

Die Syntax ist in Ordnung (überprüft von ncvhdl), aber wenn ich die Synthese versuche, beschwert sich der Compiler über Zuweisungen wie "aux_signal", die sagen, dass es einen konstanten Wert braucht.

Da ich so eine Aufgabe brauche ... gibt es einen anderen Weg, um dasselbe Ergebnis zu erzielen?

Antworten (2)

Jeffs forSchleife ist hier der richtige Ansatz, aber Sie müssen sie nicht in einen Prozess einbetten: Sie kann stattdessen eine Funktion sein, und die meisten Synthesewerkzeuge (möglicherweise nicht alle!) sollten damit korrekt umgehen.

function or_reduce_select (sig : unsigned; mask : natural) return std_logic is
  variable or_result : std_logic;
begin
  or_result := '0';
  for i in 1 to sig'left loop
    if i <= mask then
      or_result := or_result or sig(i);
    end if;
  end loop;
  return or_result;
end or_reduce_select;

...

aux_signal <= or_reduce_select(another_signal, to_integer(delta));

BEARBEITEN zu: Kommentaren ...
Das Original erfordert unterschiedliche Hardware für unterschiedliche Werte von Delta. Da Delta zur Laufzeit variiert, muss Hardware zur Laufzeit erscheinen und verschwinden.

Schauen Sie sich die Schleife hier an: Die Grenzen 1 to sig'leftsind konstant, also ist die Hardware festgelegt: Stattdessen maskiert die "if" -Bedingung jedes unerwünschte Bit mit einem UND-Gatter - das Gatter ist immer da, sein anderer Eingang ist zur Laufzeit variabel. Somit ist diese Form in Hardware physikalisch realisierbar, während dies bei der ursprünglichen Form nicht der Fall ist.

Vielleicht ist es einfacher, die Hardware zu visualisieren, die dadurch erzeugt wird, wenn wir die Schleife neu schreiben:

  for i in 1 to sig'left loop
    if i <= mask then
      or_result := or_result or sig(i);
    end if;
  end loop;

in folgender Form

  for i in 1 to sig'left loop
    or_result := (or_result or sig(i)) and (i <= mask); 
  end loop;
Darf ich fragen, warum Funktion und Schleife in einem solchen Fall funktionieren, während die gleichzeitige Zuweisung nicht funktioniert? Mir fehlt die Logik dahinter.
Der Funktionsaufruf IST eine gleichzeitige Zuweisung (oder er kann auch in einem Prozess verwendet werden)
Ok ... dann verstehe ich das Problem mit meiner Aussage nicht, warum es stattdessen funktioniert (oder gleichwertig ...). Ich verstehe nicht, welche Art von Problem Sie auf diese Weise vermeiden und warum Sie auf diese Weise vermeiden können.
Jeff hat das Problem mit Ihrer aktuellen Aussage beantwortet. Es erfordert unterschiedliche Hardware für unterschiedliche Werte von Delta. Da Delta zur Laufzeit variiert, muss Hardware zur Laufzeit erscheinen und verschwinden. Schauen Sie sich die Schleife hier an: Die Grenzen 1 to sig'leftsind konstant, also ist die Hardware festgelegt: Stattdessen maskiert die "if" -Bedingung jedes unerwünschte Bit mit einem UND-Gatter - das Gatter ist immer da, sein anderer Eingang ist zur Laufzeit variabel. Somit ist diese Form in Hardware physikalisch realisierbar, die ursprüngliche Form jedoch nicht.

Das Problem ist hier:

another_signal(to_integer(delta) downto 1)

Slices mit laufzeitvariablen Grenzen werden von der Synthese nicht unterstützt. Wie würde sich das in echte Hardware übersetzen?

Eine ähnliche Funktion könnten Sie mit einer Schleife innerhalb eines Prozesses erreichen:

process (delta, another_signal)
  variable or_result : std_logic;
begin
  or_result := '0';
  for i in 1 to another_signal'left loop
    if (i <= to_integer(delta)) then
      or_result := or_result or another_signal(i);
    end if;
  end loop;
  aux_signal <= or_result;
end process;

Wenn Sie keinen Prozess verwenden können und die Größe von another_signalfestgelegt ist, könnten Sie Folgendes schreiben:

aux_signal <= another_signal(1) when delta = 1 else
              or_reduce(another_signal(2 downto 1) when delta = 2 else
              or_reduce(another_signal(3 downto 1) when delta = 3 else
              or_reduce(another_signal(4 downto 1) when delta = 4 else
              '0';

Ich würde Ihnen dringend empfehlen, Prozesse zu verwenden, auch für asynchrone Logik.

Es ist ein kombinatorisches Design, ich möchte einen Prozess vermeiden (auch wenn der Prozess kein FF oder Register synthetisiert). Kann ich stattdessen eine Funktion verwenden?
Warum um alles in der Welt sollten Sie vermeiden, das processKonstrukt zu verwenden?
Sei mir nicht böse xD. Nur weil ich es gewohnt bin, Prozesse normalerweise mit sequentiellen Designs zu verwenden.
@Lukkio Ich habe bearbeitet, um eine mögliche Lösung für den Fall „Kein Prozess verwenden“ hinzuzufügen.
Also muss ich im zweiten Fall unbedingt "Auflistung" aller Fälle verwenden? ich dachte es wäre einfacher...
Wäre es möglich, stattdessen eine Größenänderungsfunktion (basierend auf dem Delta-Wert) und dann das or_reduce für das Ergebnis zu verwenden? (von diesem Link )
Ist Ihr Prozess korrekt? Ich meine, Sie nehmen dort eine Signalzuweisung vor, da die Zuweisung semantisch korrekt ist (für das, was ich tun muss)?
Ich denke, die Verwendung resizewürde zu demselben Problem führen, dass der Parameter nicht konstant ist. Ich habe die Antwort aktualisiert, um einen vollständigen Prozess anzuzeigen.
Ich habe Ihren Prozess ausprobiert ... es funktioniert nicht. Intern hat es eine if-Anweisung wie <code>if delta < 3</code> und diese Zeile gibt mir den gleichen Fehler ...