Forum: FPGA, VHDL & Co. Parallele Addierer für einen 16*16 Bit Array


von Daniel R. (daniel_r)


Lesenswert?

Hallo,

ich brauche 16 voneinander unabhängige Zähler, welche alle ihre eigenen
"Triggerleitungen" haben. D.h. ich möchte eine bestimmten Zähler von
meinen 16 Stück inkrementieren, wenn auf einem Signal eine Taktflanke
anliegt.

Dazu habe ich mir einen Array angelegt:

type cnt_type is array (0 to 15) of std_logic_vector(15 downto 0);
signal counters : cnt_type;

Gibt es nun eine Möglichkeit die Zähler über irgendwelche logischen
Verknüpfungen so anzusteuern, dass er bei einer Taktflanke auf dem
Triggersignal(jeder Counter hat ein eigenes) inkrementiert wird?

Dies würde mir ersparen 16 einzelne Zähler schreiben zu müssen.

Das Ganze dient einer Zeitverzögerung in welcher auf ein anderes Signal
gewartet wird. Von diesen Signalen habe ich 16 Stück und alle müssen
unabhängig voneinander ausgewertet werden...



Vielen Dank.


Daniel

von schlumpf (Gast)


Lesenswert?

Du hast also für jeden Zähler ein eigenes Triggersignal, mit dem du den
Zähler um eins inkrementieren willst?
Dann musst du auch für jedes Signal beschreiben, was passieren soll.

type trigger_type is array (0 to 15) of std_logic;
signal trigger : trigger_type;

in der synchronen Umgebung (also innerhalb des Clock-Prozesses)
beschreibst du dann für jeden Trigger:

if trigger(0) = '1' then
counters(0) <= counters(0) + 1;

if trigger(1) = '1' then
counters(1) <= counters(1) + 1;

usw....

von Daniel R. (daniel_r)


Lesenswert?

>Du hast also für jeden Zähler ein eigenes Triggersignal, mit dem du
den
>Zähler um eins inkrementieren willst?

Richtig.

>Dann musst du auch für jedes Signal beschreiben, was passieren soll.

Genau das wollte ich verhindern....  :(

Gibt es also definitiv keine andere Möglichkeit?


Daniel

von Klaus F. (kfalser)


Lesenswert?

Es ist nicht ganz klar was Du mit Trigger-Signal meinst.
Hast Du 16 Signale, und wenn an einem eine aufsteigende Flanke kommt,
dann soll der dazugehörige Zähler erhöht werden?

Die einfache Variante dazu wäre eine separates Modul mit einem Zähler,
der bei der aufsteigenden Taktflanke erhöht wird.
Dieses Modul verwendest Du 16 mal, und verknüpst dein "Triggersignal"
mit dem Takteingang des Zählmodul.
Das Zählmodul wird also nur 1 mal geschrieben, aber 16 mal verwendet.
Du kannst Dir sogar noch ein bischen Schreibarbeit sparen, wenn Du das
Generate-Statement verwendest.
Diese Variante hat aber den Nachteil, daß dabei 16 Taktleitungen im
CPLD oder FPGA benötigt würden. So viele gibt es aber meist nicht, es
werden dann andere Signal-Leitungen verwendet.

Bei der kompliziertere Variante hast Du einen Takt, der viel schneller
als deine Trigger-Signale ist, und das ganze Design läüft synchron mit
diesem Takt.
Du schreibst wieder ein Modul mit einem Zähler, der nit dem schnellen
Takt läuft, und wenn das Trigger-Signal beim Vorhergehenden Taktzyklus
0 war und beim aktuellen 1 ist, dann wird der Zähler erhöht.
Wieder brauchst Du dieses Modul nur 1 mal zu schreiben. Im Top Level
Modul verwendest Du das Zählermodul 16 mal.

Grüße
Klaus

von schlumpf (Gast)


Lesenswert?

Denk mal nicht, dass es das gibt.. Woher sollte das synthesetool denn
erraten, was du vorhast?
Wenn die Triggersignale gleichzeitig kommen würden, dann wäre es ja
kein Prroblem....
Hmmm... eventuell könntest du ja versuchen, den gesamten Array ein Feld
zuzuweisen und in dieses Feld deine Trigger reinzuschreiben.

So in der art...

counters <= counters + (trigger(0), trigger(1), trigger(2)....)

müsstest mal probieren, ob du das Syntxmässig hinbekommst.
Dann würde einfach bei jedem Takt der Wert jedes Triggers zum
zugehörigen Counter addiert (entweder 1 oder 0)
Glaub aber nicht, dass das läuft. Aber Versuch macht klug ;-)

von Matthias (Gast)


Lesenswert?

Warum machst du nicht ne Schleife im Prozess?
Also vorausgesetzt deine Eingänge sind in der Entity als trigger: in
std_logic_vector(15 downto 0) definiert, und die counter Stände wie von
dir beschrieben:

process(clk)
variable i: natural range 0 to 15;
begin
if rising_edge(clk) then
  for i in to 15 loop
    if trigger(i) = '1' then
    counters(i) <= counters(i) + 1;
  end loop;
