Forum: FPGA, VHDL & Co. 4bit ladbarer Zähler


von Matthias H. (prahlehans)


Lesenswert?

Hey, also ich will sowas machen, wie einen 4 bit Zähler, bei dem man 
anfangs einstellen kann, bei welchem Startwert er beginnen soll. Achso, 
muss dazu sagen, ich arbeite mit Quartus II 9.0 sp2. Ich hab dort ein 
Problem bei der Simulation damit. Denn, sobald die clk das erste mal 1 
annimmt, wird mein IN-Port auf 0 gesetzt. Wie kann das zu so einer 
Reaktion kommen? Ich meine, wie kann die clk in der architecture 
Einfluss auf den Port nehmen? Ich poste mal meinen bisherigen code.
1
library ieee;
2
use ieee.std_logic_1164.all,
3
  ieee.numeric_std.all;
4
5
entity counter is
6
port (  start : in std_logic_vector(3 downto 0);
7
    clk,reset: in std_logic;
8
    output: out std_logic_vector(6 downto 0)
9
    );
10
end counter;
11
12
architecture logik of counter is
13
  signal result_next: std_logic_vector(3 downto 0);
14
  signal result_reg: std_logic_vector(3 downto 0) := start;
15
begin
16
  result_next <= std_logic_vector(unsigned(result_reg) + 1);    
17
  count: process(clk,reset)
18
    begin if reset = '1' then result_reg <= start;
