Forum: FPGA, VHDL & Co. Schieberegister mit "vollständig gefüllt" Ausgang


von Andreas B. (loopy83)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe 8 bit serielle Daten, die ich parallelisieren möchte.

Dazu verwende ich ein 8bit Schieberegister.

Nun möchte ich, dass das Schieberegister einen Ausgang besitzt der 
vermeldet, wenn 8bit komplett durchgeschoben wurden, also wenn quasi das 
nächste Byte komplett am Ausgang anliegt und es abgespeichert werden 
kann.

Dazu verwende ich folgenden Code:
1
entity schiebereg8bit is
2
   Port ( CLOCK_SR : in  STD_LOGIC;       --LVDS Takt
3
          RESET_SR : in  STD_LOGIC;       --Schieberegister Reset
4
          DATA_IN_SR : in  STD_LOGIC;     --serielle Daten Eingang
5
    FULL : out STD_LOGIC;        --Byte komplett
6
          DATA_OUT_SR : out STD_LOGIC_VECTOR (7 downto 0) --parallele Daten
7
      );
8
end schiebereg8bit;
9
10
architecture Behavioral of schiebereg8bit is
11
12
signal AUSGANG : STD_LOGIC_VECTOR (7 downto 0);
13
signal COUNT_INT : integer range 0 to 8;
14
signal FULL_INT : STD_LOGIC;
15
16
begin
17
18
SR_8bit: process (CLOCK_SR, RESET_SR)
19
begin
20
  if (RESET_SR = '1' OR RESET_SR = 'H')
21
  then   AUSGANG <= (others => '0');
22
    COUNT_INT <= 0;
23
  elsif rising_edge(CLOCK_SR) then
24
    AUSGANG(0) <= DATA_IN_SR;
25
    AUSGANG(1) <= AUSGANG(0);
26
    AUSGANG(2) <= AUSGANG(1);
27
    AUSGANG(3) <= AUSGANG(2);
28
    AUSGANG(4) <= AUSGANG(3);
29
    AUSGANG(5) <= AUSGANG(4);
30
    AUSGANG(6) <= AUSGANG(5);
31
    AUSGANG(7) <= AUSGANG(6);
32
    
33
    if (COUNT_INT < 8)
34
    then   COUNT_INT <= COUNT_INT + 1;
35
      FULL_INT <= '0';
36
    elsif (COUNT_INT = 8) then
37
      COUNT_INT <= 0;
38
      FULL_INT <= '1';
39
    end if;  
40
  end if;
41
42
end process SR_8bit;
43
44
FULL <= FULL_INT;
45
DATA_OUT_SR <= AUSGANG;
46
47
end Behavioral;

Nun ergibt sich daraus das Bild im Anhang.

Das Problem was ich habe ist, dass FULL erst auf High geht, wenn 
eigentlich schon das nächste Mal geschiftet wird (siehe Cursor) und ich 
dadurch wetten könnte, dass mein Byte am Ausgang nicht den richtigen 
Wert trägt, wenn es ausgelesen wird.

Ich habe jetzt eine ganze Weile über diesem Problem gebrütet, aber komme 
zu keiner Lösung. Wenn ich den Counter für Full = 1 auf 7 setze, beißt 
sich das ja mit der Bedingung Counter < 8, weil es ja das gleiche ist.

Am besten wäre, wenn FULL = 1 gesetzt wird, wenn der Counter 8 erreicht 
hat und dann eine fallende Flanke vom CLOCK kommt, denn dann liegen 
ziemlich sicher die Daten korrekt an. Nur leider habe ich keine Ahnung, 
wie ich das bewerkstelligen soll.

Ich hoffe ihr habt eine Idee?!

DANKE!!!

MfG Andreas

PS: Wie kann ich Modelsim beibringen, dass er die aktuelle Simulation 
aktualisieren soll und sich nicht neustartet? Jedes Mal wenn ich die 
Simulation aus dem ISE starte, öffnet sich ein neues Modelsim Fenster 
und ich muss das alte schließen. Damit gehen dann auch alle Zoom- und 
sonstige Einstellungen verloren.

