www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Vector auffüllen


Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen, ich brauche mal ein paar gute idee wie cih folgendes 
problem lösen kann..

ich habe einen Vektor der angenommen 6Bit breit ist und ich bekomme pro 
takt immer einen Wert den ich nach und nach in den Vector rein schreiben 
muss und sobald ich die 7 Werte habe versende ich den ganzen Vector.. 
und setze ihn dann wieder auf null..

wie kann ich pro takt immer ein bit in den Vector setzen..

hab schon an eine for schleife gedacht aber beim bit setzen komme ich 
auf keinen grünen zweig..

danke schonmal

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> wie kann ich pro takt immer ein bit in den Vector setzen..
1. ein Schieberegister
oder
2. ein Multiplexer

Hier ist das mal für eine SPI Schnittstelle mit einem Schieberegister 
aufgeführt:
doutsr <= doutsr(doutsr'left-1 downto 0) & MOSI;
http://www.lothar-miller.de/s9y/categories/26-SPI-Slave


Und hier findet sich ein Multiplexer
rxdat(rxbitcnt) <= rxd_sr(3);
http://www.lothar-miller.de/s9y/categories/49-RS232-IO

> hab schon an eine for schleife gedacht aber beim bit setzen komme ich
> auf keinen grünen zweig..
Das ist garantiert nicht nötig. For-Schleifen führen einfach zu 
paralleler Hardware...

> und setze ihn dann wieder auf null..
Das brauchst du nicht, wenn du ihn erst dann versendest, wenn er 
"fertig" ist...

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal für die schnelle Antwort wollte es gerade auf folgende 
weise versuchen:
DAT = der übergebene Wert
CLK = ist der Clock der mir bei jedem Takt das nächste Bit ansteuert
DATA = ist der Vector in dem alles gespeichert wird

DATA(CLK_COUNT) <= DAT;

funktioniert das so?

Das Schieberegister von dir löst aber irgendwie nciht mein Problem..

doutsr <= doutsr(doutsr'left-1 downto 0) & MOSI;

ich bekommen immer nur einen Wert! deine Zeile mach doch nur den Vector 
größer und verundet das aber es wird doch immer nur das erste bit 
verundet oder verstehe ich hier gerade was falsch?

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> DATA(CLK_COUNT) <= DAT;
> funktioniert das so?
Das ist ein Multiplexer. Das könnte funktionieren, wenn das drumrum 
passt.

Reiner.H schrieb:
> Das Schieberegister von dir löst aber irgendwie nciht mein Problem..
Doch, das tut es. Du glaubst nicht, wieviel solche Schieberegister 
können. Und gerade für das Umsetzen von Seriell nach Parallel und 
umgekehrt sind sie optimal geeignet (wie z.B. der 74HC595...)

> deine Zeile mach doch nur den Vector größer
Nein. Der Vektor bleibt gleich breit. Anders ginge das gar nicht, da 
würde der Synthesizer sauber herummeckern...

> und verundet das
Der & Operator ist kein UND (dafür gibt es das Keyword AND), sondern ein 
Anhängeoperator (Concatenation).

> aber es wird doch immer nur das erste bit
> verundet oder verstehe ich hier gerade was falsch?
Ja. Es wird immer der Vektor um 1 Bit nach links geschoben und das 
"neue" Bit rechts "angehängt".

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah ok jetzt sieht das alles schon ganz anders aus :)

DAT der sich immer ändernde wert

elsif CLK'Event and CLK = '1' then
  COUNT <= COUNT + 1;

    if COUNT <= VAL then --VAL entspricht wert 7

          DATA <= DATA(DATA'COUNT-1 downto 0) & DAT;

    end if;

dann müsste das doch so aussehen?
nochmal kurz eine andere Frage wenn der CLK kommt zählt er ja 
automatisch hoch und er prüft ob count kleiner 7 ist. Im nächsten takt 
würde er DAT in den ersten Vektor Wert schreiben oder würde an DAT schon 
der zweite relevante Wert anliegen?

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> DATA <= DATA(DATA'COUNT-1 downto 0)
Das geht nicht.
Alles was mit ' (=Tic) beginnt, ist ein Attribut. Du kennst das vom 
'event. Mir zumindest ist ein attribut 'count nicht geläufig...

Ich würde das her so machen:
das Schieberegister 1 Bit länger, und dann mit "0000001" laden, dann 
solange schieben, bis die '1' links angekommen ist.
elsif CLK'Event and CLK = '1' then
    if DATA(DATA'left)='0' then
          DATA <= DATA(DATA'left-1 downto 0) & DAT;
    else
       ...                -- Daten weitergeben
       DATA <= "0000001"; -- und Schieberegister initialisieren
    end if;

> nochmal kurz eine andere Frage wenn der CLK kommt zählt er ja
> automatisch hoch und er prüft ob count kleiner 7 ist. Im nächsten takt
> würde er DAT in den ersten Vektor Wert schreiben
Ja, aber natürlich nur, wenn Die Daten zum Takt synchron sind...
Ich würde dir raten: simulier das einfach mal. So eine Waveform sagt 
mehr als 1001 Worte.

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
' in Verbindung mit count ist mir auch nicht bekannt :)

deine if abfrage ist aber komisch :).. ich glaube ich probiere erst mein 
aus und führe aus solange kleiner 7..

aber die Zeile verwende ich auf jedenfall das ist echt klasse
 DATA <= DATA(DATA'left-1 downto 0) & DAT;
ich nehme mal an das der mir mit jedem Takt einen nach links schiebt 
oder?

hab das jetzt so da stehen wird hoffentlich so funktionieren :)

elsif CLK'Event and CLK = '1' then
   COUNT <= COUNT + 1;
      if COUNT <= VAL then
         DATA <= DATA(DATA'left-1 downto 0) & DAT;
      end if;

falls du da keinen fehler siehst

vielen dank fuer die Hilfe!

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> DATA <= DATA(DATA'left-1 downto 0) & DAT;
> ich nehme mal an das der mir mit jedem Takt einen nach links schiebt
> oder?
Ja, das tut es.

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt habe ich aber noch ein weiteres blödes Problem :)

kann ich einen Takt den ich habe auch an den ausgang legen? Denn ich 
bekomme erst einen Wert wenn ich einen clock an den ausgang lege. Jede 
High Flanke sendet mir den aktuellen Wert.. wobei das auch wieder 
verzögert erfolgt..

und somit sich das laden in den vektor erheblich erschwert..

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> kann ich einen Takt den ich habe auch an den ausgang legen?
Ja.
Aber mal von vorn: welche Frequenz hat der Takt? Welche Frequenz hat 
dein "Masterclock"? Was willst du überhaupt mit was machen?

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hatte eig. eine super idee aber das funktioniert alles nicht..

also mein Master clk sendet alle 80ns eine high flanke ( hab also einen 
40ns clk)

ich muss meinem Encoder einen clk geben mit jeder steigenden flanke 
bekomme ich einen Wert von ihm.. den ich in einem Vector speichern muss 
(12 Bit)

das 13 Bit muss eine 0 sein

und das 14 Bit leutet eine wait periode ein die ca. 10us andauern muss 
während dieser Zeit wird konstant eine 1 gesendet..

Wenn ich wieder einen Wert haben möchte muss ich den encoder starten 
bzw. also einen Takt senden..

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> aber das funktioniert alles nicht..
Zeig doch mal deinen Code (als *.vhd Anhang)...

> also mein Master clk sendet alle 80ns eine high flanke
Das wären 12,5MHz.
> ( hab also einen 40ns clk)
Die Schlussfolgerung ist falsch, denn das ist ja nur die halbe 
Periodendauer. Und das sind nunmal 25MHz.

Und die Frage
> Was willst du überhaupt mit was machen?
Bezog sich nicht darauf wie DU es machen willst. Sondern wirklich WAS 
du machen willst. Also z.B.
Ich möchte einen Baustein AB123 der Firma YXZ an ein OIUZ-FPGA von ASDF 
anschliessen. Mein Quarzoszillator am FPGA hat 25MHz. Usw. usf...

Autor: Reiner.H (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ah ok :)

hab einen 25 MHz clk.. Mein encoder ist ein Winkelcodierer der mir den 
aktuellen Winkelstand ausgeben soll..

wenn ich ihm einen clk anlege bekommen ich bei jeder high flanke einen 
Wert es sind 12 bit weil er 4096 Positionen ermöglicht.. das 13 bit muss 
eine 0 sein und ab dem 14 konstant 1..

Meinen code habe ich zu 80% wieder gelöscht weil es so nicht 
funktioniert hat.. ich poste dir mal das was noch übrig gelassen habe..

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> wenn ich ihm einen clk anlege bekommen ich bei jeder high flanke einen
> Wert es sind 12 bit weil er 4096 Positionen ermöglicht.. das 13 bit muss
> eine 0 sein und ab dem 14 konstant 1..
Und wie geht es wieder von vorn los? Irgendwann? Oder über ein Timeout, 
wenn eine bestimmte Zeit keine Takte gekommen sind?
BTW: Das ist doch sicher irgendein Standardprotokoll...?

Wie auch immer: eigentlich ist das ganz einfach...
Du lädst dein 14 Bit breites Schieberegister mit dem Wert 0. Und dann 
gibst du einen Takt aus. Dieser Takt ist übrigens eigneltich nicht das, 
was ein FPGA unter einem Takt versteht! Es ist ein simples Signal wie 
jedes Andere auch, das einfach abhängig von irgendwelchen Zuständen 
seinen Pegel wechselt.

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ab dem 14bit muss die '1' mind. 6us und max 16us gesendet werden.

erst nach dieser Zeit darf auf den Ausgang wieder der clk gelegt werden 
damit der encoder weiß jetzt muss ich senden..

ich muss also einen künstlichen clk erzeugen.. liegt der clk an wird er 
aufgefordert mit bei jeder High flanke vom clk einen Wert zu senden ('1' 
oder '0') wo er sich halt gerade befindet und das 12 Takte lang bis er 
die Position hat..

Mein problem ist das der künstlichen clk langsamer ist als mein Master 
clk.. deshalb kann ich nciht genau abschätzen wann ich genau meine Werte 
vom encoder bekomme nicht das er mir falsche werte in den vector läd..

hoffe du verstehst mein verständniss problem..

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> Mein problem ist das der künstlichen clk langsamer ist als mein Master
> clk..
Wie schnell/langsam darf/soll den der Encodertakt sein?

> deshalb kann ich nciht genau abschätzen wann ich genau meine Werte
> vom encoder bekomme nicht das er mir falsche werte in den vector läd..
Das bauchst du auch nicht zu schätzen: es gibt eine Aktion (steigende 
Flanke am Encodertakteingang) und eine Reaktion (der Encoder spukt das 
nächste Bit aus. Und daher mußt du mit dem Einlesen nur solange 
warten, bis dieses Bit wieder stabil bei dir angekommen ist. Das Problem 
ist nicht neu und prinzipiell bei allen synchronen seriellen 
Schnittstellen gelöst.

> ab dem 14bit muss die '1' mind. 6us und max 16us gesendet werden.
Auf der Taktleitung?
Diese Taktleitung ist also auch noch eine Synchronisationsleitung.
Welchen Encoder (Hersteller/Typ) hast du denn da?

Autor: Reiner.H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soweit ich das dem Datenblatt entnehmen konnte 1MHz also 1us
das Datenblatt seite 2
http://www.twk.de/data/pdf/11294dd0.pdf

bist du sicher das es eine Steigende ist? ich kriege doch binär werte 
kann doch genauso eine 0 bekommen stehe gerade bisschen aufm schlauch.. 
hab gerade keine ahung wie ich abfragen kann wann ein neuer wert kommt 
und das nicht noch der alte ist..

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

Bewertung
0 lesenswert
nicht lesenswert
Reiner.H schrieb:
> bist du sicher das es eine Steigende ist?
Du selber hast das gesagt.
>>> bei jeder High flanke vom clk einen Wert zu senden
Ich wusste bisher (wegen Salamitaktik) bisher ja noch gar nichts von der 
Hardware...

Da sieht insgesamt nicht kompliziert aus, da wäre es für einen Anfänger 
am einfachsten, eine passende State-Machine aufzusetzen, die die 
einzelnen Zustände abklappert...

Autor: newbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja laut datenblatt bekomme ich die nach einer high flanke ich bin mir 
nur nicht sicher ob ich den wert direkt im nächsten Takt bekomme..

deswegen hab ich gedacht ich müsste irgendwie abfragen ob der mir jetzt 
ein signal schickt bzw. gibt es eine möglichkeit die zustandsänderungen 
leicht erfasst..

den rest kriege ich glaub ich ohne probleme hin.. hab nur das problem 
mit dem wann ich das signal empfange um das richtig in den Vector zu 
schreiben..

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

Bewertung
0 lesenswert
nicht lesenswert
newbie schrieb:
> ja laut datenblatt bekomme ich die nach einer high flanke ich bin mir
> nur nicht sicher ob ich den wert direkt im nächsten Takt bekomme..
Nur so funktioniert eine synchrone Übertragung.
Es wird ein(e) Takt(flanke) ausgegeben, und auf diese Aktion wird das 
nächste Datenbit ausgegeben. Die nächste Taktflanke darf natürlich erst 
kommen, wenn das Datenbit stabil am FPGA anliegt. Diese Zeit lässt sich 
ausrechnen und die Kommunikationstaktfrequenz entsprechend auslegen. Und 
da schadet es nichts, wenn die zu Kommunikation zu Anfang noch zu 
langsam ist, das kann man später optimieren...

> deswegen hab ich gedacht ich müsste irgendwie abfragen ob der mir jetzt
> ein signal schickt bzw. gibt es eine möglichkeit die zustandsänderungen
> leicht erfasst..
Und was würdest du machen, wenn sich das Signal nicht ändert? Also 
wenn z.B. zwei '0' oder zwei '1' nacheinander kommen.

Autor: newbie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das hab ich mir so gedacht das die direkt im nächsten Takt kommt den 
ich ihr vorgebe anders kann es ja eig. auch nciht funktionieren..

wenn zwei '0' nach einander komme bin ich mir nicht sicher ob es dann 
die selbe '0' ist oder ob es schon eine neue ist..

bei Taktflanke eins sende ich eine high flanke an den Ausgang

bei der zweiten Taktflanke bekomme ich eine Antwort also das Signal was 
ich in meinen Vektor schieben muss und ein erneutes high liegt am 
Ausgang

bei der dritten Taktflanke bekomme ich das zweite Signal und kann es in 
den Vektor schieben und es liegt erneut ein high am Ausgang

das sehe ich doch richtig? bin mir nur nicht so sicher wie ich das am 
besten umsetzen soll..

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

Bewertung
0 lesenswert
nicht lesenswert
newbie schrieb:
> das sehe ich doch richtig?
Ja.

> bin mir nur nicht so sicher wie ich das am besten umsetzen soll..
Ich würde da einfach meinen SPI-Master an die Anforderungen anpassen:
http://www.lothar-miller.de/s9y/categories/45-SPI-Master
Sieh dir das mal genauer an. Der Code funktioniert, es ist eine 
Testbench dabei. Da kannst du dir jetzt mal ein paar Stunden den Kopf 
drüber zerbrechen, und dann wirst du die Stellen schon finden, an denen 
was geändert werden muß...

Autor: None Blub (nioo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das jetzt mal alles umprogrammiert und es funktioniert eig. auch 
alles so wie es soll bis auf eine kleinigkeit..

während des erstn künstlich erzeugten Taktes funktioniert noch alles 
wenn aber die periode mit den gesendeten einsen vorbei ist und der 
künstliche clk quasi von neuem beginnt..
hört der clk einen zu früh auf und ich finde den fehler einfach nicht 
hoffe einer von euch sieht ihn..

leider kriege ich es nicht hin das bild von der Testbench anzufügen..
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;

entity Encoder is
  port  (   RESN           : in std_logic;
        CLK          : in std_logic;  
        DATA_ENCODER    : in std_logic;  -- 13 Bits  Empfangen
        EN1          :   OUT STD_LOGIC;
        EN2          :   OUT STD_LOGIC;  
        CLK_OUT        : out std_logic;  -- an den Drehgeber
        ENCODER_POSITON  : out std_logic_vector(12 downto 0):= (others => '0') --zum NIOS um die Lage zu erkennen
      );
end Encoder;

architecture Behavioral  of Encoder is

  signal CLK_COUNT           : std_logic_vector (6 downto 0) := (others => '0'); --64bit
  signal FLAG_WAIT_PERIOD      : std_logic;
  signal Flanke            : std_logic;
  signal wait_count          : std_logic_vector (7 downto 0) := (others => '0');
  signal wait_flag          : std_logic;  
  signal DATA              : std_logic_vector (12 downto 0) := (others => '0');
  signal temp              : std_logic_vector (12 downto 0) := (others => '0');
  signal TEST              : std_logic;
  
begin

  process (CLK, RESN)
    
    variable counter        : integer range 0 to 13;

    begin      
      
      if RESN   =  '0' then      
        CLK_OUT    <= '0';
        wait_flag <= '0';
        Flanke   <= '0';
      elsif CLK'Event and CLK = '1' then      
        -----------------------------------------------------------------  
        if(wait_flag = '0') then
          CLK_COUNT <= CLK_COUNT + 1; 
        else
          wait_count <= wait_count+1;        
        end if;        
        CLK_OUT <= CLK_COUNT(5);
        
        -----------------------------------------------------------------  
        if (CLK_COUNT(5) = '1') then
          if(counter = 13) then
              temp <= DATA;
            if(wait_count >= 120) then
              wait_flag   <= '0';
              wait_count  <= (others=>'0');              
              CLK_COUNT   <= (others=>'0');
              DATA   <= (others=>'0');
              counter     := 0;
            else
              wait_flag <= '1';
            end if;
          end if;            
          Flanke <= '1';
        -----------------------------------------------------------------    
        else
          if Flanke = '1' then          
            if(counter /= 13) then               
              DATA(counter) <= DATA_ENCODER;
              counter := counter + 1;              
            end if;          
            Flanke <= '0';            
          end if;
        
        end if;
        -----------------------------------------------------------------  
        if (counter = 13) and (DATA_ENCODER = '0') then
          ENCODER_POSITON(12 downto 0) <= temp(12 downto 0);
        end if;
      end if;        
        
  end process;
  
end Behavioral;

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

Bewertung
0 lesenswert
nicht lesenswert
None Blub schrieb:
> hört der clk einen zu früh auf
Was bedeutet "einer zu früh"?

BTW:
Entweder das:
 use ieee.std_logic_unsigned.all;
 use ieee.std_logic_arith.all;
Oder das:
 use ieee.numeric_std.all;
Aber niemals beide zusammen!
Früher oder später wirst du damit auf die Nase fallen.
Hier im Forum gibt es einige Beispiele davon...

Autor: None Blub (nioo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fehler gefunden der ist mir in einen Fall zu früh gesprungen mit 
variablen funktionierte das so wie ich es gemacht habe nicht.. hab die 
variable gegen signal ausgetauscht und noch was angepasst jetzt 
funktionierts..

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.