Forum: FPGA, VHDL & Co. VHDL: 4-Bit Register aus D-FFs und Multiplexern


von Henrik L. (henrik_l)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich bin noch relativ unerfahren mit VHDL und versuche folgende Aufgabe 
zu lösen: Ein 4-Bit Register, bestehend aus D-Flip-Flops und 
Multiplexern. Im Anhang befindet sich die dazugeörige Schaltung. Die 
Kopplung der Flip-Flops soll so erfolgen, dass mit jedem Takt ein 
Schiebevorgang nach links ausgeführt wird. Durch das EN-Signal werden 
die Flipflops freigeschaltet. Der Dateneingang ist vom Steuersignal 
Ripple des Multiplexers abhängig (Input oder D). Das Ganze soll ich mit 
Komponenten entwickeln, wofür ich die generate-Anweisung verwenden soll.

Die Entities sind gegeben:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
entity DFF is
4
  generic(P_DELAY: time := 1 ns; SETUP : time := 1 ns);
5
  port(D, CLK, EN, RESET: in std_logic;
6
       Q, Q_INV : out std_logic);
7
end DFF;
8
9
library ieee;
10
use ieee.std_logic_1164.all;
11
entity MUX2X1 is
12
  generic(P_DELAY: time := 2 ns);
13
  port(S, E1, E2: in std_logic;
14
       Y: out std_logic);
15
end MUX2X1;
16
17
library ieee;
18
use ieee.std_logic_1164.all;
19
entity D_RIPPLE_REG is
20
  generic(P_DELAY: time := 8 ns; SETUP : time := 2 ns;
21
         SIZE : positive := 4);
22
  port(D: in std_logic_vector(size-1 downto 0);
23
       CLK, EN, RESET, RIPPLE, INPUT: in std_logic;
24
       Q : out std_logic_vector (size-1 downto 0);
25
       Q_INV : out std_logic_vector (size-1 downto 0);
26
       OUTPUT: out std_logic);
27
end D_RIPPLE_REG;
Für die Entity D_RIPPLE_REG soll ich die Architektur erstellen. Bis lang 
habe ich allerdings nur sehr simple Schaltungen umgesetzt und weiß nicht 
so recht wo und wie ich genau anfangen soll.

Bis lang habe ich Folgendes implementiert:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
4
entity D_RIPPLE_REG is
5
  generic (P_DELAY: time := 8 ns; SETUP : time := 2 ns;
6
           SIZE : positive := 4);
7
  port (D: in std_logic_vector(size-1 downto 0);
8
        CLK, EN, RESET, RIPPLE, INPUT: in std_logic;
9
        Q : out std_logic_vector (size-1 downto 0);
10
        Q_INV : out std_logic_vector (size-1 downto 0);
11
        OUTPUT: out std_logic);
12
end D_RIPPLE_REG;
13
14
architecture Verhalten of D_RIPPLE_REG is 
15
COMPONENT DFF is
16
  generic (P_DELAY: time := 1 ns; SETUP : time := 1 ns);
17
  port (D, CLK, EN, RESET: in std_logic;
18
        Q, Q_INV : out std_logic);
19
end component;
20
21
COMPONENT MUX2X1 is
22
  generic (P_DELAY: time := 2 ns);
23
  port (S, E1, E2: in std_logic;
24
        Y: out std_logic);
25
end component;
26
begin
27
  gen1: for i in 0 to size - 1 generate
28
    ffd: DFF port map (D => D(i), CLK => CLK, EN => EN, RESET => RESET, Q => Q(i), Q_INV => Q_INV(i));
29
  end generate;
30
31
  gen2: for i in 0 to size - 1 generate
32
    mux: MUX2X1 port map (Y(i) => D(i)); --Da fehlt noch etwas
33
  end generate;
34
35
RESET_PROC: process (RESET)
36
begin
37
--  if RESET = '1' then
38
39
--  end if;
40
end Verhalten;

: Verschoben durch Moderator
von oerks (Gast)


Lesenswert?

Was war jetzt die Frage?

von Henrik L. (henrik_l)


Lesenswert?

