Forum: FPGA, VHDL & Co. Schieberegister vereinzelt parallel laden


von Maik R. (kiamur)


Lesenswert?

Hallo!

Ich probiere gerade mal etwas mit Schieberegistern rum und habe das 
Problem, dass ich es nicht schaffe ein Bit mitten im SR zu verändern.

Diesen Code habe ich von der Altera Seite:
1
LIBRARY IEEE;
2
USE IEEE.STD_LOGIC_1164.ALL;
3
4
ENTITY shift_8x64_taps IS
5
PORT (
6
  clk :       IN STD_LOGIC;
7
  shift :       IN STD_LOGIC;
8
  sr_in :       IN STD_LOGIC_VECTOR(7 DOWNTO 0);
9
  sr_out :       OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
10
);
11
END shift_8x64_taps;
12
13
ARCHITECTURE arch OF shift_8x64_taps IS
14
15
SUBTYPE sr_width IS STD_LOGIC_VECTOR(7 DOWNTO 0); -- Bits
16
TYPE sr_length IS ARRAY (63 DOWNTO 0) OF sr_width; -- Spalten
17
18
SIGNAL sr : sr_length;
19
20
BEGIN
21
  PROCESS (clk)
22
  BEGIN
23
    IF (clk'EVENT and clk = '1') THEN
24
      IF (shift = '1') THEN 
25
        sr(63 DOWNTO 1) <= sr(62 DOWNTO 0);
26
        sr(0) <= sr_in;
27
      END IF;
28
    END IF;
29
  END PROCESS;
30
31
  sr_out <= sr(63);
32
33
END arch;
Ich möchte nun die Bits 0 von sagen wir mal Spalte 3 und 10 logisch UND 
Verknüpfen, und mit dem Ausgang dieser Verknüpfung das Bit 7 in Spalte 4 
setzen.

Ich denke mal, dass ich die UND-Verknüpfung auf ein Speicherelement 
lege, dass ich dann mit negativer Flanke wieder zurücksetze. Den Ausgang 
dieses Speichers lege ich So würde dann das Ergebnis beim nächsten 
positiven auf den Eingang vom D-Flip-Flop 0 in Spalte 4.
Bei der nächsten positiven CLK-Flanke wird dann der Wert in das 
Schieberegister übernommen, und bei der negativen Flanke der 
Zwischenspeicher gelöscht.

So viel zu meiner Idee. Leider hapert es an der Umsetzung. Ich habe 
schon so einiges ausprobiert, aber komme nicht so richtig weiter.
Das Einzige, was schon geklappt hat, war eine UND-Verknüpfung zwischen 
den beiden Bits, die ich dann auf einen Ausgangspin legen konnte. Aber 
wie bekomme ich dieses Ergebnis jetzt wieder ins SR zurück?

Könnt ihr mir vielleicht ein paar Tips geben, wie ihr die Sache angehen 
würdet?

Gruß
Maik

von Falk (Gast)


Lesenswert?

@Maik Ritter

>Ich möchte nun die Bits 0 von sagen wir mal Spalte 3 und 10 logisch UND
>Verknüpfen, und mit dem Ausgang dieser Verknüpfung das Bit 7 in Spalte 4
>setzen.

siehe unten.

>Ich denke mal, dass ich die UND-Verknüpfung auf ein Speicherelement
>lege, dass ich dann mit negativer Flanke wieder zurücksetze. Den Ausgang

Das gewöhn dir gar nicht erst an. Du solltest dich erstmal mit den 
Grundlagen synchroner, sequenzieller Logik befassen. Das läuft alles 
wunderbar mit ein Taktflanke.

>den beiden Bits, die ich dann auf einen Ausgangspin legen konnte. Aber
>wie bekomme ich dieses Ergebnis jetzt wieder ins SR zurück?

Du brauchst ein weiteres Steuersignal, ich hab es mal load genannt. 
Ausserdem ist deine Typdefinition suboptimal. Besser so.

ENTITY shift_8x64_taps IS
PORT (
  clk :       IN STD_LOGIC;
  shift :       IN STD_LOGIC;
  load  :       IN STD_LOGIC;
  sr_in :       IN STD_LOGIC_VECTOR(7 DOWNTO 0);
  sr_out :       OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END shift_8x64_taps;

ARCHITECTURE arch OF shift_8x64_taps IS

TYPE sr_array IS ARRAY (63 DOWNTO 0) OF STD_LOGIC_VECTOR(7 DOWNTO 0); 
Array

SIGNAL sr : sr_array;
SIGNAL sr_load : sr_array;

BEGIN
  PROCESS (clk)
  BEGIN
    IF (clk'EVENT and clk = '1') THEN
      IF (shift = '1') THEN
        sr(63 DOWNTO 1) <= sr(62 DOWNTO 0);
        sr(0) <= sr_in;
      elsif load='1' then
        sr <= sr_load;
      END IF;
    END IF;
  END PROCESS;

  sr_out <= sr(63);

-- Logik für Datenverknüpfung, kombinatorisch

process(sr)

begin
  -- hier kann jede beliebige Verknüpfung stehen
  sr_load <= sr;    -- erstmal alle normal zuweisen, Änderungen werden 
in den nachfolgenden zeilen überschrieben
  sr_load(7)(4) = sr(3)(0) and sr(10(0);
end process;
END arch;

MfG
Falk

von Maik R. (kiamur)


Angehängte Dateien:

Lesenswert?

Hallo Falk!

Vielen Dank auch heute wieder mal!

>process(sr)

Das ist was, wo ich jetzt wohl nicht drauf gekommen wäre. Ich muss mich 
mit den VHDL Konzepten (bzw. der Parallelität der Hardware) erst noch 
anfreunden. Bis jetzt habe ich ja nur Software gemacht. . .

Ehrlich gesagt wage ich auch jetzt nur zu ahnen, was da wohl passiert. 
Und auch das Symbol im Anhang, was der RTL Viewer aus dem Code generiert 
hat kenne ich nicht.
Als ich das Symbol zum ersten Mal in den Altera Data Sheets gesehen 
habe, habe ich gedacht, das das ein Mux ist. Aber irgendwie fehlt doch 
da die Adressleitung zum Umschalten, welcher Eingang jetzt aktiv ist. 
Deswegen ist es wohl kein Mux. Aber was ist es dann?

Gruß
Maik

von Falk (Gast)


Lesenswert?

@Maik Ritter

>Deswegen ist es wohl kein Mux. Aber was ist es dann?

Es IST ein Mux. Ein 1 Bit 2:1 Mux

2 Dateneingänge (links)
1 Steuereingang (oben)

Knapp vorm Ziel verrissen ;-)

MFG
Falk

von Maik R. (kiamur)


Lesenswert?

Okay, okay, ich glaubs dir. . . .

Aber für mich macht dann die Verbindung zum Shift Signal keinen Sinn.
Wenn ich jetzt mit jedem Takt das Schieberegister weiterschieben möchte, 
dann ist doch das Shift Signal ständig auf '1', und es kann nie die 
Zelle (4)(7) parallel mit dem Ergebnis der UND Verknüpfung geladen 
werden, oder?

von Falk (Gast)


Lesenswert?

@Maik Ritter

>Aber für mich macht dann die Verbindung zum Shift Signal keinen Sinn.
>Wenn ich jetzt mit jedem Takt das Schieberegister weiterschieben möchte,
>dann ist doch das Shift Signal ständig auf '1', und es kann nie die
>Zelle (4)(7) parallel mit dem Ergebnis der UND Verknüpfung geladen
>werden, oder?

Richtig, denn in der Beschreibung hat Schieben Priorität vor Laden. wenn 
du es anders willst, musst du die IF Abfrage vertauschen (erst load, 
dann shift).

MfG
Falk

von Maik R. (kiamur)


Lesenswert?

Hallo!

Ich musste mal eben nach Hause fahren. Deswegen melde ich mich jetzt 
erst.

Eine Frage hätte ich dann noch zu der Problematik hier: Egal, wie rum 
ich es mache, ich bekomme kein kontinuierliches Schieben durch die 
Register hin, oder? Ich also pro Takt entweder nur schieben, oder nur 
laden.

Gibt es auch eine Möglichkeit beides Gleichzeitig zu machen? Geladen 
werden dann eben nur die D-FFs, die auch wirklich über ein MUX am 
Eingang verfügen.
Die anderen bekommen ihr Signal nach wie vor von den vorhergehenden 
D-FFs.

Hmmmm, eine Idee?

Gruß
Maik

von Falk (Gast)


Lesenswert?

@ Maik Ritter

>Die anderen bekommen ihr Signal nach wie vor von den vorhergehenden
>D-FFs.

>Hmmmm, eine Idee?

Na DAS solltest du jetzt aber alleine hinbekommen. Schau dir mal das 
VHDL an.

MfG
Falk

von Maik R. (kiamur)


Lesenswert?

Hallo Falk!

Ich hoffe du bist in der Nähe . . .

Um es kurz zu machen: Ich bekomme es nicht hin.
Egal, was ich versuche, entweder spuckt der Compiler schon einen 
Syntaxfehler aus, oder mein ganzes Schieberegister ist weg . . . (ich 
habe dann im RTL Viewer nicht mehr 512 D-FFs sondern nur noch 11 oder so 
. . . )

Im RTL Viewer sehe ich ja, dass die D-FFs auch einen asynchronen 
Ladeeingang haben. Den könnte ich ja eigentlich benutzen und mit meiner 
UND Verknüpfung verbinden. Nur wie?

Du musst mir ja nicht gleich die Ganze Lösung präsentieren. Vielleicht 
reicht ja auch schon ein Tip an welcher Stelle ich ran muss.

Auf alle Fälle stört mich dieses "ENTWEDER schieben ODER laden" pro 
Takt. Es soll halt geschoben werden und das Ergebnis der UND Verknüpfung 
gleich an die entsprechende Stelle geladen werden.

Sorry, wenn ich mich blöd anstelle, aber ich finde echt nichts in meinen 
VHDL Unterlagen, die mir weiterhelfen . . .

Gruß
Maik

von Falk (Gast)


Lesenswert?

@ Maik Ritter

>Ich hoffe du bist in der Nähe . . .

I'll be there for you . . . ;-)

>Um es kurz zu machen: Ich bekomme es nicht hin.

Hmm.

>Im RTL Viewer sehe ich ja, dass die D-FFs auch einen asynchronen
>Ladeeingang haben. Den könnte ich ja eigentlich benutzen und mit meiner
>UND Verknüpfung verbinden. Nur wie?

Nein.

>Du musst mir ja nicht gleich die Ganze Lösung präsentieren. Vielleicht
>reicht ja auch schon ein Tip an welcher Stelle ich ran muss.

Kleiner Denkanstoss.
Bei jedem Takt laden die FlipFlops einen neuen Wert. Einige sollen nur 
als Schieberegister arbeiten. Diese laden den Wert ihres Vorgängers. 
Einige sollen als Speicher für logisch verknüpfte Signale arebeiten. 
Diese laden eben die logischen Verknüpfungen.
Du kannst im Prinzip eine sehr lange Liste schreiben, welchen Wert jedes 
einzelne FlipFlop laden soll. Die Fortgeschrittenen sparen sich durch 
clevere Formulierungen viel Schreibarbeit.

Na, dämmerts?

>Auf alle Fälle stört mich dieses "ENTWEDER schieben ODER laden" pro
>Takt. Es soll halt geschoben werden und das Ergebnis der UND Verknüpfung
>gleich an die entsprechende Stelle geladen werden.

Das entweder Schieben oder Laden enstand nur in dem Beispiel. Das kannst 
du wieder rausnehmen. Alles was du brauchst ist eine 0815 
Signalzuweisung in einem getakteten Prozess.

>Sorry, wenn ich mich blöd anstelle, aber ich finde echt nichts in meinen
>VHDL Unterlagen, die mir weiterhelfen . . .

Das ist ein Problem des Grundverständnisses. Wie arbeitet synchrone 
Logik?

MFG
Falk

von Maik R. (kiamur)


Lesenswert?

Vielen Dank, dass du solche Geduld mit mir hast.

Langsam reift in mir eine Idee. Dazu nur eine kleine Frage: Das Schieben 
der Registerinhalte (was ja nach wie vor noch 98% meiner Applikation 
ausmacht) realisiere ich dann nicht mehr über ein einfaches zuweisen wie 
hier:
1
sr(63 DOWNTO 1) <= sr(62 DOWNTO 0);

sondern ich muss nun für jedes FF einzeln entscheiden, ob es den 
Vorgängerwert übernimmt, oder anders geladen wird, oder?

Ich frage nur vorsichtshalber nach und fange jetzt gleich mit dem 
ausprobieren an. Wenn ich nach wie vor diesen Code als Grundlage nehmen 
soll, dann kannst du ja die Notbremse ziehen.

Gruß
Maik

von Falk (Gast)


Lesenswert?

@ Maik Ritter

>Langsam reift in mir eine Idee. Dazu nur eine kleine Frage: Das Schieben
>der Registerinhalte (was ja nach wie vor noch 98% meiner Applikation
>ausmacht) realisiere ich dann nicht mehr über ein einfaches zuweisen wie
>hier:

>sr(63 DOWNTO 1) <= sr(62 DOWNTO 0);

Doch, das ist schonmal richtig.

>sondern ich muss nun für jedes FF einzeln entscheiden, ob es den
>Vorgängerwert übernimmt, oder anders geladen wird, oder?

Das ist auch richtig. Der Knackpunt ist, es möglichs mit wenig Aufwand 
hinzuschreiben. Schliesslisch willst du nicht für 64x8 Bit jeweils eine 
eigene Zuweiseung schreiben.
Noch ein kleiner Tip.

In einem kombinatorischen Prozess funktioniert Logik wie in Software. 
Zuweisungen die weiter unten stehen überschrieben Zuweisungen die weiter 
oben stehen.

Nun aber!

>ausprobieren an. Wenn ich nach wie vor diesen Code als Grundlage nehmen
>soll, dann kannst du ja die Notbremse ziehen.

Der Code den ich geschrieben habe kannst du verwenden. Schmeiss die IF 
mit shift und load raus.

MFG
Falk

von Maik R. (kiamur)


Lesenswert?

Wow, ich hab's! :-)
1
sr(63 DOWNTO 1) <= sr(62 DOWNTO 0);
2
sr(0)(7) <= sr(5)(5) and sr(10)(5);
3
sr(4)(7) <= (sr(3)(0) and sr(10)(0)) or sr(3)(7);
4
sr(0) <= sr_in;

Habe auch schon ein neues Extra mit eingebaut. So sieht es auf den 
ersten Blick schon mal genau so aus, wie ich es haben wollte.

Jetzt vielleicht noch mal eine praktische Frage: Funktioniert das auch?

Angenommen "(sr(3)(0) and sr(10)(0))" ist '1' nach dem letzten Takt. 
Dann wird dies aber erst im nächsten Takt von sr(4)(7) übernommen. In 
diesem nächsten Takt kann sich aber auch "(sr(3)(0) and sr(10)(0))" 
schon wieder so ändern, dass es nicht mehr '1' ist. Kann man denn 100%ig 
sagen, dass die alte '1' übernommen wird. Ich denke mal im Simulator 
wird das so sein, aber in der Praxis?

Was sagst du als erfahrener Hase dazu?

Bis hier hin aber wirklich erst mal vielen Dank für deine tolle Hilfe!!!

Gruß
Maik

von Falk (Gast)


Lesenswert?

@ Maik Ritter

>sr(63 DOWNTO 1) <= sr(62 DOWNTO 0);
>sr(0)(7) <= sr(5)(5) and sr(10)(5);
>sr(4)(7) <= (sr(3)(0) and sr(10)(0)) or sr(3)(7);
>sr(0) <= sr_in;

Heureka!

>Jetzt vielleicht noch mal eine praktische Frage: Funktioniert das auch?

Ja. Fast.
Dein

sr(0) <= sr_in;

in der 4. Zeile macht dir dein

sr(0)(7) <= sr(5)(5) and sr(10)(5);

unwirksam. Da musst du die Reihenfolge vertauschen.

>Angenommen "(sr(3)(0) and sr(10)(0))" ist '1' nach dem letzten Takt.
>Dann wird dies aber erst im nächsten Takt von sr(4)(7) übernommen. In
>diesem nächsten Takt kann sich aber auch "(sr(3)(0) and sr(10)(0))"
>schon wieder so ändern, dass es nicht mehr '1' ist. Kann man denn 100%ig
>sagen, dass die alte '1' übernommen wird. Ich denke mal im Simulator
>wird das so sein, aber in der Praxis?

Auch in der Praxis. Es dauert* ja eine kleine Weile, bis die neuen Daten 
aus den FLipFlop rauskommen. Da sind die alten Daten längst übernommen 
worden.

>Was sagst du als erfahrener Hase dazu?

Gut durchgekämpft! Weiter so!

MFG
Falk

*die FlipFlops in heutigen FPGAs brauchen dazu weniger als eine 
Nanosekunde. Aber das passt schon.

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.