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


von Chris (Gast)


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
1
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
1
architecture Behavioral of n_bit_counter is
2
  signal count_max: std_logic_vector (n-1 downto 0) ;
3
   
4
begin
5
  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  :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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?

von Jan M. (mueschel)


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).

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

von Frank (Gast)


Lesenswert?

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

oder irre ich hier ?

von Chris (Gast)


Lesenswert?

Ok, vielen Dank für eure Antworten.

Zu meiner ersten Frage kann niemand etwas sagen?

von berndl (Gast)


Lesenswert?

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

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

von Chris (Gast)


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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.
1
:
2
   signal count: unsigned (n-1 downto 0) ;
3
:
4
   process (clk) begin
5
      if rising_edge(clk) then
6
         count <= count+1;
7
      end if;
8
   end process;
9
10
   zero <= '1' when count = (count'range=>'0') else '0'; 
11
12
   count_out <= std_logic_vector(count);
13
:

von Chris (Gast)


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:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
7
entity n_bit_counter is
8
9
  generic(n: integer :=2);
10
    Port ( clk : in  STD_LOGIC;
11
           reset : in  STD_LOGIC;
12
           enable : in  STD_LOGIC;
13
           init_value : in std_logic_vector (n-1 downto 0);
14
        overflow : out std_logic;
15
        count_out : out  STD_LOGIC_VECTOR (n-1 downto 0)
16
       );
17
end n_bit_counter;
18
19
architecture Behavioral of n_bit_counter is
20
  signal count_reg: std_logic_vector (n-1 downto 0) ;
21
  --signal count_max: std_logic_vector (n-1 downto 0) ;
22
   
23
begin
24
  --count_max <= (count_max'range => '1');
25
    process(clk,enable,reset)
26
    begin
27
      if reset = '1' then
28
        count_reg <= init_value;
29
      elsif (clk='1' and clk'event) then
30
        if enable='1' then
31
          count_reg <= count_reg +1;
32
        end if;
33
      end if;
34
      if count_reg = (count_reg'range =>'1') then
35
        overflow <= '1';
36
      else
37
        overflow <= '0';
38
      end if;
39
    end process;
40
  
41
  count_out <= count_reg;
42
end Behavioral;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

Mach es doch so:
1
begin
2
  --count_max <= (count_max'range => '1');
3
    process(clk,enable,reset)
4
    begin
5
      if reset = '1' then
6
        count_reg <= init_value;
7
      elsif (clk='1' and clk'event) then
8
        if enable='1' then
9
          count_reg <= count_reg +1;
10
        end if;
11
      end if;
12
    end process;
13
14
  -- Überlauf, wenn Zähler auf "111" steht
15
  overflow <= '1' when  count_reg = (count_reg'range =>'1') else '0';
16
17
  count_out <= count_reg;
18
end Behavioral;

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

von Chris (Gast)


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?

von Chris (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

von Chris (Gast)


Lesenswert?

Ok, alles klar. Nochmals vielen Dank

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.