Ich weiß nicht wie ich die Anforderungen umsetzen soll und bräuchte da 
etwas Hilfe, wie man die Aufgabe am besten lösen kann.

von Gustl B. (-gb-)


Lesenswert?

Henrik L. schrieb:
> Für die Entity D_RIPPLE_REG soll ich die Architektur erstellen.

Du musst erstmal auch die anderen Komponenten mit Leben füllen.

Henrik L. schrieb:
> Ich weiß nicht wie ich die Anforderungen umsetzen soll und bräuchte da
> etwas Hilfe, wie man die Aufgabe am besten lösen kann.

1. DFF und MUX2X1 mit Leben füllen.
2. Innerhalb der D_RIPPLE_REG die beiden Komponenten DFF und MUX2X1 so 
mit den ein und Ausgängen und zusätzlichen Signalen verbinden damit das 
ein Schieberegister ist.

Warte etwas dann bereite ich dir den Code etwas anfängerfreundlich auf 
...

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

So, hat etwas gedauert, musste das selber erst lösen. Eigentlich eine 
schöne Aufgabe, aber das mit den Timings finde ich für Anfänger doch 
ziemlich hart.

Hinweise:

Das mit dem Timing kannst du erstmal komplett ignorieren, das 
funktioniert auch so.
Danach wenn du das Timing beachten willst, dann helfen dir:
a <= b after TIME;
a <= transport b after TIME;
SIGNALNAME'LAST_EVENT

So kannst du die Komponenten einbinden ohne sie nochmals deklarieren zu 
müssen.
1
inst_MUX2X1: entity work.MUX2X1
2
  generic map(
3
  P_DELAY  => P_DELAY)
4
  port map(
5
  S   => ... ,
6
  E1  => ... ,
7
  E2  => ... ,
8
  Y   => ... );

Ich würde zuerst eine Testbench für die einzelnen Komponenten schreiben 
und die simulieren und dann erst eine Testbench für die übergeordnete 
Komponente D_RIPPLE_REG.

Edit:
In der VHDL Datei soll es unten natürlich heißen

> -- Hier kommt die Beschreibung vom D_RIPPLE_REG rein.

und

> -- Hier werden verwendete Komponenten deklariert.

kannst du ignorieren wenn du die wie oben einbindest.

: Bearbeitet durch User
von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Und weil du schon genug zu tun hast, hier im Anhang kleine Testbenches 
für DFF, MUX2X1 und D_RIPPLE_REG.

Das kannst du einfach unten an das VHDL in der einen Datei rankopieren. 
Aber du kannst auch für alles eigene Dateien machen, ist egal.

von Christoph Z. (christophz)


Lesenswert?

Gustl B. schrieb:
> Das mit dem Timing kannst du erstmal komplett ignorieren, das
> funktioniert auch so.
> Danach wenn du das Timing beachten willst, dann helfen dir:
> a <= b after TIME;
> a <= transport b after TIME;
> SIGNALNAME'LAST_EVENT

Ich sehe gerade nicht, wo es bei dir geklemmt hat aber so etwas sollte 
in dieser Aufgabe nicht nötig? Synthesefähig wäre das dann ja auch 
nicht.

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


Lesenswert?

Christoph Z. schrieb:
> Synthesefähig wäre das dann ja auch nicht.
Das ist eh' nur eine akademische Spielerei im Simulator...

> aber so etwas sollte in dieser Aufgabe nicht nötig?
Wenn diese Parameter als Generics übergeben werden, dann sollte der 
Schüler ja schon was damit machen. Und eben die Einhaltung der 
Setup-Zeit kontrollieren und den Ausgang irgendwie verzögern.

Gustl B. schrieb:
> dann helfen dir:
> a <= b after TIME;
> a <= transport b after TIME;
> SIGNALNAME'LAST_EVENT
Ich würde an dieser Stelle noch auf das Attribut 'stable hinweisen.
Das könnte recht brauchbar für die Kontrolle der Setup-Zeit sein.

von Christoph Z. (christophz)


Lesenswert?

