mikrocontroller.net

Forum: FPGA, VHDL & Co. parametrisierbarer Binärzäher


Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe im Rahmen einer Übungsaufgabe das Modell eines Binärzählers 
geschrieben,  dessen Bitbreite mittels eines Generic-Konstrukts variabel 
sein soll.
Als Erweiterung dieser Aufgabe soll beim höchsten Zählzustand ein Bit 
gesetzt werden.
Da die Bitbreite den Ausgangsvektor unbekannt ist
count_out : out std_logic_vector (n-1 downto 0)

hab ich mir geholfen, indem ich ein lokales Signal mit gleicher 
Bitbreite wie count_out deklariere, das komplett mit '1' fülle
architecture Behavioral of n_bit_counter is
  signal count_max: std_logic_vector (n-1 downto 0) ;
   
begin
  count_max <= (count_max'range => '1');

und mit  count_out vergleiche.
Wahrscheinlich kann man das eleganter lösen, nur wie?

Und wo wir grad dabei sind, habe ich grad noch eine Frage zu dieser 
Zeile
count_max <= (count_max'range => '1');
Ich weiß zwar was sie diese Anweisung bewirkt aber was da genau passiert 
ist mir nicht klar.
'range ermittelt die Bitbreite des Vektors, aber was soll dann  der "=>" 
Operator?
Im Zusammenhang mit Signalzuweisungen in einer Port Map oder innerhalb 
von case-Anweisungen ist mir das ja klar, aber hier?

Wäre nett wenn das jemand helfen könnte  :)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeig doch mal ein wenig mehr vom Quellcode.
Natürlich brauchst du für den Endwert kein eigenes lokales Signal.
Du könntest z.B. eine Konstante verwenden:
constant count_max: std_logic_vector (n-1 downto 0) := (others=>'1');

Aber warum lässt du deinen Binärzahler nicht einfach überlaufen?

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>count_max <= (count_max'range => '1');
>Ich weiß zwar was sie diese Anweisung bewirkt aber was da genau passiert
>ist mir nicht klar.
>'range ermittelt die Bitbreite des Vektors, aber was soll dann  der "=>"
>Operator?

Die Syntax hier ist ganz einfach:

signal <= (Bitnummer/Range => Wert1, Bitnummer/Range => Wert2 ...);

Bitnummer/Range kann dabei für ein einzelnes Bit (z.B. 0, 1, 2...) 
stehen, dem dann Wert zugewiesen wird, oder gleich für eine ganze Reihe 
von Bits (z.B. (2 downto 0)), denen dann jeweils der Wert zugewiesen 
wird.
Dein count_max'range wird einfach automatisch durch die richtige Range 
ersetzt, in deinem Fall (n-1 downto 0).

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verschärft kann man dann ans Ende der Liste noch ein others 
einbringen:
 signal <= (Bitnummer/Range=>Wert1, Bitnummer/Range=>Wert2, ..., others=>Wert3);

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das denn überhaupt sinnvoll ? so wie ich das sehe, reicht hier doch 
ein einfaches:
count_max <= (others => '1');

oder irre ich hier ?

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, vielen Dank für eure Antworten.

Zu meiner ersten Frage kann niemand etwas sagen?

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Chris schrieb:
> signal count_max: std_logic_vector (n-1 downto 0) ;

doch, einfach wie oben schon angesprochen ersetzen durch:
  constant count_max : std_logic_vector (n-1 downto 0) := (others=>'1');

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>doch, einfach wie oben schon angesprochen ersetzen durch:
>
>  constant count_max : std_logic_vector (n-1 downto 0) := (others=>'1');


Nein, das meinte ich nicht. Es ging mir darum eine Methode zu finden mit 
der sich herausfinden läßt, ob der Vektor count_out seinen Maximalwert 
angenommen hat. Dies ist hier, zumindest mit meinen bisherigen 
Kenntnissen, problematisch, da ich die Größe des Vektor nicht kenne. 
Deshalb habe ich mir damit geholfen einen Hilfsvekttor count_max zu 
definieren, alle BITS auf 1 zu setzen und mt count_out zu vergleichen. 
Mir kommt diese Methode, obwohl sie funktioniert, recht aufwändig vor. 
Daher meine Frage: geht das auch einfacher?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wahrscheinlich kann man das eleganter lösen, nur wie?
1) Mit std_logic_vector rechnet man nicht. Nimm die numeric_std.
2) Lass den Zähler überlaufen.
:
   signal count: unsigned (n-1 downto 0) ;