PS2: Ich bin mir sicher, dass man den Code auch effektiver gestalten 
kann, aber ich stehe noch recht am Anfang meiner VHDL "Karriere" und bin 
erstmal frph, wenn das Design das macht, was es soll :) Ich hoffe ich 
habe dann keine Probleme, die Sache in die Hardware zu implementieren.

von help (Gast)


Lesenswert?

Was spricht dagegen, auf <7  und =7 zu prüfen?
Korrekterweise solltest du ja auch von 0 bis 7 zählen, derzeit zählst du 
von 0 bis 8.
Das mit der fallenden Flanke ganz schnell vergessen, mit dem synchronen 
Design zur steigenden wird schon alles so gemacht wie du es willst.

In der Modelsim-Konsole unten kannst du Pfeil-nach-oben bis zum ersten 
Befehl drücken, dann wird das getan, was ISE macht.

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


Lesenswert?

Dein DATA_OUT_SR : out STD_LOGIC_VECTOR (7 downto 0)
hat 8 Bits (von 0 bis 7).
Also müsste doch auch dein Zähler von 0 bis 7 laufen...  :-o
Mit deinem Code machst du immer 9 Bits...


Das hier:
1
    AUSGANG(0) <= DATA_IN_SR;
2
    AUSGANG(1) <= AUSGANG(0);
3
    AUSGANG(2) <= AUSGANG(1);
4
    AUSGANG(3) <= AUSGANG(2);
5
    AUSGANG(4) <= AUSGANG(3);
6
    AUSGANG(5) <= AUSGANG(4);
7
    AUSGANG(6) <= AUSGANG(5);
8
    AUSGANG(7) <= AUSGANG(6);
geht so kürzer:
1
    AUSGANG <= AUSGANG(6 downto 0) & DATA_IN_SR;

von Andreas B. (loopy83)


Lesenswert?

DANKE für die Hilfe, aber an sich kann man das so machen, oder ist es 
eher "unsauber" und es gibt eine bessere, vielleicht effektivere und 
Ressourcen schohnendere Methode?

VIELEN DANK!

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


Lesenswert?

"Unsauber" ist der asynchrone Reset
1
  if (RESET_SR = '1' OR RESET_SR = 'H')
2
  then   AUSGANG <= (others => '0');
3
    COUNT_INT <= 0;
4
  elsif rising_edge(CLOCK_SR) then
5
  :
Besser ist, den synchron zu verwenden:
1
  if rising_edge(CLOCK_SR) then
2
    if (RESET_SR = '1')  then   
3
      AUSGANG <= (others => '0');
4
      COUNT_INT <= 0;
5
    else
6
    :


Diese Abfrage ist für die Synthese uninteressant:
 OR RESET_SR = 'H'
Denn in der realen Hardware gibt es nur 0,1 und Z.

> eine bessere, vielleicht effektivere ... Methode?
Du könntest das Schieberegister ein Bit breiter machen und beim Reset 
mit "000000001" laden. Wenn die '1' beim Schieben ganz links angekommen 
ist, bist du fertig. Das dürfte ein wenig effizienter sein ;-)

von Andreas B. (loopy83)


Lesenswert?

Ah ok,

nur wenn ich schon ganz zu Beginn die Flanke abfrage, was kann ich dann 
als Bedgung für das elsif formulieren?
1
SR_8bit: process (CLOCK_SR, RESET_SR)
2
begin
3
  if rising_edge(CLOCK_SR) then
4
    if (RESET_SR = '1' OR RESET_SR = 'H')
5
      then   AUSGANG <= (others => '0');
6
          COUNT_INT <= 0;
7
    elsif ??? then
8
      AUSGANG <= AUSGANG(6 downto 0) & DATA_IN_SR;
9
      
10
      if (COUNT_INT < 7)
