Forum: FPGA, VHDL & Co. Counter VHDL


von teciu (Gast)


Lesenswert?

Hallo Zusammen.
Ich habe ein bisschen Mühe mit dem Design eines modulo-n Counters. 
Dieser soll von n-1 rückwärts bis 0 zählen und danach wieder auf n-1 
springen. Der Reset value ist ebenfalls n-1.

Hier ist mein Code:
1
use ieee.std_logic_1164.all;
2
use ieee.numeric_std.all;
3
use ieee.math_real.all;
4
5
6
entity mod_n_counter is
7
8
generic(
9
    n : integer := 255;
10
);
11
port(
12
    clk       : in  std_ulogic;
13
    reset      : in  std_ulogic;
14
    count_out : out std_ulogic_vector(integer(ceil(log2(real(n+1))))-1 down to 0);
15
);
16
end mod_n_counter;
17
18
19
architecture behavioral of mod_n_counter is
20
21
constant bit_width: integer:= integer(ceil(log2(real(n+1))));
22
signal present_counter, next_counter : unsigned(bit_width-1 down to 0);
23
24
begin
25
26
Output_logic : count_out <= present_counter;
27
28
Next_state_logic : process(present_counter)
29
begin
30
    if present_counter = 0 then
31
        next_counter <= n-1;
32
    else
33
        next_counter <= present_counter - 1;
34
    end if;
35
end process;
36
37
Registers : process(reset, clk)
38
begin
39
    if reset = '1' then
40
        present_counter <= n-1;
41
    elsif rising_edge(clk) then
42
            present_counter <= next_counter;
43
    end if;
44
end process;
45
46
end behavioral;

Mein Problem nun: Bei meiner next_state_logic will ich ja sagen, dass 
falls der aktuelle Wert 0 ist, er auf n-1 springen soll. Aber kann ich 
das einfach mit n-1 zuweisen? Es scheint mir ein bisschen komisch, weil 
n ja ein Integer ist und mein next_counter ein unsigned ist.

Wie gehe ich hier am besten vor?

: Bearbeitet durch Moderator
von Duke Scarring (Gast)


Lesenswert?

teciu schrieb:
> Aber kann ich
> das einfach mit n-1 zuweisen?
Mit to_unsigned sollte die Zuweisung klappen:
1
    next_counter <= to_unsigned( n-1, bit_width);

Wie lautet denn die Fehlermeldung des Simulators?

Hier sind die Umwandlungsfunktionen vorbildlich erläutert:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

Duke

von Markus F. (mfro)


Lesenswert?

Warum machst Du das "n"-Generic nicht auch gleich unsigned?

Wenn Du tatsächlich einen unsigned Zähler haben willst, sollte der 
Startwert doch auch unsigned (oder wenigstens natural) sein. Damit 
würdest Du dir eine Typumwandlung sparen (und gleich noch die - 
zumindest theoretische - Fehlerquelle, dass einer deine Entity mit einem 
negativen Startwert instantiiert).

von Vancouver (Gast)


Lesenswert?

Waumr Zähler nicht einfach als Integer oder Natural?

von Mulen (Gast)


Lesenswert?

Der Aufbau ist generell komplizierter als notwendig. Das könnte man 
übersichtlicher in einem Prozess machen:
1
process(clk,reset)
2
begin
3
    if reset='1' then
4
        count <= to_unsigned(n-1, bit_width);
5
    elsif(rising_edge(clk))then
6
        if count = to_unsigned(0, bit_width)then
7
            count <= to_unsigned(n-1, bit_width);
8
        else
9
            count <= count - '1';
10
        end if;
11
    end if;
12
end;

Wenn du diese "next logic" magst, dann würde ich die 2-Prozess-Methode 
mal ansehen.

von teciu (Gast)


Lesenswert?

Liebe alle, vielen Dank für eure Inputs!
Nun zur Erklärung: Ich schreibe demnächst eine Prüfung in VHDL und ich 
möchte mich gut darauf vorbereiten. Wir haben einen ganzen Katalog mit 
Aufgabenstellungen erhalten - ohne Lösungen - und ich versuche jetzt ein 
paar von diesen zu lösen. Ich habe leider auch keine Simulator. Ich 
mache es einfach schriftlich für mich um zu sehen, ob ich die Thematik 
verstanden habe. :) Und ich bin sehr froh um eure Unterstützung.

Jetzt zurück zum Beispiel.
Die Schnittstellen wurden vorgegeben. Sprich clk und rst als std_ulogic 
und count_out als std_ulogic_vector. Beim Rest bin ich frei. Ich soll 
einzig einen parametrisierbaren modulo-n down-counter machen.

