www.mikrocontroller.net

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


Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.