11
      then   COUNT_INT <= COUNT_INT + 1;
12
          FULL_INT <= '0';
13
      elsif (COUNT_INT = 7) then
14
          COUNT_INT <= 0;
15
          FULL_INT <= '1';
16
      end if;  
17
    end if;
18
  end if;
19
20
end process SR_8bit;

Denn so vermeldet er mir, dass COUNT_INT von mehreren Takten beeinflusst 
wird.

DANKE!!

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


Lesenswert?

Ersetze
    elsif ??? then
durch
    else

Wobei....
wenn ich mir das ganze genau betrschte wirst du u.U. ein Problem mit dem 
Takt haben. Denn zurückgesetzt wird jetzt nur noch mit dem Takt :-/
Du wirst also fürs Zurücksetzen einen CLOCK_SR Puls brauchen.

von Andreas B. (loopy83)


Lesenswert?

Ja genau, das Problem mit dem Reset habe ich gerade gefunden und lange 
ging nix. Ich frage im TopLevel Design den FULL Ausgang ab und lese in 
Abhängigkeit davon die Daten des Schieberegisters aus.

Ich habe mir das jetzt so zurecht gebastelt:
1
Inst_schiebereg8bit: schiebereg8bit PORT MAP(
2
    CLOCK_SR => CLOCK,
3
    RESET_SR => RESET,
4
    DATA_IN_SR => DATA_IN,
5
    FULL => DATA_READ_EN,
6
    DATA_OUT_SR => DATA_OUT_INT
7
  );
8
  
9
READ_EN : process (CLOCK, RESET, DATA_READ_EN, DATA_OUT_INT)
10
begin
11
  if rising_edge(CLOCK) then  
12
    if (RESET = '1') then
13
      DATA_OUT <= (others => '0');
14
    elsif (DATA_READ_EN = '1') then
15
      DATA_OUT <= DATA_OUT_INT;
16
    end if;
17
  end if;
18
end process;
Nun habe ich aber das Problem, dass meine Simulation wie im Anhang 
aussieht. Also die Daten nicht bei der steigenden Flanke von FULL 
ausgelesen werden, sondern einen Takt später, was ja genau wieder falsch 
ist. Ich vermute, dass meine Abfrage nach dem DATA_READ_EN (FULL) 
Probleme macht und dadurch einen Takt länger braucht.

Hat jemand eine Idee, wie ich das lösen könnte? Ich simuliere jetzt 
schon ca. 1h... ich bekomme es entweder nicht übersetzt oder es 
funktioniert nicht so, wie ich es mir vorstelle.

Sind das bei jedem die Probleme, mit denen man sich rumärgern muss? Also 
wird es irgendwann besser und man bekommt einen besseren Überblick, auf 
was man achten muss? Denn bisher ist es sehr sehr mühsam etwas zustande 
zu bekommen... das ist nervenaufreibend und nicht gerade das Tempo, mit 
dem ich eigentlich mein Projekt bearbeiten wollte.

DANKE!!!

von Andreas B. (loopy83)


Angehängte Dateien:

Lesenswert?

Hier der Anhang, hab ich vergessen anzuhängen... sorry!

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


Lesenswert?

Mach das Lesen kombinatorisch:
1
READ_EN : process (RESET, DATA_READ_EN, DATA_OUT_INT)
2
begin
3
    if (RESET = '1') then
4
      DATA_OUT <= (others => '0');
5
    elsif (DATA_READ_EN = '1') then
6
      DATA_OUT <= DATA_OUT_INT;
7
    end if;
8
end process;

BTW:
Die Sensitivliste in deinem Prozess wäre sowieso überdefiniert:
1
READ_EN : process (CLOCK, RESET, DATA_READ_EN, DATA_OUT_INT)
2
begin
3
  if rising_edge(CLOCK) then  
4
  :
Dieser Prozess hinge nur von Clock ab:
1
READ_EN : process (CLOCK)
2
begin
3
  if rising_edge(CLOCK) then  
4
  :

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.