19
      elsif (clk'event and clk = '1') then result_reg <= result_next;
20
      end if;
21
    end process;  
22
  ausgabe: entity work.count_muxer(logik) port map (input=>result_next,segment=>output);
23
  
24
end logik;

Achso, noch dazu: das Ergebnis soll auf nem 7-Segmenter in hex 
ausgegeben werden. Deswegen hat der Output nur 7 bits. Und diesen 
count_muxer braucht ihr glaub ich nich beachten. Der setzt einfach nur 
die Ausgaben auf dem 7-Segmenter.

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

Matthias Hanske schrieb:

>
1
> 
2
> entity counter is
3
> port (  start : in std_logic_vector(3 downto 0);
4
5
...
6
7
>   signal result_reg: std_logic_vector(3 downto 0) := start;
8
>

Die Initialisierung eines Signals mit dem Wert eines Eingangssignals ist 
nicht gerade sinnvoll.

Tom

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


Lesenswert?

>   signal result_reg: std_logic_vector(3 downto 0) := start;
So geht das nicht, weil zum Synthesezeitpunkt start nicht bekannt 
ist...
An dieser Stelle kann für die Synthese nur eine Konstante angegeben 
werden. Und zwar deshalb, weil zum Initialisierungszeitpunkt 
(Einschalten) das Signal start auch noch nicht bekannt ist (das ginge 
bestenfalls über ein Generic, aber das ist auch wieder "nur" eine 
Konstante).

BTW:
Du solltest das Laden des Werts synchron machen:
1
:
2
architecture logik of counter is
3
  signal result_reg: std_logic_vector(3 downto 0) := "0000"; -- hier gehen in der Realitiät nur Konstanten
4
begin
5
  count: process(clk) begin 
6
      if (clk'event and clk = '1') then 
7
         result_reg <= std_logic_vector(unsigned(result_reg) + 1);
8
         if reset = '1' then 
9
            result_reg <= start; 
10
         end if;
11
      end if;
12
  end process;  
13
:

> Denn, sobald die clk das erste mal 1 annimmt,
> wird mein IN-Port auf 0 gesetzt.
Das ist nicht so kritisch. Denn in der Realität wird dein Clock ein 
paar mal kommen, bis du endlich alles initialisiert hast und loslegst...

von Matthias H. (prahlehans)


Lesenswert?

Naja. wenn ich aber  "0000" setze, dann isses ja nur ein stinknormaler 
Zähler. Der soll ja grade bei start anfangen zu zählen.

>> Denn, sobald die clk das erste mal 1 annimmt,
>> wird mein IN-Port auf 0 gesetzt.
>Das ist nicht so kritisch.

Hmm. vllt doch, denn ich weiß noch nicht so genau, ob später beim reset 
auf "0000" gesetzt werden soll, oder auf start.

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


Lesenswert?

> Hmm. vllt doch, denn ich weiß noch nicht so genau, ob später beim reset
> auf "0000" gesetzt werden soll, oder auf start.
Dann braucht du eben ein load und ein reset Signal.

von Matthias H. (prahlehans)


Lesenswert?

Zu deinem Quelltext oben. Das is doch ein wenig unlogisch, da doch das 
reset asynchron kommen kann. Also darf das reset doch nicht von der clk 
abhängig sein. Das würde ja bedeuten, dass das reset auch nur synchron 
auftreten kann.

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


Lesenswert?

> Das würde ja bedeuten, dass das reset auch nur synchron auftreten kann.
Besser wäre das wirklich...
Denn wenn dein Reset wirklich asynchron kommen kann, dann kann er auch 
asynchron wieder weggehen. Und dann wird es kritisch, denn der geht 
garantiert nicht bei jedem Zählerflipflop gleichzeitig weg. Was dann 
passieren kann, das kannst du dir ohne Probleme selber denken   :-o

Zum heissen Thema Reset gibts auch was im 
Beitrag "Xilinx und die Resets"

von Matthias H. (prahlehans)


Lesenswert?

So, ich hab jetz zwarr nochwas verändert, aber das Verhalten beim 
simulieren hat sich trotzdem nicht verändert...Was mach ich nur falsch? 
Im Prozess soll das Verhalten erstmal vom Reset abhängig sein, dann, 
falls ein load-Signal kommt, der counter auf meinen Eingangs-start 
gesetzt werden und gar nicht weiterzählen, und erst dann, soll bei 
steigender Taktflanke hoch gezählt werden...Aber es passiert im Ausgang 
gar nix...Hier nochmal mein Text
1
library ieee;
2
use ieee.std_logic_1164.all,
3
  ieee.numeric_std.all;
4
5
entity counter is
6
port (  start : in std_logic_vector(3 downto 0);
7
    clk,reset,load: in std_logic;
8
    output: out std_logic_vector(6 downto 0)
9
    );
10
end counter;
11
12
architecture logik of counter is
13
  signal result_next: std_logic_vector(3 downto 0);
14
  signal result_reg: std_logic_vector(3 downto 0);
15
begin
16
  
17
  result_next <= std_logic_vector(unsigned(result_reg) + 1);    
18
  count: process(clk,reset)
19
    begin if reset = '1' then result_reg <= (others=>'0');
20
      elsif load = '1' then result_reg <= start;
21
      elsif (clk'event and clk = '1') then result_reg <= result_next;
22
      end if;
23
    end process;  
24
  ausgabe: entity work.count_muxer(logik) port map (input=>result_next,segment=>output);
25
  
26
end logik;

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


Lesenswert?

> Was mach ich nur falsch?
Du bist offenbar lernresistent  :-/
Hast du meine Beiträge ernsthaft angesehen und verstanden?

> dann, falls ein load-Signal kommt, der counter auf meinen
> Eingangs-start gesetzt werden
Mal abgesehen davon, dass dein Quelltext (immer noch) unschön formatiert 
ist, ist die Sensitivliste unvollständig. Eine Änderung von load bewirkt 
bei der Simulation daher nichts:
1
  count: process(clk,reset) begin -- hier fehlt load

Damit beschreibst du einen asynchron setz- und ladbaren Zähler:
1
      if reset = '1' then 
2
         result_reg <= (others=>'0');
3
      elsif load = '1' then 
4
         result_reg <= start;
5
      elsif (clk'event and clk = '1') then 
6
         result_reg <= result_next;
7
      end if;
8
    end process;
Können deine FFs im FPGA sowas überhaupt?
Bei Xilinx gibt es sowas nicht.
Hast du dir mal das Syntheseergebnis im RTL-Viewer angesehen?

Um mich selber zu zitieren:
> Du solltest das Laden des Werts synchron machen:
1
:
2
architecture logik of counter is
3
  signal result_reg: std_logic_vector(3 downto 0) := "0000"; 
4
begin
5
  count: process(clk) begin -- diese Sensitivliste ist vollständig, weil der Prozess auf clk synchron ist
6
      if (clk'event and clk = '1') then 
7
         if reset = '1' then 
8
            result_reg <= "0000"; 
9
         elsif load = '1' then 
10
            result_reg <= start; 
11
         else
12
            result_reg <= std_logic_vector(unsigned(result_reg) + 1);
13
         end if;
14
      end if;
15
  end process;  
16
:

BTW:
>  signal result_next: std_logic_vector(3 downto 0);
>  signal result_reg: std_logic_vector(3 downto 0);
Warum verwendest du sogar für so einen blödsinnig einfachen Zähler die 
getrennte Takt-Zustands-Schreibweise?

Sieh dir meinen Code an, simuliere und verstehe ihn.

von Matthias H. (prahlehans)


Lesenswert?

> Damit beschreibst du einen asynchron setz- und ladbaren Zähler:

Na laut meiner Aufgabenstellung soll es ein synchroner Zähler mit 
asynchronem Reset sein...Deswegen vorhin mein Einwand. Irgendwie war 
auch in der Vorgabe so ein Beispiel von nem stinknormalen Zähler. Da 
haben die auch Takt-Zustandssteuerung gemacht und den reset haben die 
auch so gemacht wie ich ihn hatte.


> Hast du dir mal das Syntheseergebnis im RTL-Viewer angesehen?
Ich hab nur mit ModelSim simuliert.


>Du bist offenbar lernresistent  :-/
Nun ja...Es ist halt so, dass ich seit vllt 2 Wochen erst mit VHDL in 
Kontakt geraten bin und daher komplexere Sachen nich auf Anhieb 
verstehe. Bisher hatten wir auch nur so einfache Sachen wie einen Muxer, 
arithmetischen Shifter...Das war noch simpel. Für dich is das hier vllt 
auch ein Klacks, nur ich hatte vorher noch nie mit sowas zu tun.

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


Lesenswert?

Matthias Hanske schrieb:
> Na laut meiner Aufgabenstellung soll es ein synchroner Zähler mit
> asynchronem Reset sein...Deswegen vorhin mein Einwand. Irgendwie war
> auch in der Vorgabe so ein Beispiel von nem stinknormalen Zähler. Da
> haben die auch Takt-Zustandssteuerung gemacht und den reset haben die
> auch so gemacht wie ich ihn hatte.
Na gut, dann mach den Reset asynchron (wobei das bestenfalls 
"suboptimal" zu nennen ist), aber halte wenigstens das Setzen synchron.
1
architecture logik of counter is
2
  signal result_reg: std_logic_vector(3 downto 0) := "0000"; 
3
begin
4
  count: process(clk,reset) begin 
5
      if reset = '1' then 
6
         result_reg <= "0000"; 
7
      elsif (clk'event and clk = '1') then 
8
         if load = '1' then 
9
            result_reg <= start; 
10
         else
11
            result_reg <= std_logic_vector(unsigned(result_reg) + 1);
12
         end if;
13
      end if;
14
  end process;
Aber das mit der Takt-Zustands-Beschreibung bei einem Zähler ist 
ungewöhnlich bis unübersichtlich...
BTW:
Ich würde für das Zählersignal einen integer range 0 to 15 verwenden und 
das Eingangssignal start sowie das Ausgangssignal output 
entsprechend umwandeln.

>> Hast du dir mal das Syntheseergebnis im RTL-Viewer angesehen?
> Ich hab nur mit ModelSim simuliert.
Du kannst ohne weiteres dein Design (nach Erweiterung der Sensitivliste 
um das fehlende load) simulieren. Aber in der Hardware wird dann an 
die asynchronen Set- und Reset-Eingänge der FF Kombinatorik eingebaut. 
Und Kombinatorik im asynchronen Resetpfad (genauso wie im Setpfad) ist 
unberechenbar...
Denn der load kann ja asynchron kommen und gehen wie er will. Was, 
wenn dann 2 deiner Zähler-FF noch ein aktives load Signal sehen, die 
anderen beiden nicht mehr? Siehe dazu: 
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html

von Matthias H. (prahlehans)


Lesenswert?

> Na gut, dann mach den Reset asynchron (wobei das bestenfalls
> "suboptimal" zu nennen ist), aber halte wenigstens das Setzen synchron.
Aye Sir :)
> BTW:
> Ich würde für das Zählersignal einen integer range 0 to 15 verwenden und
> das Eingangssignal start sowie das Ausgangssignal /output/
> entsprechend umwandeln.
Das dürfen wir nicht machen, da wir das in den vorangegangenen Laboren 
auch nicht hatten. Wir sollen nur das verwenden, was auch bisher auf den 
Übungen vorkam und auf dem jetzigen vorkommt. Wer weiß, vielleicht haben 
wir im nächsten Labor mehr Spielraum. Aber meine Wave dazu sieht jetzt 
erstmal ordentlich aus.

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.