:
   process (clk) begin
      if rising_edge(clk) then
         count <= count+1;
      end if;
   end process;

   zero <= '1' when count = (count'range=>'0') else '0'; 

   count_out <= std_logic_vector(count);
:

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Aufgabenstellung verlangt

  "...dass ein Überlauf bei höchstem Zählzustand angezeigt wird"

wobei das aus meiner Sicht unglücklich formuliert ist. Meines Wissens 
erfolgt der Überlauf nicht beim höchsten Zählstand sondern einen Takt 
später.
Wenn ich es so mache wie in deinem Beispiel, also den Ausgang auf 0 
teste, habe ich aber bereits gleich zu Beginn (vorausgesetzt ich fange 
bei null an zu zählen) das Überlaufbit auf 1, und das kann ja auch nicht 
gewollt sein, oder?

Ich habs jetzt mal so umgesetzt wie in der Aufgabenstellung gefordert 
und setzte das Überlaufbit beim höchsten Zählzustand:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity n_bit_counter is

  generic(n: integer :=2);
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           enable : in  STD_LOGIC;
           init_value : in std_logic_vector (n-1 downto 0);
        overflow : out std_logic;
        count_out : out  STD_LOGIC_VECTOR (n-1 downto 0)
       );
end n_bit_counter;

architecture Behavioral of n_bit_counter is
  signal count_reg: std_logic_vector (n-1 downto 0) ;
  --signal count_max: std_logic_vector (n-1 downto 0) ;
   
begin
  --count_max <= (count_max'range => '1');
    process(clk,enable,reset)
    begin
      if reset = '1' then
        count_reg <= init_value;
      elsif (clk='1' and clk'event) then
        if enable='1' then
          count_reg <= count_reg +1;
        end if;
      end if;
      if count_reg = (count_reg'range =>'1') then
        overflow <= '1';
      else
        overflow <= '0';
      end if;
    end process;
  
  count_out <= count_reg;
end Behavioral;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>     process(clk,enable,reset)
enable ist unnötig. Der Prozess ist nur von reset und clk abhängig.

Mach es doch so:
begin
  --count_max <= (count_max'range => '1');
    process(clk,enable,reset)
    begin
      if reset = '1' then
        count_reg <= init_value;
      elsif (clk='1' and clk'event) then
        if enable='1' then
          count_reg <= count_reg +1;
        end if;
      end if;
    end process;

  -- Überlauf, wenn Zähler auf "111" steht
  overflow <= '1' when  count_reg = (count_reg'range =>'1') else '0';

  count_out <= count_reg;
end Behavioral;

BTW:
Es ist nicht gut, mit Vektoren zu rechnen. Nimm besser die numeric_std 
und die darin definierten Datentypen unsigned bzw. signed.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, das ging aber schnell, danke

>enable ist unnötig. Der Prozess ist nur von reset und clk abhängig.

Hast Recht, aber schaden tut's auch nicht, oder?

>Es ist nicht gut, mit Vektoren zu rechnen.

ok, aber warum?

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: du hast die overflow Abfrage aus dem Prozess rausgenommen. Ist 
sie da besser aufgehoben?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Chris schrieb:
> Nachtrag: du hast die overflow Abfrage aus dem Prozess rausgenommen. Ist
> sie da besser aufgehoben?
Durch die Concurrent-Zuweisung entfällt der 1 Takt Latency, der dir 
Probleme gemacht hat.


>> Es ist nicht gut, mit Vektoren zu rechnen.
> ok, aber warum?
Du mußt immmer mit angeben, welche der Libs (STD_LOGIC_UNSIGNED oder 
STD_LOGIC_SIGNED) du verwendet hast. Bei der Verwendung der Datentypen 
SIGNED und UNSIGNED gibt es keine Doppeldeutigkeiten. Das hatten wir 
schon mal im Beitrag "Re: Problem mit FSM"

EDIT:
>> Hast Recht, aber schaden tut's auch nicht, oder?
JA und NEIN.
Es braucht in der Simulation (und nur für die Simulation ist die 
Sensitivliste überhaupt interessant) mehr Rechenzeit, denn der Prozess 
wird auch neu berechnet, wenn sich enable ändert. Das wäre aber unnötig.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, alles klar. Nochmals vielen Dank

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.