Lothar M. schrieb:
>> aber so etwas sollte in dieser Aufgabe nicht nötig?
> Wenn diese Parameter als Generics übergeben werden, dann sollte der
> Schüler ja schon was damit machen. Und eben die Einhaltung der
> Setup-Zeit kontrollieren und den Ausgang irgendwie verzögern.

Ach so, jetzt habe ich die Stelle auch gefunden.

Ja, das sind halt so Sachen, die ein Entwickler im Feld da halt komplett 
nicht erwartet und dann einfach nicht sieht ;-)
Sorry for the noise

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


Lesenswert?

Christoph Z. schrieb:
> Sorry for the noise
Passt schon.
So sieht der geneigte Lernende wenigstens, dass das nicht praxisrelevant 
ist... ;-)

von Gustl B. (-gb-)


Lesenswert?

Lothar M. schrieb:
> 'stable

Vielen Dank!

von Henrik L. (henrik_l)


Angehängte Dateien:

Lesenswert?

@Gustle Vielen Dank für deine Hilfe! Die DFF und MUX2X1 funktionieren 
soweit. Allerdings hänge ich noch bei der D_RIPPLE_REG Architektur. Ich 
weiß nicht genau, was für zusätzliche Signale ich benötige. 
Wahrscheinlich benötige ich gar nicht alle, die ich angelegt habe. Was 
ich noch nicht verstehe ist, wie ich die beiden Bausteine (DFF und 
MUX2X1) miteinander verknüpfe. Wie macht man das? Wahrscheinlich denke 
ich falsch, da ich eher mit Programmiersprachen wie Java und C++ zu tun 
habe...

von Gustl B. (-gb-)


Lesenswert?

1
elsif(rising_edge(CLK)) and EN = '1' then
2
Y <= E1 when (S = '1') else E2;

Da kannst du jedes Mal ein Klammernpaar weglassen.
1
ffd: DFF port map (D => D_TEMP(i), CLK => CLK_TEMP, EN => EN_TEMP, 
2
    RESET => RESET_TEMP, Q => Q_TEMP(i), Q_INV => Q_INV_TEMP(i));

Das sieht zwar schön kompakt aus, erschwert aber die Lesbarkeit.
1
ffd: DFF port map(
2
   D     => D_TEMP(i),
3
   CLK   => CLK_TEMP,
4
   EN    => EN_TEMP, 
5
   RESET => RESET_TEMP,
6
   Q     => Q_TEMP(i),
7
   Q_INV => Q_INV_TEMP(i));

Henrik L. schrieb:
> Ich weiß nicht genau, was für zusätzliche Signale ich benötige.

Du brauchst das als Signal was
a) noch in keiner der eingebundenen Komponenten enthalten ist
b) kein Ein- oder Ausgang ist.
Da bleiben im Bild oben die schwarzen Drähte zwischen den MUX und DFF 
und die drei roten Drähte zwischen den DFF und den MUX.
Aber: Die roten Drähte gehen ja an Ausgänge, werden aber auch intern 
verwendet. Genauso das Signal Output, da wird ebenfalls ein Ausgang 
verzweigt. Es bietet sich daher an ein std_logic_vector für die Q zu 
nehmen, Q_temp oder so, und einen gleich langen vector für die Ys von 
den MUXes zu den Ds von den DFFs.
Weitere Signale braucht man nicht.

Henrik L. schrieb:
> Was
> ich noch nicht verstehe ist, wie ich die beiden Bausteine (DFF und
> MUX2X1) miteinander verknüpfe.

Mit Signalen, wie in Hardware, mit Drähten.

Das folgende Beispiel zeigt, wie die Y Ausgänge von den MUXen mit den D 
Eingängen der DFFs verbunden werden können.
1
signal MUX_Y : std_logic_vector(... downto ...):=(others => '0');
2
3
begin
4
5
gen_logic: for I in ... to ... generate
6
7
    inst_MUX2X1: entity work.MUX2X1
8
        port map(
9
        S       => ...,
10
        E1      => ...,
11
        E2      => ...,
12
        Y       => MUX_Y(I));
13
14
    inst_DFF: entity work.DFF