end process;

Kein Anspruch auf syntaktische Richtigkeit, bin zu faul das jetzt zu
testen ;)

von schlumpf (Gast)


Lesenswert?

Na ja, so kann man es auch machen, aber ehrlich gesagt, bei Schleifen
bin ich vorsichtig... man weiss nie so richtig, was die Synthese draus
macht, oder?

von Daniel R. (daniel_r)


Lesenswert?

@Klaus Falser

>>Hast Du 16 Signale, und wenn an einem eine aufsteigende Flanke
kommt,
>>dann soll der dazugehörige Zähler erhöht werden?
Ja, stimmt.

Ich habe die Signale bereits über 2 FFs eingetaktet. Das meintest Du
glaub ich auch mit der "komplizierteren Variante".

D.h. bei einer steigenden Flanke am "Triggersignal" kommt nach den 2
FFs nur noch eine einen Takt lange Flanke. Diese soll letztendlich das
Inkrementieren des dazugehörigen Counters auslösen. Die Triggersignale
sind relativ langsam.


@Matthias
Dann würde ja bei jedem Durchlauf eins dazuaddiert werden, unabhängig
vom Triggersignal oder?


@Schlumpf
counters <= counters + (trigger(0), trigger(1), trigger(2)....)

Das würde gehen(vorausgesetzt ich kriegs mit dem Syntax hin).


Ich brauche im Prinzip einen Addierer, der einen Vector inkrementiert,
wenn eine Taktflanke reinkommt(das Triggersignal). Und dieses Ding
brauch ich 16 mal...


Daniel

von schlumpf (Gast)


Lesenswert?

So beschreibst du zwar auch 16 Counter, aber der Code ist recht
übersichtlich: (Hier im Beispiel mit 2 Counter)

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.all;USE ieee.std_logic_arith.all;

ENTITY conterversuch IS
   PORT(
      clk     : IN     std_logic;
      reset   : IN     std_logic;
      trigger : IN     std_logic_vector (0 TO 1)
   );


END conterversuch ;

ARCHITECTURE arch OF conterversuch IS
type cnt_type is array (0 to 1) of std_logic_vector (15 downto 0);
signal counters_in, counters_q : cnt_type;

BEGIN
  process(clk, reset)
  begin
    if reset = '0' then
      counters_q <= (x"0000", x"0000");
    elsif clk'event and clk <= '1' then
      counters_q <= counters_in;
    end if;
  end process;

  process(counters_q, trigger)
  begin
    counters_in <= counters_q;

    if trigger(0) = '1' then counters_in(0) <= counters_q(0) + 1; end
if;
    if trigger(1) = '1' then counters_in(1) <= counters_q(1) + 1; end
if;
  end process;

END arch;

von schlumpf (Gast)


Lesenswert?

Daniel, ich hab das mit dem addieren versucht, aber leider erfolglos.
Mein Compiler meckert das + an, wenn ich versuche, ein Feld zu
addieren.

Aber wenn du das hinbekommst, dann sag bescheid, mich würde das
interessieren

von Klaus F. (kfalser)


Lesenswert?

Ich denke, Matthias hat schon die richtige Lösung gebracht.

Man kann es auch mit einen Generate Statement schreiben, dann ist der
Loop außerhalb des Prozesses
..
g: for i in 0 to 15 generate
  process(clk)
  begin
    if rising_edge(clk) then
      if trigger(i) = '1' then
        counters(i) <= counters(i) + 1;
      end if;
    end if;
  end process;
end generate g1;

Klaus

von yalu (Gast)


Lesenswert?

Ich weiß, hier im Forum machen alle VHDL ...
... außer mir, ich find Verilog etwas cooler, obwohl die Unterschiede
sicher marginal sind.

In Verilog würde man so oder so ähnlich schreiben:

module counter(input trigger, output reg [15:0] out);
always @(posedge trigger)
  out <= out + 1;
endmodule

module test( /* ... */ );
wire [15:0] manytriggers
wire [15:0] manyouts [15:0];
counter manycounters [15:0] (trigger, out);
endmodule

Das erste Modul definiert einen Einzelzähler, im zweiten werden 16
Stück davon instantiiert. Natürlich müssen die manytriggers und
manyouts noch mit irgendwas vebunden werden.

In VHDL gibt's soch sicher ein vergleichbares Konstrukt.

von yalu (Gast)


Lesenswert?

'tschuldigung, das zweite Modul muss natürlich so aussehen
module test( /* ... */ );
wire [15:0] manytriggers
wire [15:0] manyouts [15:0];
counter manycounters [15:0] (manytriggers, manyouts);
endmodule

Die Namen der Argumente der manycounters waren falsch.

von Daniel R. (daniel_r)


Lesenswert?

Vielen Dank an alle!!! Ich denke Matthias´ und Klaus´ Lösung ist die
Richtige. Genau das, was ich gesucht habe. Ich kannte die Generate
Anweisung zuvor nicht.

Falls es Probleme gibt komme ich auf Euch zurück.


Daniel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.