Hallo,
ich versuche eine Operation wie diese in HW zu giessen:
n = n + 1
wobei n vom Typ std_logic_vector(4 downto 0) wäre.
Jetzt habe ich schon festgestellt dass für Zählen in HW Flipflops
benötigt werden. D.h. ich müsstse den Zustand verschiedener Signale
definieren, um einen Zählvorgang zu beschreiben.
1) Ich brauch FlipFlops - wo liegt der Unterschied ob ich D oder JK
Flipflops hernehme?
2) In einem alten Datasheet ist die Schaltung mit JK FF implementiert,
und vornedran werden auf dem D Signal ein paar Signale verodert und
verundet - wie ist dieser "Selekter" zu verstehen?
Besten Dank für eine kleine Starthilfe bei der Aufgabe, den Zähler zu
bauen.
JK-FFs sind aus dem Pleistozän der Digitaltechnik. Heute werden nur noch
D-FFs verwendet. Die Funktion ist denkbar einfach: Der Wert am D-Eingang
wird mit der aktiven Taktflanke an den Ausgang Q übernommen.
Für den Zähler überleg jetzt mal, wie du von einem Zählerstand zum
nächsten kommst, daraus ergibt sich die Schaltung praktisch von selbst.
Vorneweg: ich kann kein VHDL.
Patrick M. schrieb:> 1) Ich brauch FlipFlops - wo liegt der Unterschied ob ich D oder JK> Flipflops hernehme?
Mit JK-FF hast du mehr Möglichkeiten. Im Prinzip kannst du aber beide
nehmen. Mit welcher Variante du einfacher wegkommst, hängt auch davon
ab, ob du einen synchronen oder einen asynchronen Zähler bauen willst.
Beim synchronen ist meiner Erinnerung nach der Aufwand beim
Bereitstellen der richtigen JK-Signale einfacher.
> 2) In einem alten Datasheet ist die Schaltung mit JK FF implementiert,> und vornedran werden auf dem D Signal ein paar Signale verodert und> verundet - wie ist dieser "Selekter" zu verstehen?
Daran siehst du, was für ein Aufwand getrieben wird, um aus einem JK-FF
ein D-FF zu machen. Die Gatter sind einfach notwendig, um das korrekte
D-Signal, das ja bei einem Zähler auch abhängig vom FF-Ausgang ist,
richtig zu generieren.
Schau dir doch einfach mal in den Datenblättern die Wirkung von JK- bzw.
D-Signalen auf das Schalten von FFs an.
Moin,
Patrick M. schrieb:> 1) Ich brauch FlipFlops - wo liegt der Unterschied ob ich D oder JK> Flipflops hernehme?
Bei D-Flipflops brauchst du 5 Schaltnetze mit jeweils 5 Eingaengen und
einem Ausgang, bei denen gibt es aber keine don't care Kombinationen.
Bei JK-Flipflops brauchst du 10 Schaltnetze mit jeweils 5 Eingaengen und
einem Ausgang, da werden aber "don't care" Kombinationen auftauchen,
d.h. wahrscheinlich werden die "einfacher" ausfallen. Dafuer halt
doppelt so viele.
Gruss
WK
Patrick M. schrieb:> Jetzt habe ich schon festgestellt dass für Zählen in HW Flipflops> benötigt werden. D.h. ich müsstse den Zustand verschiedener Signale> definieren, um einen Zählvorgang zu beschreiben.
Wenn Du digitale Schaltungstechnik lernen möchtest, ist das der richtige
Ansatz. Wenn Du VHDL lernen möchtest, eher nicht. Da heißt das:
Patrick M. schrieb:> Jetzt habe ich schon festgestellt dass für Zählen in HW Flipflops> benötigt werden.
Du kannst mit VHDL zwar JK-Flipflops beschreiben. Du kannst sie aber
nicht in FPGAs einbauen, weil es dort keine gibt.
> 1) Ich brauch FlipFlops - wo liegt der Unterschied ob ich D oder JK> Flipflops hernehme?
Wenn du mit deiner Beschreibung auf ein FPGS oder ein CPLD willst, dann
musst du D-Flipflops nehmen. Denn nur solche hast du auf dieser
Zielplattform zur Verfügung.
Oder andersrum: du kannst zwar irgendwas mit 50mm langen Schrauben auf
ein Blatt Papier zeichnen. Wenn du in deiner Kiste aber nur 30mm lange
Schrauben hast, dann kannst du es nicht wie gewünscht aufbauen.
> D.h. ich müsstse den Zustand verschiedener Signale definieren, um einen> Zählvorgang zu beschreiben.
Nein, in VHDL nimmst du einfach den '+' Operator um einen Zählvorgang zu
beschreiben. Natürlich kannst du auch deine eigene Zählerfortschaltlogik
machen, aber die ist trotzdem sicher langsamer als das simple '+'
Zeichen. Markus F. schrieb:> Die Tools erledigen den Rest für dich.
Denn mit einem '+' kann der Synthesizer umgehen und die
Addierer-Strukturen im FPGA verwenden. Eine selbst handgestrickte Logic
setzt er aber umständlich in LUTs und Verdrahtung um.
Huer noch die Lösung mit dem Prozess:
Lothar M. schrieb:> Nein, in VHDL nimmst du einfach den '+' Operator um einen Zählvorgang zu> beschreiben. Natürlich kannst du auch deine eigene Zählerfortschaltlogik> machen, aber die ist trotzdem sicher langsamer als das simple '+'
die Carry-Chain Lowlevel Primitive kann man auch "per Hand" bedienen
(langsamer ist der "handgestrickte" Zähler also nicht notwendigerweise).
Aber warum sollte man das tun, wenn's ein einfaches "+" auch tut?
Vielen Dank für eure Hilfe. Verstehe, die Flipflops explizit für einen
Counter im VHDL zu beschreiben ist nicht nötig. Dann lasse ich die mal
in der Schublade (oder auf dem Blatt Papier für andere Projekte) und
konzentriere mich ganz auf einen Counter durch '+'
Mein Versuch aktuell sieht so aus:
VHDL für den Counter:
Und eine erste Testbench, die nur versucht den Zählvorgang zu triggern:
1
libraryieee;
2
3
useieee.std_logic_1164.all;
4
5
6
entitytbisbegin
7
end;
8
9
10
11
architecturetb_behavoftbis
12
13
componentCounterisport(
14
clk:instd_logic;-- clock
15
Q:outstd_logic_vector(3downto0);
16
TC:outstd_logic-- Terminal Count
17
);
18
endcomponent;
19
20
signaltb_CLK:std_logic:='0';
21
signaltb_Q:std_logic_vector(3downto0):="0000";
22
signaltb_TC:std_logic:='0';
23
24
25
begin
26
27
dut:Counterportmap(
28
clk=>tb_clk,
29
Q=>tb_Q,
30
TC=>tb_TC
31
);
32
33
clk_proc:processbegin
34
35
CLK<=notCLK;
36
waitfor5ns;
37
38
ifNOW>200nsthen
39
wait;
40
endif;
41
endprocessclk_proc;
42
43
stim_proc:processbegin
44
45
46
waitfor80ns;
47
48
wait;
49
50
endprocess;
51
52
endarchitecturetb_behav;
Mit Ghdl --std=08 analyze und elaborate bekome ich die Waveform wie im
Anhang. Leider sehe ich noch keinen Effekt vom '+' im Q bus. Bin nun
etwas verwirrt....
Tipp: welchen Wert hat q (in der Entity) beim Start?
und welchen Wert hat es, wenn man 1 auf diesen Wert aufaddiert?
Willkommen in der Welt der 5-wertigen Logik.
Ja, der Groschen ist gefallen. Danke.
Ich habe ein Reset Signal eingefügt mit dem q <= "0000" gesetzt werden
kann.
Zuerst dachte ich der reset sei über ein VHDL Konstrukt q := "0000"
möglich. Ein extra Signal zum Reset sieht sauberer aus.
Patrick M. schrieb:> Ich dachte der reset wäre über ein VHDL Konstrukt := "0000" möglich.
Man kann Initialwerte für Signale so vorgeben.
Aber eben nicht von der Testbench auf einen Ausgang des Prüflings! Du
musst den Initwert im Modul vorgeben. In deinem Fall müsste das so
aussehen:
1
entityCounterisport(
2
:
3
q:outstd_logic_vector(3downto0):="0000";
4
:
5
);
Aaaaaber:
Patrick M. schrieb:> q: out std_logic_vector(3 downto 0);> q <= std_logic_vector(unsigned(q) + 1) when rising_edge(clk);
Da kloppt dir hoffentlich der Synthesizer auf die Finger. Denn einen
output Port kann man nicht lesen. Nimm ein lokales Signal zum Zählen und
weise das dann dem Ausgang zu. Denn der schreibfaule Stil mit einem
zurückgelesenen ouput oder buffer im Port ist halt nur faul. Keineswegs
etwa schlau oder elegant.
Patrick M. schrieb:> Der Reset sieht sauberer aus.
Ein Initwert ist auch vollkommen sauber, wenn man weiß, wo er hingehört.
Für deinen Zähler würde ich einen unsigned Vektor zum zählen nehmen und
dann den Zählerwert auf den Ausgang konvertieren und somit so schreiben:
1
LIBRARYieee;
2
USEieee.std_logic_1164.ALL;
3
USEieee.numeric_std.ALL;
4
5
entityCounterisport(
6
clk:instd_logic;-- clock
7
-- ... mehr controls kommen spaeter
8
q:outstd_logic_vector(3downto0);
9
TC:outstd_logic-- trickle, carry out oder so
10
);
11
endCounter;
12
13
architecturearcofCounteris
14
signalcnt:unsigned(3downto0):=(others=>'0');
15
begin
16
17
cnt<=cnt+1whenrising_edge(clk);
18
19
q<=std_logic_vector(cnt);
20
21
endarchitecturearc;
Hier noch ein paar Lösungen auf die Fragen, die
Markus F. schrieb:> Tipp: welchen Wert hat q (in der Entity) beim Start?
Es hat den "linkesten" Wert seiner Deklaration. Bei einem std_logic ist
das U für "Uninitialized".
https://www.cs.sfu.ca/~ggbaker/reference/std_logic/1164/std_logic.html> und welchen Wert hat es, wenn man 1 auf diesen Wert aufaddiert?
Die Auflösungstabelle resolution_table gibt für 'U' mit irgendwas
anderem wieder 'U' aus.
https://vhdlwhiz.com/std_logic-vs-std_ulogic/> Willkommen in der Welt der 5-wertigen Logik.
Ein std_logic ist neunwertig.... ;-)
Lothar M. schrieb:> Da kloppt dir hoffentlich der Synthesizer auf die Finger. Denn einen> output Port kann man nicht lesen.VHDL 2008 (das der TO offensichtlich benutzt) erlaubt das (und ich
find's gut)
Lothar M. schrieb:> Markus F. schrieb:>> Tipp: welchen Wert hat q (in der Entity) beim Start?> Es hat den "linkesten" Wert seiner Deklaration. Bei einem std_logic ist> das U für "Uninitialized".> https://www.cs.sfu.ca/~ggbaker/reference/std_logic/1164/std_logic.html>
Das ist richtig.
>> und welchen Wert hat es, wenn man 1 auf diesen Wert aufaddiert?> Die Auflösungstabelle resolution_table gibt für 'U' mit irgendwas> anderem wieder 'U' aus.> https://vhdlwhiz.com/std_logic-vs-std_ulogic/
... nicht richtig:
"UUU" + 1 ergibt unmittelbar "XXX"
numeric_std-Funktionen ("+" ist eine) weisen sofort (ohne Meldung) "X"
zu, wenn ihnen irgendwas seltsam vorkommt...
>> Willkommen in der Welt der 5-wertigen Logik.> Ein std_logic ist neunwertig.... ;-)
Stimmt. Von den Neunen hab' ich einfach mal vier ignoriert, weil sie in
freier Wildbahn praktisch nie vorkommen...
Lothar M. schrieb:> begin>> q <= cnt+1 when rising_edge(clk);>> q <= std_logic_vector(cnt);>> end architecture arc ;
Das sollte doch bestimmt so aussehen:
cnt <= cnt+1 when rising_edge(clk);
q <= std_logic_vector(cnt);
Helmut S. schrieb:> Das sollte doch bestimmt so aussehen:
Ja, latürnich, danke. Habs korrigiert... ;-)
Markus F. schrieb:> "UUU" + 1 ergibt unmittelbar "XXX"> numeric_std-Funktionen ("+" ist eine)
Stimmt, da kommt die Auflösungstabelle gar nicht zur Wirkung:
L01:=TO_01(RESIZE(L,SIZE),'X');-- von hier kommt das X
10
if(L01(L01'left)='X')thenreturnL01;endif;
11
R01:=TO_01(RESIZE(R,SIZE),'X');-- und von hier
12
if(R01(R01'left)='X')thenreturnR01;endif;
13
returnADD_UNSIGNED(L01,R01,'0');
14
end;
15
:
Aus https://www.csee.umbc.edu/portal/help/VHDL/packages/numeric_std.vhdMarkus F. schrieb:> VHDL 2008 (das der TO offensichtlich benutzt) erlaubt das
Der Verdacht mit VHDL2008 liegt nahe.
> (und ich find's gut)
Naja, es bringt eben genau solche unnötige Verwirrung ins Spiel, dass
für manche Ports in der Portdeklaration Intitialwerte angegeben werden
können (für diejenigen eben, die speichern können). Und das führt
garantiert zu Verwirrungen.
Ich deklariere lokale Signale, belege sie mit Initwerten (wenn nötig),
rechne mit ihnen, und weise sie zum Schluss an Ports nach aussen zu
(wenn nötig). Immer alles gleich und geradlinig... ;-)
Vancouver schrieb:> JK-FFs sind aus dem Pleistozän der Digitaltechnik. Heute werden nur noch> D-FFs verwendet.
Das ist natürlich völliger Quatsch. JK ist viel flexibler als
D-Flipflop. Beim JK-FF bestimmt der Logikpegel an den JK-Eingängen wie
der dem Taktimpuls folgende Ausgangszustand aussieht. Da es i.d.R. immer
mehrere AND oder NAND verknüpfte Eingänge gibt spart das meist auch noch
zusätzliche Gatter.
Synchronzähler z.B. lassen sich nur mit JK-FF realisieren.
@TO
Wenn Du was über Flipflop Schaltungstechnik lernen möchtest, dann
empfehle ich Dir Kühn/Schmied "Handbuch integrierte Schaltkreise". Das
Buch war seinerzeit der Tietze/Schenk der TTL-Schaltkreistechnik. Auch
wenn TTL-Schaltkreise schon lange überholt sind, aber die Grundlagen
logischer Schaltkreise und Schaltungen gelten nach wie vor. Genau
deshalb kann ich Dir dieses Buch nur wärmsten empfehlen. Danach sollte
die Implementation eines Zählers in VHDL nur noch ein Kinderspiel sein.
Das Buch beschreibt auch wie man so ein FF aus Gattern aufbauen kann.
Ebenso werden verschiedene Zähler und Codecs behandelt. Alles mit
Standardgattern, JK-FF und auch D-FF. Bestimmte Sachen gehen aber eben
nur mit JK-FF.
Zeno schrieb:> JK ist viel flexibler als> D-Flipflop.
Dann erklär uns doch mal, ws man mit einem JK-FF machen kann, was mit
einem D-FF nicht geht.
Zeno schrieb:> Beim JK-FF bestimmt der Logikpegel an den JK-Eingängen wie> der dem Taktimpuls folgende Ausgangszustand aussieht.
Beim D-FF bestimmt der Logikpegel am D-Eingang, wie der dem Taktimpuls
folgende Ausgangszustand aussieht. Und?
Zeno schrieb:> Da es i.d.R. immer> mehrere AND oder NAND verknüpfte Eingänge gibt spart das meist auch noch> zusätzliche Gatter.
... die dann dafür im JK-FF drinstecken.
Zeno schrieb:> Synchronzähler z.B. lassen sich nur mit JK-FF realisieren.
Also das ist völliger Quatsch. Die oben beschriebene
Zählerimplementierung ist synchron, weil alle D-FFs den gleichen Takt
bekommen, und selbst asynchrone Zähler sind einfacher mit D-FFs zu bauen
- ganz ohne zusätzliche Gatter.
Ich kenne keine FPGAs und keine ASIC-Standardzellenbibliothek, in der
noch JK-FFs verfügbar sind (weiß jemand, ob es sowas gibt?)
Wenn man entsprechend masochistisch veranlagt ist, kann man natürlich in
VHDL oder Verilog ein JK-FF definieren und dann daraus einen Zähler oder
eine Statemachine bauen (ich will gar nicht darüber nachdenken, wie der
Code aussähe...), aber die Logiksynthese wird den den ganzen
Gatterverhau optimieren und wieder D-FFs daraus machen.
JK-FFs werden heute nur noch verwendet, um Informatiker im ersten
Semster zum Nachdenken anzuregen (was zugegeben nicht das Schlechteste
ist), aber ansonsten sind die weg vom Fenster.