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
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...
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?
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".
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?
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.
' 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!
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.
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..
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?
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..
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...
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..
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.
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..
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?
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..
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...
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..
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.
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..
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ß...
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; |
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.