@Mulen deine Lösung gefällt mir gut! Ich dachte es wäre übersichtlicher 
mit der next_state_logic. Aber ich habe mich wohl geirrt.
Nun das heisst ich würde meine Code wie folgt anpassen:
1
entity mod_n_counter is
2
3
generic(
4
    n : integer := 255;
5
);
6
port(
7
    clk       : in  std_ulogic;
8
    reset      : in  std_ulogic;
9
    count_out : out std_ulogic_vector(integer(ceil(log2(real(n+1))))-1 
10
down to 0);
11
);
12
end mod_n_counter;
13
14
15
architecture behavioral of mod_n_counter is
16
17
constant bit_width: integer:= integer(ceil(log2(real(n+1))));
18
signal count : unsigned(bit_width-1 down to 0);
19
20
21
process(clk,reset)
22
begin
23
    if reset='1' then
24
        count <= to_unsigned(n-1, bit_width);
25
    elsif(rising_edge(clk))then
26
        if count = to_unsigned(0, bit_width)then
27
            count <= to_unsigned(n-1, bit_width);
28
        else
29
            count <= count - '1';
30
        end if;
31
    end if;
32
33
count_out = std_ulogic_vector(count);
34
35
end behavioral;


Wäre das so richtig?


Wenn ich jetzt aber meinen Code nehmen würde und einfach das n als 
unsigned deklarieren würde, wir müsste ich da vorgehen? Weil ich ja 
nicht weiss, was mein n ist. Also ich würde etwas wie generic (n:= 
unsigned(???))

Entschuldigt, ich bin wirklich fleissig am lernen und möchte es gerne 
verstehen. Sorry wenn immer noch ein bisschen Mühe habe.

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


Lesenswert?

teciu schrieb:
> Ich habe leider auch keine Simulator.
Heutzutage kein Problem, solange man einen Browser hat:
https://www.edaplayground.com

> Wir haben einen ganzen Katalog mit Aufgabenstellungen erhalten...
> Die Schnittstellen wurden vorgegeben. Sprich
> clk und rst als std_ulogic und count_out als std_ulogic_vector.
Als unconstrained vector ohne definierte Breite?
Mein Vorschlag: lass doch einfach mal die Aufgabe sehen.
Wenn man nur die Lösungsansätze sieht, muss man sich die Aufgabe 
irgendwie erraten. Das ist umständlich...

von teciu (Gast)


Angehängte Dateien:

Lesenswert?

Ok :) Hier habe ich die Aufgabe angehängt!

von Duke Scarring (Gast)


Lesenswert?

teciu schrieb:
> Ich habe leider auch keine Simulator.
Aber Internetzugang, oder?

Da dürfte das hier weiterhelfen:
https://www.edaplayground.com/

Duke

von Duke Scarring (Gast)


Lesenswert?

Hmm. Zu knapp gelesen, Lothar war schneller (wie so oft :-)

von berndl (Gast)


Lesenswert?

teciu schrieb:
> Ok :) Hier habe ich die Aufgabe angehängt!

dann frag' mal denjenigen, der dir die Aufgabe gestellt hat, ob der 
Reset auch asynchron deaktiviert wird. Und ueberleg' dir mal, was dann 
passieren kann...

von teciu (Gast)


Lesenswert?

Das steht jetzt gar nicht und ich denke, das wäre zu umfangreich. 
Einizige Bedingungen sind eben, dass er bei n-1 beginnt, bis 0 runter 
zählt und dann wieder bei n-1 beginnt. Oder eben, nei rst auch wieder 
zurück zu n-1.

von teciu (Gast)


Lesenswert?

Mag vielleicht jemand meinen Vorschlag anschauen? (Post bisschen höher 
oben)

:-) Danke!!

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


Lesenswert?

teciu schrieb:
> Mag vielleicht jemand meinen Vorschlag anschauen?
Passt konzeptionell soweit.
Nach dem Entfernen einiger Syntaxfehler wie z.b. "down to" und -1 statt 
-'1' sowie dem Einfügen des eines "begin" für die Architecture und eines 
"end process" geht die Beschreibung durch den Compiler und ergibt das 
gewünschte Verhalten.

Aber einfacher und übersichtlicher wäre es (wie schon erwähnt) mit einem 
integer als Zähler:
1
library IEEE;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
use ieee.math_real.all;
5
6
entity mod_n_counter is
7
   generic(
8
      n : integer := 255
9
   );
10
   port(
11
      clk       : in  std_ulogic;
12
      reset      : in  std_ulogic;
13
      count_out : out std_ulogic_vector(integer(ceil(log2(real(n+1))))-1 downto 0)
14
   );
15
end mod_n_counter;
16
17
architecture behavioral of mod_n_counter is
18
   constant bit_width: integer:= integer(ceil(log2(real(n+1))));
19
   signal count : integer range 0 to n-1;
20
begin
21
22
   process (clk,reset)
23
   begin
24
      if reset='1' then
25
         count <= n-1;
26
      elsif(rising_edge(clk))then
27
         if count = 0 then  count <= n-1;
28
         else               count <= count-1;
29
         end if;
30
      end if;
31
   end process;
32
   
33
   count_out <= std_ulogic_vector(to_unsigned(count,bit_width));
34
  
35
end behavioral;

BTW: bitte VHDL-Code mit den [vhdl] Tags formatieren. Wie das geht ist 
in der Anleitung über jeder Eingabebox zu finden...

: Bearbeitet durch Moderator
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.