www.mikrocontroller.net

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


Autor: Andreas B. (loopy83)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
entity schiebereg8bit is
   Port ( CLOCK_SR : in  STD_LOGIC;       --LVDS Takt
          RESET_SR : in  STD_LOGIC;       --Schieberegister Reset
          DATA_IN_SR : in  STD_LOGIC;     --serielle Daten Eingang
    FULL : out STD_LOGIC;        --Byte komplett
          DATA_OUT_SR : out STD_LOGIC_VECTOR (7 downto 0) --parallele Daten
      );
end schiebereg8bit;

architecture Behavioral of schiebereg8bit is

signal AUSGANG : STD_LOGIC_VECTOR (7 downto 0);
signal COUNT_INT : integer range 0 to 8;
signal FULL_INT : STD_LOGIC;

begin

SR_8bit: process (CLOCK_SR, RESET_SR)
begin
  if (RESET_SR = '1' OR RESET_SR = 'H')
  then   AUSGANG <= (others => '0');
    COUNT_INT <= 0;
  elsif rising_edge(CLOCK_SR) then
    AUSGANG(0) <= DATA_IN_SR;
    AUSGANG(1) <= AUSGANG(0);
    AUSGANG(2) <= AUSGANG(1);
    AUSGANG(3) <= AUSGANG(2);
    AUSGANG(4) <= AUSGANG(3);
    AUSGANG(5) <= AUSGANG(4);
    AUSGANG(6) <= AUSGANG(5);
    AUSGANG(7) <= AUSGANG(6);
    
    if (COUNT_INT < 8)
    then   COUNT_INT <= COUNT_INT + 1;
      FULL_INT <= '0';
    elsif (COUNT_INT = 8) then
      COUNT_INT <= 0;
      FULL_INT <= '1';
    end if;  
  end if;

end process SR_8bit;

FULL <= FULL_INT;
DATA_OUT_SR <= AUSGANG;

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.

Autor: help (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
    AUSGANG(0) <= DATA_IN_SR;
    AUSGANG(1) <= AUSGANG(0);
    AUSGANG(2) <= AUSGANG(1);
    AUSGANG(3) <= AUSGANG(2);
    AUSGANG(4) <= AUSGANG(3);
    AUSGANG(5) <= AUSGANG(4);
    AUSGANG(6) <= AUSGANG(5);
    AUSGANG(7) <= AUSGANG(6);
geht so kürzer:
    AUSGANG <= AUSGANG(6 downto 0) & DATA_IN_SR;

Autor: Andreas B. (loopy83)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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


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 ;-)

Autor: Andreas B. (loopy83)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ok,

nur wenn ich schon ganz zu Beginn die Flanke abfrage, was kann ich dann 
als Bedgung für das elsif formulieren?
SR_8bit: process (CLOCK_SR, RESET_SR)
begin
  if rising_edge(CLOCK_SR) then
    if (RESET_SR = '1' OR RESET_SR = 'H')
      then   AUSGANG <= (others => '0');
          COUNT_INT <= 0;
    elsif ??? then
      AUSGANG <= AUSGANG(6 downto 0) & DATA_IN_SR;
      
      if (COUNT_INT < 7)
      then   COUNT_INT <= COUNT_INT + 1;
          FULL_INT <= '0';
      elsif (COUNT_INT = 7) then
          COUNT_INT <= 0;
          FULL_INT <= '1';
      end if;  
    end if;
  end if;

end process SR_8bit;

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

DANKE!!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas B. (loopy83)
Datum:

Bewertung
0 lesenswert
nicht 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:
Inst_schiebereg8bit: schiebereg8bit PORT MAP(
    CLOCK_SR => CLOCK,
    RESET_SR => RESET,
    DATA_IN_SR => DATA_IN,
    FULL => DATA_READ_EN,
    DATA_OUT_SR => DATA_OUT_INT
  );
  
READ_EN : process (CLOCK, RESET, DATA_READ_EN, DATA_OUT_INT)
begin
  if rising_edge(CLOCK) then  
    if (RESET = '1') then
      DATA_OUT <= (others => '0');
    elsif (DATA_READ_EN = '1') then
      DATA_OUT <= DATA_OUT_INT;
    end if;
  end if;
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!!!

Autor: Andreas B. (loopy83)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier der Anhang, hab ich vergessen anzuhängen... sorry!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach das Lesen kombinatorisch:
READ_EN : process (RESET, DATA_READ_EN, DATA_OUT_INT)
begin
    if (RESET = '1') then
      DATA_OUT <= (others => '0');
    elsif (DATA_READ_EN = '1') then
      DATA_OUT <= DATA_OUT_INT;
    end if;
end process;

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.