Forum: FPGA, VHDL & Co. Ausgang geht auf Undef Zustand


von Achim B (Gast)


Lesenswert?

Hallo

ich will serielle Daten in parallen umwandeln.
Jetzt ist mein Problem das wenn am seriellen Eingang eine
Eins anliegt geht der Ausgang auf einen Undef Zustand.
Aber wenn der Ausgang undef ist und eine Null anliegt geht er wieder
auf Null.
Also irgendwie rafft er das nicht die eins zu setzen.
Was hab ich falsch gemacht.
Das ganze hab ich unter Xilinx Webpack programmiert und mit Modelsim
simuliert.

Gruss
Achim

entity versuch1 is
    Port (
           DIN : in std_logic;
           DOUT : out std_logic_vector(7 downto 0):="00000000";
           ....
end versuch1;

architecture Behavioral of versuch1 is
  signal SIN : std_logic;
  signal POUT : std_logic_vector(7 downto 0):="00000000";
  signal uebernahme : std_logic;

begin

--hier steht noch andere code mit Clock Behandlung usw.

Daten: process(BCLK)
subtype int70 is integer range 0 to 7;
variable i: int70 :=0  ;
begin
  if BCLK='1' and BCLK'event then

    POUT(i)<=DIN;
    i:=i+1;
  elsif i=7 then
  i:=0;

  end if;
end process;
Ausgabe: process(uebernahme)
begin
  if uebernahme='1' then
    DOUT<=POUT;
  end if;

end process;



end Behavioral;

von Hagen (Gast)


Lesenswert?

Daten: process(BCLK, Uebernahme)
begin
  if Uebernahme = '1' then
    DOUT <= POUT;
  elsif BCLK = '1' and BCLK'Event then
    POUT <= POUT(5 downto 0) & PIN;
  end if;
end process;

einfaches Schieberegister.

gruß hagen

von Achim B (Gast)


Lesenswert?

Hallo
Erstmal danke.
Aber irgendwie ist das langweilig. ;o)
So ein einfaches Schiebregister.
Meine Lösung fand ich irgendwie so genial. ;o)

Achim

von Hagen (Gast)


Lesenswert?

Ich bin zwar auch nicht so erfahren aber das Schieberegister dürfte weit
weniger Resourcen fressen als dein komplizierter Multiplexer.
Egal, was zählt ist das es funktioniert ;)

Gruß Hagen

von Axel Meineke (Gast)


Lesenswert?

Da kann ich nur die fertigen Templates die sogar im WebPack enthalten
sind, empfehlen. Die sind schon sehr gut aufgebaut.

von Michael (Gast)


Lesenswert?

Was ich noch machen würde wäre ein zweites Schieberegister. Das ganze
sieht denn so aus:


process (CLR,CLK,S_REGA)