15
        port map(
16
        D       => MUX_Y(I),
17
        CLK     => ...,
18
        EN      => ...,
19
        RESET   => ...,
20
        Q       => ...,
21
        Q_INV   => ...);
22
23
end generate;

: Bearbeitet durch User
von Henrik L. (henrik_l)


Angehängte Dateien:

Lesenswert?

Danke, mir wird dabei einiges klar. So ganz funktioniert es aber leider 
noch nicht. Bei der Simulation der Testbench erhalte ich für die 
Ausgänge nur undefinierte Werte.

von Gustl B. (-gb-)


Lesenswert?

Statt
1
process (CLK)
2
begin
3
  for i in 0 to size - 1 loop              
4
    Q_INV_TEMP(i) <= not Q_TEMP(i);
5
  end loop;
6
end process;

kannst du auch schreiben

Q_INV_TEMP <= not Q_TEMP;

Aber wieso willst du das überhaupt invertieren?
Das DFF hat doch schon den Ausgang und den hast du sogar verwendet.
Q_INV => Q_INV_TEMP(i));


Also lass den process mit der Invertierung einfach weg.

Tja warum bleibt Q uninitialisiert? Weil du Q, Q_INV und OUTPUT nichts 
zuweist.

Es fehlen:

Q <= Q_TEMP;
Q_INV <= Q_INV_TEMP;
OUTPUT <= Q(size-1);

Edit:
Die Y der MUXes hast du korrekt an die FFs angeschlossen. Aber bei den 
Ds aus den FFs zu den E1 des nächsten MUX ist noch ein Denkfehler.

Und zwar wird nicht Q(i) an E1(i) verbunden, sondern Q(i) an E1(i+1).
Oder anders:

E1 => Q_TEMP(i-1);
Dabei wird also:
für i von 1 bis size-1:
   E1 => Q_TEMP(i-1);

Aber dann hast du keinen Index 0 in der Schleife, auch nicht fein.
Du kannst das lösen, indem du die Schleife/Generate von 1 bis size 
laufen lässt.
Dann musst du aber die Indizes anpassen und

Q_TEMP(0) <= INPUT;

hinzufügen. Da wird dann INPUT so behandelt als wäre es quasi das Q von 
einem FF weiter links im Bild, das aber nicht existiert.

: Bearbeitet durch User
von Henrik L. (henrik_l)


Lesenswert?

Dankeschön! Jetzt funktioniert es auch. Wäre schön wenn es in den 
Skripten mal so verständlich rübergebracht werden würde!

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


Lesenswert?

Henrik L. schrieb:
> Jetzt funktioniert es auch.
Und jetzt musst du wahrscheinloch noch die als Generics übergebenen 
Zeiten einsetzen:

1. mit 'stable überwachen, ob der Eingangswert des Flipflops vor der 
steigenden Flanke stabil war, und eine Fehlermeldung ausgeben, falls 
nicht

2. den Ausgangswert jeweils um die "delay"-Zeit verzögern

von Gustl B. (-gb-)


Lesenswert?

Henrik L. schrieb:
> Dankeschön! Jetzt funktioniert es auch.

Bitteschön, gut gemacht!

Henrik L. schrieb:
> Wäre schön wenn es in den
> Skripten mal so verständlich rübergebracht werden würde!

