Hallo... Habe eine Frage zur Weiterverarbeitung eines PWM-Signals. Habe einen Sensor der ein PWM Signal ausgibt. Dieses möchte ich mit einer bestimmten Frequenz abtasten, um somit einen Wert zuerhalten den ich weiterverarbeiten kann. Derzeit habe ich ein PWM-Signal mit einer Pulsbreite von 1ms und einer Periodendauer von 20ms. Ich habe mir gedacht ich lasse einen Zähler mit einer Frequenz von 1MHz hochzählen solange der Puls anliegt. Und kann somit weiterarbeiten. Allerdings habe ich noch keine Möglichkeit gefunden wie ich den Wert speichern kann, da ja vom Sensor gleich wieder eine Veränderung übermittelt werden kann. Vielleicht kann mir jemand einen guten ratschlag geben. Hänge meine Idee einfach mal mit dazu. Gruß Ronny -- STANDARD LIBRARIES -- LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; -- BEGIN OF ENTITY -- ENTITY Sensor_REG IS -- GLOBAL VARIABLE MAX-COUNT (Periodendauer 20 ms) -- PORT ( -- GLOBAL CLOCK OF MAX II ALTERA -- glb_clk: IN BIT; -- CLOCK FOR DISTANCE MEASUREMENT 1 MHz -- en: IN STD_LOGIC; -- GLOBAL RESET USER PUSH BUTTON S1 -- nReset: IN BIT; -- RESULT works -- --readyREG: IN BIT; -- PULS WIDE -- data_in: IN BIT; -- DATA OUT -- wide_out: OUT INTEGER range 0 to 2**12-1 ); END Sensor_REG; -- END OF ENTITY -- -- BEGIN OF ARCHITECTURE -- ARCHITECTURE Result OF Sensor_REG IS TYPE STATE_TYPE IS (POWER_ON_DELAY, INITIALIZE); SIGNAL state: STATE_TYPE; BEGIN PROCESS (glb_clk, nReset, en, data_in) variable count: integer range 0 to 2**12-1:= 0; BEGIN IF (nReset = '0') THEN count := 0; state <= POWER_ON_DELAY; -- GENERATING NEW CLOCK -- ELSIF (glb_clk'EVENT AND glb_clk='1') THEN -- START OF INITIALIZATION -- IF en = '1' THEN CASE state IS -- BEGINNING OF INITIALIZATION -- WHEN POWER_ON_DELAY=> IF data_in = '1' THEN count := count + 1; ELSE wide_out <= save; state<=INITIALIZE; END IF; WHEN INITIALIZE=> wide_out <= count; count := 0; state <= POWER_ON_DELAY; END case; ELSE count := count; END IF; END IF; END PROCESS; END Result; -- END OF ARCHITECTURE --
Naja, prinzipiell würde ich dein PWM Signal als Trigger nehmen und deine Speicheroperation darauf synchronisieren. Bei positiver PWM Flanke resettest du deinen 1 MHz Zähler, bei negativer Flange nimmst du den aktuellen Zählerwert und machst deine Speicheroperation (wohin auch immer...) So hast du immer die aktuelle Pulsbreite verarbeitet.
Da ich vhdl nicht mag, weil ich es nicht lesen kann, hier mein Ansatz in verilog: input clk_1mhz; input pwm_in; output [13:0] data_out; reg [13:0] data_out_reg; reg [13:0] counter; reg pwm_in_buf; always @ (negedge clk_1mhz) begin pwm_in_buf <= pwm_in; end always @ (posedge clk_1mhz) begin // reset counter at pwm_in negedge else increment counter <= (pwm_in & ~pwm_in_buf) ? 0 : counter + 1; end always @ (negedge pwm_in) begin data_out_reg <= counter; end assign data_out = data_out_reg; Wenn deine Pulsbreite doch mal breiter sein sollte als 1ms, muss dein Zähler übrigens 14 Bit breit werden, da 1 MHz / 50 einen Maximalwert von 20000 ergibt, und das passt in 12 Bit ja nicht rein.
Zu deinem Code:: Statt PROCESS (glb_clk, nReset, en, data_in) reicht PROCESS (glb_clk, nReset) Ich würde es so machen: PROCESS (glb_clk) variable datainlast: bit; -- fuer Flankenauswertung variable count2: integer range 0 to 2**12-1:= 0; BEGIN IF rising_edge(glb_clk) THEN IF (nReset = '0') THEN -- synchroner Reset (wenn schon) count := 0; ELSIF (en = '1') THEN datainlast <= data_in; IF data_in = '1' THEN -- zaehlen solange High count1 := count1 + 1; ELSIF datainlast = '1' THEN -- fallende Flanke wide_out <= count1; END IF; END IF; END IF; END PROCESS; @Tim R. >always @ (negedge pwm_in) ist eine zweite Taktdomäne. Macht bei FPGAs fast ausschliesslich Probleme.
Das Zurücksetzen vom Counter hat noch gefehlt. Und dann ersetzen wir sämtliche count1 und count2 durch count, dann gehts ;-) : ELSIF datainlast = '1' THEN -- fallende Flanke wide_out <= count; count <= 0; -- zurücksetzen END IF; :
>>always @ (negedge pwm_in) >>ist eine zweite Taktdomäne. >Macht bei FPGAs fast ausschliesslich Probleme. stimmt. kein guter ansatz.
>>Macht bei FPGAs fast ausschliesslich Probleme. >stimmt. kein guter ansatz. Bei der Beachtung rudimentärer Designrichtlinien macht das gar keine Probleme.
>Bei der Beachtung rudimentärer Designrichtlinien >macht das gar keine Probleme. pwm_in ist asynchron zu glb_clk. So definiere ich ein Problem. Wenn für dich "rudimentäre Designrichtlinien" so definiert sind, dass pwm_in vorher auf glb_clk synchronisiert wurde, dann gebe ich dir Recht.
-es ist doch egak, wie Du es machts: Am Ende wird Deine PWM mit der Taxtfrequenz des FPGA quantisiert.
@Harald: Ne, Lothar hat da schon ganz recht. Es ist nicht sichergestellt, dass pwm_in nicht gleichzeitig mit einem counter increment eine negative flanke hat, und in dem Fall ist unklar, in welchem Zustand der counter ist. = Problem. Man kann das natürlich lösen, aber da ja bereits eine funktionierende VHDL Lösung da steht, verzichte ich darauf.
Hey Lothar Miller (lkmiller)... Habe deinen Code probiert, und der funktioniert sehr gut. Danke nochmal. Hat mir sehr weiter geholfen. HAbe dabei auch meinen eigenen Fehler erkannt. So hatte ich es mir gedacht. In der Simulation zählt der wunderbar hoch und ich könnte mit dem Zählerstand weiter arbeiten. Allerdings wenn ich mein weiteres Programm, zum Beispiel die LCD anzeige mit einbinde, kann ich die Ausgabedaten nicht nutzen (wide_out). Kann das sein das diese Daten nicht lange genug anliegen, zur Verfügung stehen, und ich diese vielleicht nochmal speichern muss. Ciao
Hey Lothar Miller (lkmiller)... Ich habe da nochmal eine Frage zu deinem Syntax. Du nutzt ja "datainlast", wo du nochmal eine Flanke abfragst, mit welchem Hintergrund benötige ich die genau. Ciao
Ronny wrote:
> Habe deinen Code probiert, und der funktioniert sehr gut.
Das wundert mich fast etwas...
Der ist ja ko***bel...
Wieso hatte ich bei meinem ersten Post eigentlich variable drin?
Das müssen signale sein, ich hasse variable...
Da kam sicher vom copy&paste :-(
Und den reset habe ich jetzt auch pensioniert, das geht auch ohne.
Jetzt gefällt mir der code besser....
1 | :
|
2 | signal dsr: std_logic_vector(3 downto 9); -- fuer Flankenauswertung |
3 | signal count: integer range 0 to 2**12-1:= 0; |
4 | :
|
5 | PROCESS (glb_clk) |
6 | BEGIN
|
7 | IF rising_edge(glb_clk) THEN |
8 | IF (en = '1') THEN -- 1MHz |
9 | dsr <= dsr(2 downto 0) & data_in; -- Schieberegister |
10 | IF (data_in='1') THEN -- zaehlen solange High |
11 | count <= count + 1; |
12 | END IF; |
13 | IF (dsr="1100") THEN -- fallende Flanke |
14 | wide_out <= count; -- Ausgabewert aktualisieren |
15 | count <= 0; -- und Zähler löschen |
16 | END IF; |
17 | END IF; |
18 | END IF; |
19 | END PROCESS; |
20 | :
|
> Ich habe da nochmal eine Frage zu deinem Syntax. > Du nutzt ja "datainlast", wo du nochmal eine Flanke abfragst, mit > welchem Hintergrund benötige ich die genau. Ciao Die Idee ist, nur bei der fallenden Flanke den Ausgabewert abzuspeichern.
>um Beispiel die LCD anzeige mit einbinde, >kann ich die Ausgabedaten nicht nutzen (wide_out). >Kann das sein das diese Daten nicht lange genug anliegen, >und ich diese vielleicht nochmal speichern muss. Klar: das Display weiß nichts von der PWM und andersrum genauso. Die beiden laufen einfach nur irgendwie vor sich hin. Deshalb musst du die Daten für die Ausgabe noch einmal zwischenspeichern, oder das Abspeichern nach wide_out anderweitig mit der Ausgabe synchronisieren.
Hi..... Bei dieser Zeile: "dsr <= dsr(2 downto 0) & data_in;" kommt folgende Meldung: Error (10327): VHDL error at Sensor_Reg.vhd(82): can't determine definition of operator ""&"" -- found 0 possible definitions Kann das daran liegen das da versucht wird einen Std_Logic_Vector mit einer Bit Variable zu verknüpfen? Wenn ich das & durch ein AND ersetze. Dabei bin total überfordert :) Error (10476): VHDL error at Sensor_Reg.vhd(82): type of identifier "data_in" does not agree with its usage as std_logic_vector type Wenn ich die & Operation herausnehme, kann ich compilieren allerdings bekomme ich noch ein Warning: Bei dieser Zeile " IF (dsr="1100") THEN " kommt diese Meldung: Warning (10620): VHDL warning at Sensor_Reg.vhd(86): comparison between unequal length operands always returns FALSE Total unverständlich. Vielleicht sagt es dir etwas. Ciao
Hi.. "&" ist eine "Anhängung", keine "Verundung". Lösung: erst data_in nach std_logic konvertieren: "lesenswert": http://dz.ee.ethz.ch/support/ic/hdl/vhdlsources.en.html Gruß Joko
>Kann das daran liegen das da versucht wird einen Std_Logic_Vector mit >einer Bit Variable zu verknüpfen? Ja, du mußt data_in noch konvertieren/casten. >Lösung: erst data_in nach std_logic konvertieren: Oder noch besser: verwende nur std_logic(_vector) und integer, und das Leben wird einfach. Gut, das wird nicht immer klappen, aber den Versuch ist es wert... Der &-Operator ist (wie von Joko schon gesagt) eine Concatenation, keine logische Operation.
>Wenn ich die & Operation herausnehme, kann ich compilieren allerdings >bekomme ich noch ein Warning: >Bei dieser Zeile " IF (dsr="1100") THEN " kommt diese Meldung: >Warning (10620): VHDL warning at Sensor_Reg.vhd(86): comparison between >unequal length operands always returns FALSE Im Code von Lothar hat sich ein kleiner Tippfehler eingeschlichen >signal dsr: std_logic_vector(3 downto 9); müsste heissen: signal dsr: std_logic_vector(3 downto 0); dann müsste die Warnung verschwinden Gruß Chris
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.