begin
   if (CLR = '1') then
      S_REGA <= "000000001";
   elsif (CLK'event and CLK = '0') then
      S_REGA <=  S_REGA(7 downto 0) & S_REGA(8); -- schieben
   end if;
end process;


Das erste Schieberegister schiebst Du mit der abfallenden Flanke.
Dadurch wird die '1' immer weiter nach links geschoben. Immer wenn
die '1' ganz links angekommen ist, dann werden die Werte an
den parallelen Ausgang übergeben. Somit brauchst Du keine Zähler
zurücksetzen, den Zähler nicht abfragen und und und.



process(CLR,CLK,POUT,PIN)
begin
  if (CLR = '1') then
     DOUT <= (others => '0');
  elsif (CLK'event and CLK = '1') then
     if(S_REGA(8) = 1) then
        DOUT <= POUT;
     else
        POUT <= POUT(5 downto 0) & PIN;
  end if;
end process;

Mit der ansteigenden Flanke fragst Du die Posisition des
Schieberegisters ab, steht die '1' an der richtigen Stelle, dann
übergibst Du die Werte, wenn nicht dann schiebst einen neuen Wert in
das zweite Schieberegister. Wenn Du in diesem Prozess die ansteigende
Flanke benutzt, dann kannst Du sicher sein das schon alles
eingeschwungen ist. Diese Lösung ist sehr elegant und vor allem sehr
übersichtlich.

von Hagen (Gast)


Lesenswert?

Naja, dann könnte er auch POUT statt mit 6 Bits mit 7 Bit Breite
definieren. Sobald Bit 6 == 1 wird müssen die Daten an den Ausgabeport
und das POUT Schieberegister neu initialisiert werden.

process(Clr, clk)
begin
  if Clr = '1' then
    DOut <= (others => '0');
    POut <= "0000001";
  elsif Clk = '1' and Clk'Event then
    if POut(6) = 1 then
      DOut <= POut(5 downto 0);
      POut <= "000001" & Pin;
    else
      POut <= POut(5 downto 0) & Pin;
    end if;
end process;

Dies wäre dann aber eben keine asynchrone Ausgabe des internen
Schieberegisters.

Das Takten auf fallende Flanke einer Clock sollte man eher vermeiden.
In meinen bisherigen Projekten hat dies immer zu schlechteren Fittings
geführt.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

oder mit 6 Bits (spart ein Register/FF), dann so

process(Clr, clk)
begin
  if Clr = '1' then
    DOut <= (others => '0');
    POut <= "000001";
  elsif Clk = '1' and Clk'Event then
    if POut(5) = 1 then
      DOut <= POut(4 downto 0) & Pin;
      POut <= "000001";
    else
      POut <= POut(4 downto 0) & Pin;
    end if;
end process;

von Michael (Gast)


Lesenswert?

Das ist aber keine schöne Lösung, denn Du schreibst die Daten von POut
nach DOut wenn POut(5) = 1 ist. Bis dahin ist alles noch ok. Aber dann
definierst Du POut neu. Und genau das kann Probleme machen. Wenn man
sich das ganze in Logik vorstellt, dann übernimmt die Scahltung mit
einer Taktflanke die Daten nach DOut aber setzt POut auch gleich wieder
zurück. Wie willst Du mit der Lösung sicherstellen, dass es zu keinen
undefinierten Zuständen kommt. Mit anderen Worten woher soll das System
wissen, wann die Daten erfolgreich übergegeben wurden, denn erst dann
darf das System zurückgesetzt werden.

Ich denke mal das da meine Lösung deulich besser ist. Und warum sollte
es Probleme geben wenn ich zwei Flanken benutze. Man muss bei seinem
Design halt nur dabei bleiben, dann wird es sehr überschaubar und man
kann sehr einfach programmieren. (kann ich zumindestens aus Erfahrungen
meiner Projekte sagen)

Gruss Michael

von Achim B (Gast)


Lesenswert?

Hallo
So ein zweitesmal irgendwie war geradeben nach einen falschen
Tastendruck der ganze Text weg. grrrr ;o)
So erstmal danke für eure Antworten.

Meine nächstes Problem ist das die ganze Umwandlung erst starten darf
wenn ein anderes Signal auf High geht.
Ich hab dafür ein zweites Clocksignal LRCLK das alle 32 Takte von CLK
einen Takt hat. Ich schaff zwar das zu programmieren kann das aber
nicht synthesieren.

@Michael Könnte sein das dein Entwurf ein Fehler hat?
Nämlich immer wenn das Schieberegister ausgegeben wird übersieht er das
Bit. ich hab das versucht zu kompensieren indem ich das Schieberegister
auch bei der Ausgabe weiterschieb aber es hilft irgendwie nicht.
Oder simuliere ich irgendwie falsch?

Gruss

Achim

process(CLR,CLK,POUT,PIN)
begin
  if (CLR = '1') then
     DOUT <= (others => '0');
  elsif (CLK'event and CLK = '1') then
     if(S_REGA(8) = '1') then
        DOUT <= POUT;
        POUT <= POUT(6 downto 0) & PIN;
        WCLK<='1'
     else
        POUT <= POUT(6 downto 0) & PIN;
        WCLK<='1'
  end if;
 end if;
end process;

von Michael (Gast)


Lesenswert?

Ich habe das ganze nicht getestet, sondern nur als Hilfe gepostet.
Deshalb kann es sein, dass noch Fehler enthalten sind.

was ich noch nicht geschrieben habe ist, dass das Signal noch
deklariert werden muss.

entity versuch1 is
    Port
    (
           CLK    : in std_logic;
           CLR    : in std_logic;
           SIN    : in std_logic;
           DOUT   : out std_logic_vector(7 downto 0)
    );
end versuch1;

architecture structure of versuch1 is

   signal S_REGA  : std_logic_vector (9 downto 0);
   signal S_POUT  : std_logic_vector (7 downto 0);
   signal S_OK    : std_logic;

begin

process (CLR,CLK,S_REGA,S_OK)

begin
   if (CLR = '1') then
      S_REGA <= "000000001";
      S_OK <= '0';
   elsif (CLK'event and CLK = '0') then
      S_REGA <=  S_REGA(8 downto 0) & S_REGA(9); -- schieben
      S_OK <= '1'  -- damit man sicher ist das zuerst die fallende

                      Flanke kommt und das zählen nicht durcheinander
                      gebracht wird
   end if;
end process;


process(CLR,CLK,S_POUT,SIN,S_OK)
begin
  if (CLR = '1') then
     S_POUT <= (others => '0');
  elsif (CLK'event and CLK = '1') then
     if(S_REGA(9) = 1 and S_OK = '1') then
        DOUT <= S_POUT;
     else
        S_POUT <= S_POUT(6 downto 0) & SIN;
  end if;
end process;

Ich denke mal das muss jetzt funktionieren. Das Signal S_OK ist
notwendig, da man nie weiß ob zuerst die ansteigende oder abfallende
Flanke erscheint, wenn man die Spannungsversorgung anschaltet. Deshalb
verwende ich hier noch das Signal S_OK. Du solltest Dir dafür noch
einen anderen Namen ausdenken.

Das mit dem schnelleren Clock ist schon etwas komplizierter. Am besten
Du setzt ein Signal, das z.b. "ENABLE" heist auf '1', wenn die Daten
von parallel in seriell gewandelt werden sollen. Dann benötigst Du noch
eine zweite Variable, damit die Wandlung nur einmal durchlaufen wird,
denn Du kannst das Signal "ENABLE" nur in dem Prozess zurücksetzen,
in dem Du es gesetzt hast.

Gruss Michael

von Achim B (Gast)


Lesenswert?

hallo Michael

Das sollte auf keinen Fall eine Kritik an dir gewesen sein.
Mir war das schon klar das du mir es nur als Hilfe gepostet hast.
Auch die Signaldeklaration war mir klar.
Ich fand nur deine Herangehsweise an das Problem interessant,
deshalb nochmals die Nachfrage ob das Problem bei mir liegt indem ich
die Simulation falsch fahr oder bei deinem Vorschlag.
Mein Problem ist das ich noch immer zu sehr in C Programmierwesie denk
und programmier.
Was auch meistens bis zur Simulation klappt, aber dann bei der Synthese
na klar überhaupt nicht mehr funktioniert.
Vielen Dank nochmals für deine Hilfe.

Gruss
Achim

von Michael (Gast)


Lesenswert?

Ich habe es auch nicht als Kritik angesehen und ich fühlte mich auch
nicht angegriffen.

Ich denke mal es liegt an Deiner Simulation. Du must aufpassen dass Du
mit der richtigen Clockflanke anfängst. Deshalb habe ich bei der
zweiten Variante das Signal "S_OK" eingefügt. Somit müste es
eigentlich funktionieren.

Gruss

Michael

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.