Das hab ich ja auch so gelernt als IT Lehrer (-:
Die Dozenten an der Uni müssen leider keine Didaktikvorlesungen besuchen 
oder mal vorher an einer Schule ein Praktikum machen.

von Christoph Z. (christophz)


Lesenswert?

Gustl B. schrieb:
> Die Dozenten an der Uni müssen leider keine Didaktikvorlesungen besuchen
> oder mal vorher an einer Schule ein Praktikum machen.

Ja, das ist ziemlich frustrierend für alle Studenten. Schon fast zynisch 
ist es daher, dass die ETH Zürich gute Didaktik Kurse anbietet, die für 
ETH Dozenten freiwillige Weiterbildungen sind aber "um sich neue 
berufliche Optionen zu eröffnen, beispielsweise als Gymnasiallehrer/in 
oder als Dozent/in an einer Fachhochschule", weil das da Pflicht ist.
Quelle: https://ethz.ch/de/studium/didaktische-ausbildung.html

von -gb- (Gast)


Lesenswert?

Ui, keine Ahnung ob das üblich ist an Unis.
Was sehr weit verbreitet ist ist aber Didaktik. Ob man die als 
Weiterbildung besuchen kann weiß ich nicht, aber wenn es da Lehramt 
gibt, dann gibt es da auch Didaktik dazu. Die werden leider oft eher 
stiefmütterlich behandelt und selbst im Lehramtstudium ist die Didaktik 
nur ein kleiner Teil. Trotzdem machen die gute Arbeit die Didaktiken, 
ich war da ein paar Jahre als studentische Hilfskraft und bekam ein paar 
Einblicke.

Wer da mal reingucken möchte kann sich den 
http://www.physikdidaktik.uni-karlsruhe.de/ durchlesen. Dieser Kurs, der 
in Bayern (und vielen anderen Bundesländern) leider nicht unterrichtet 
werden darf baut den Physikunterricht anders auf als üblich.

Üblich ist es, die Themen Wärmelehre, Elektrodynamik, Mechanik, Optik 
und Akustik getrennt zu behandeln.
Allerdings hängen manche der Themen zusammen, haben sehr ähnliche 
Konzepte und nur andere Begriffe. Nehmen wir Trägheit. Etwas wird als 
träge bezeichnet weil es seinen Zustand nicht instantan ändert. In der 
Mechanik muss ein sich in Bewegung befindlicher Körper erst seine 
Bewegungsenergie loswerden bis er sich nicht mehr bewegt.
In der Wärmelehre haben wir auch den Austausch von Wärme zwischen 
Körpern. Auch da gibt es Trägheit, es dauert bis beide Körper die 
gleiche Temperatur haben. In der Elektrizitätslehre gibt es das auch 
wenn etwas geladen oder entladen wird. Ein RC Filter reagiert träge weil 
es eben Zeit dauert bis Ladungen in den Kondensator hinein und wieder 
heraus fließen.

Oder nehmen wir Widerstand. In der Elektrik ist uns das klar, aber den 
gibt es natürlich auch in der Mechanik. Wenn du unangeschnallt im Auto 
sitzt, das bremst und du fliegst nach vorne, dann war der Widerstand 
zwischen dir und dem Sitz/Auto zu groß die Reibung war zu klein. Durch 
diesen großen Widerstand konntest du deine Bewegungsenergie nicht in der 
kurzen Zeit an das Auto und über das Auto an den Boden abgeben. Der 
größte Widerstand wäre wenn du gar nicht mit dem Auto verbunden wärest. 
Der Sicherheitsgurt verringert den Widerstand, du kannst deine 
Bewegungsenergie an das Auto und das Auto über die Bremsen und Reifen an 
den Boden abgeben.

Und genau so schöne Themenfelderübergreifende Erklärungen bietet der 
Karlsruhger Physikkurs.

von Christoph Z. (christophz)


Lesenswert?

-gb- schrieb:
> Üblich ist es, die Themen Wärmelehre, Elektrodynamik, Mechanik, Optik
> und Akustik getrennt zu behandeln.
> Allerdings hängen manche der Themen zusammen, haben sehr ähnliche
> Konzepte und nur andere Begriffe

Genau. Nur um dann in späteren Semestern das alles wieder mühsam 
zusammen zu hängen, weil in der Realität eh alles zusammenhängt und dazu 
kommt, dass mittlerweile eh viele Sachen mit Multiphysics 
Simulationssoftware entwickelt wird. In meinem Akustikkurs wurde mir 
dann ja auch beigebracht, wie man Akustische/Mechanische Systeme in 
äquivalente Systeme transformiert, die elektrische Elemente nutzen (Also 
akustische Zusammenhänge als Kondensatoren/Spulen/Widerstände 
dargestellt). Das ist der frühere Ansatz für Multiphysics Simulation, es 
wir alles übersetzt, so dass es in Spice reinpasst :-)

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.