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


von Reiner.H (Gast)


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

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


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...

von Reiner.H (Gast)


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?

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


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".

von Reiner.H (Gast)


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?

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


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.
1
elsif CLK'Event and CLK = '1' then
2
    if DATA(DATA'left)='0' then
3
          DATA <= DATA(DATA'left-1 downto 0) & DAT;
4
    else
5
       ...                -- Daten weitergeben
6
       DATA <= "0000001"; -- und Schieberegister initialisieren
7
    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.

von Reiner.H (Gast)


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!

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


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.

von Reiner.H (Gast)


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..

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


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?

von Reiner.H (Gast)


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..

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


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...

von Reiner.H (Gast)


Angehängte Dateien:

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..

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


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.

von Reiner.H (Gast)


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..

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


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?

von Reiner.H (Gast)


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..

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


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...

von newbie (Gast)


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..

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


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.

von newbie (Gast)


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..

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


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ß...

von None B. (nioo)


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..
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
use ieee.std_logic_arith.all;
5
use ieee.numeric_std.all;
6
7
entity Encoder is
8
  port  (   RESN           : in std_logic;
9
        CLK          : in std_logic;  
10
        DATA_ENCODER    : in std_logic;  -- 13 Bits  Empfangen
11
        EN1          :   OUT STD_LOGIC;
12
        EN2          :   OUT STD_LOGIC;  
13
        CLK_OUT        : out std_logic;  -- an den Drehgeber
14
        ENCODER_POSITON  : out std_logic_vector(12 downto 0):= (others => '0') --zum NIOS um die Lage zu erkennen
15
      );
16
end Encoder;
17
18
architecture Behavioral  of Encoder is
19
20
  signal CLK_COUNT           : std_logic_vector (6 downto 0) := (others => '0'); --64bit
21
  signal FLAG_WAIT_PERIOD      : std_logic;
22
  signal Flanke            : std_logic;
23
  signal wait_count          : std_logic_vector (7 downto 0) := (others => '0');
24
  signal wait_flag          : std_logic;  
25
  signal DATA              : std_logic_vector (12 downto 0) := (others => '0');
26
  signal temp              : std_logic_vector (12 downto 0) := (others => '0');
27
  signal TEST              : std_logic;
28
  
29
begin
30
31
  process (CLK, RESN)
32
    
33
    variable counter        : integer range 0 to 13;
34
35
    begin      
36
      
37
      if RESN   =  '0' then      
38
        CLK_OUT    <= '0';
39
        wait_flag <= '0';
40
        Flanke   <= '0';
41
      elsif CLK'Event and CLK = '1' then      
42
        -----------------------------------------------------------------  
43
        if(wait_flag = '0') then
44
          CLK_COUNT <= CLK_COUNT + 1; 
45
        else
46
          wait_count <= wait_count+1;        
47
        end if;        
48
        CLK_OUT <= CLK_COUNT(5);
49
        
50
        -----------------------------------------------------------------  
51
        if (CLK_COUNT(5) = '1') then
52
          if(counter = 13) then
53
              temp <= DATA;
54
            if(wait_count >= 120) then
55
              wait_flag   <= '0';
56
              wait_count  <= (others=>'0');              
57
              CLK_COUNT   <= (others=>'0');
58
              DATA   <= (others=>'0');
59
              counter     := 0;
60
            else
61
              wait_flag <= '1';
62
            end if;
63
          end if;            
64
          Flanke <= '1';
65
        -----------------------------------------------------------------    
66
        else
67
          if Flanke = '1' then          
68
            if(counter /= 13) then               
69
              DATA(counter) <= DATA_ENCODER;
70
              counter := counter + 1;              
71
            end if;          
72
            Flanke <= '0';            
73
          end if;
74
        
75
        end if;
76
        -----------------------------------------------------------------  
77
        if (counter = 13) and (DATA_ENCODER = '0') then
78
          ENCODER_POSITON(12 downto 0) <= temp(12 downto 0);
79
        end if;
80
      end if;        
81
        
82
  end process;
83
  
84
end Behavioral;

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


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...

von None B. (nioo)


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..

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.