Counter VHDL

Gast #5522543
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?
#5522882
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).
Gast #5523108
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.
Gast #5523421
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.
Moderator (Firma: Titel) Persönliche Seite #5523694
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...
Gast #5524524
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.
Moderator (Firma: Titel) Persönliche Seite #5530853
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren