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.
:
Bearbeitet durch User
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:
1 | n <= std_logic_vector(unsigned(n) + 1) when rising_edge(clk); |
oder eben in einem Prozess, wenn dir das lieber ist. Die Tools erledigen den Rest für dich.
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:
1 | process begin |
2 | wait until rising_edge(clk); |
3 | n <= n+1; -- verwendet die flotte Carrychain |
4 | end process; |
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:
1 | LIBRARY ieee; |
2 | |
3 | USE ieee.std_logic_1164.ALL; |
4 | USE ieee.numeric_std.ALL; |
5 | |
6 | entity Counter is port ( |
7 | clk: in std_logic; -- clock |
8 | -- ... mehr controls kommen spaeter
|
9 | q: out std_logic_vector(3 downto 0); |
10 | TC: out std_logic -- trickle, carry out oder so |
11 | );
|
12 | end Counter; |
13 | |
14 | |
15 | architecture arc of Counter is |
16 | |
17 | |
18 | begin
|
19 | |
20 | q <= std_logic_vector(unsigned(q) + 1) when rising_edge(clk); |
21 | |
22 | end architecture arc ; |
Und eine erste Testbench, die nur versucht den Zählvorgang zu triggern:
1 | library ieee; |
2 | |
3 | use ieee.std_logic_1164.all ; |
4 | |
5 | |
6 | entity tb is begin |
7 | end ; |
8 | |
9 | |
10 | |
11 | architecture tb_behav of tb is |
12 | |
13 | component Counter is port ( |
14 | clk: in std_logic; -- clock |
15 | Q: out std_logic_vector(3 downto 0); |
16 | TC: out std_logic -- Terminal Count |
17 | );
|
18 | end component ; |
19 | |
20 | signal tb_CLK : std_logic := '0'; |
21 | signal tb_Q : std_logic_vector(3 downto 0) := "0000"; |
22 | signal tb_TC : std_logic := '0'; |
23 | |
24 | |
25 | begin
|
26 | |
27 | dut : Counter port map ( |
28 | clk => tb_clk, |
29 | Q => tb_Q , |
30 | TC => tb_TC |
31 | );
|
32 | |
33 | clk_proc: process begin |
34 | |
35 | CLK <= not CLK; |
36 | wait for 5 ns; |
37 | |
38 | if NOW > 200 ns then |
39 | wait; |
40 | end if; |
41 | end process clk_proc; |
42 | |
43 | stim_proc : process begin |
44 | |
45 | |
46 | wait for 80 ns ; |
47 | |
48 | wait ; |
49 | |
50 | end process; |
51 | |
52 | end architecture tb_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....
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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 | entity Counter is port ( |
2 | :
|
3 | q : out std_logic_vector(3 downto 0) := "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 | LIBRARY ieee; |
2 | USE ieee.std_logic_1164.ALL; |
3 | USE ieee.numeric_std.ALL; |
4 | |
5 | entity Counter is port ( |
6 | clk: in std_logic; -- clock |
7 | -- ... mehr controls kommen spaeter
|
8 | q: out std_logic_vector(3 downto 0); |
9 | TC: out std_logic -- trickle, carry out oder so |
10 | );
|
11 | end Counter; |
12 | |
13 | architecture arc of Counter is |
14 | signal cnt : unsigned (3 downto 0) := (others=>'0'); |
15 | begin
|
16 | |
17 | cnt <= cnt+1 when rising_edge(clk); |
18 | |
19 | q <= std_logic_vector(cnt); |
20 | |
21 | end architecture arc ; |
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.... ;-)
:
Bearbeitet durch Moderator
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:
1 | :
|
2 | -- Id: A.3
|
3 | function "+" ( L,R: UNSIGNED ) return UNSIGNED is |
4 | constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; |
5 | variable L01 : UNSIGNED(SIZE-1 downto 0); |
6 | variable R01 : UNSIGNED(SIZE-1 downto 0); |
7 | begin
|
8 | if ((L'length<1) or (R'length<1)) then return NAU; end if; |
9 | L01 := TO_01(RESIZE(L,SIZE),'X'); -- von hier kommt das X |
10 | if (L01(L01'left)='X') then return L01; end if; |
11 | R01 := TO_01(RESIZE(R,SIZE),'X'); -- und von hier |
12 | if (R01(R01'left)='X') then return R01; end if; |
13 | return ADD_UNSIGNED (L01, R01, '0') ; |
14 | end; |
15 | :
|
Aus https://www.csee.umbc.edu/portal/help/VHDL/packages/numeric_std.vhd Markus 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... ;-)
:
Bearbeitet durch Moderator
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.
Moin, Zeno schrieb: > Synchronzähler z.B. lassen sich nur mit JK-FF realisieren. Bei der Aussage meld' ich doch mal ganz leise Zweifel an. Gruss WK
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.