Hallo Forum, ich möchte ein einfaches Ausgangssignal mit einem CPLD ausgeben. Dieses soll abhängig von CLK=40MHz (clock cycle=25ns) und zwei Registersettings kreiert werden. Bräuchte mal nen Ansatz, da ich vhdl-Beginner bin, ich denke das ist rel. einfach... a) Das Signal z soll nur soviele CLK-cycles "high"=1 sein, wie es in Register1 (x) steht. b) Das Signal z so nachfolgend solange "low"=0 sein, wie es in Register2 (y) steht. Steht also in Register1 0100=4 und in Register2 0010=2 soll das Signal 4x25ns=100ns lang "high" sein und nachfolgend 2x25ns=50ns "low" sein. Danach startet das Signal von vorne: 100ns "high, 50ns "low" usw... Hab mal 2 Beispiele angehangen. Die Frage ist jetzt, wie ich hier vorgehe...Benutze ich für das Signal z einen vector oder benutze ich einen Zähler mit integer range oder...? THX for RE! jey
schau dir mal das Programm auf Lothar Miller seiner Seite an zum LED blinken. Das ist so ziemlich genau das was du suchst.
full well schrieb: > a) Das Signal z soll nur soviele CLK-cycles "high"=1 sein, wie es in > Register1 (x) steht. Wie sieht es aus, wenn da 0 steht? 0 Zyklen '1', also immer '0' am Ausgang? Aber wie sieht es aus, wenn in beiden Registern 0 steht?
Lothar Miller schrieb: > Wie sieht es aus, wenn da 0 steht? > 0 Zyklen '1', also immer '0' am Ausgang? > > Aber wie sieht es aus, wenn in beiden Registern 0 steht? gute Frage :) Da ich die Registerwerte per µC setzten möchte (8bit Datenbus), habe ich das ja eigendlich selbst in der Hand... Das Signal z muss mind. 100µs und darf max. 10ms "low" sein, was kleineres/größeres darf es nicht geben, wird etwas kleineres gesendet, wird es verworfen... Die "high"-Dauer liegt auch in festen Grenzen... Wie ich das sauber programmiere weiss ich noch nicht, da wende ich mich dann vertrauensvoll wieder an euch hehe... aber nochmal zurück zu meinem Anfangsproblem: Ich habe mal Anhand deiner Seite folgendes programmiert:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.STD_LOGIC_ARITH.ALL; |
4 | use IEEE.STD_LOGIC_UNSIGNED.ALL; |
5 | |
6 | entity z_gen is port( |
7 | clock: in std_logic; --40MHz |
8 | z: out std_logic); --output signal: synchron zu clock! |
9 | end z_gen; |
10 | |
11 | architecture z_timing of z_gen is |
12 | signal x_hightime : integer range 0 to 5:=0; --Anzahl clock-zyklen "high" |
13 | signal y_lowtime : integer range 0 to 5:=0; --Anzahl clock-zyklen "low" |
14 | signal t : std_logic := '0'; --flag für counter-end |
15 | |
16 | begin
|
17 | process begin |
18 | wait until rising_edge(clock); |
19 | if (x_hightime <4) then -- x<4? => x kleiner 4x25ns=100ns |
20 | x_hightime<=x_hightime+1; --zaehler+1 cycle |
21 | z<='1'; --output=high solange x_hightime<100ns |
22 | t<='0'; --flag=0 |
23 | else
|
24 | t<='1'; --flag=1 (high-time-ende) |
25 | end if; |
26 | |
27 | if(t='1') then --wenn high-time-ende zähle y hoch "low" |
28 | if(y_lowtime<4) then |
29 | y_lowtime<=y_lowtime+1; |
30 | z<='0'; |
31 | else
|
32 | y_lowtime<=0; --wenn beide zaehler fertig: restart x,y |
33 | x_hightime<=0; |
34 | end if; |
35 | end if; |
36 | end process; |
37 | |
38 | end z_timing; |
Allerdings zählt er immer einen "low" zuviel, bei den gegebenen settings high=4 und low=4 macht er 4 cycles "1" und 5 cycles "0"...wieso? siehe Anhang...
full well schrieb: > Allerdings zählt er immer einen "low" zuviel, bei den gegebenen settings > high=4 und low=4 macht er 4 cycles "1" und 5 cycles "0"...wieso? Latency. Weil du synchron bist, wirst du immer mindestens 1 high oder low haben. Das ist der, den du zuviel hast... Probiers mal so:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity BlinkHiLo is |
6 | Port ( clk : in STD_LOGIC; |
7 | outp : out STD_LOGIC; |
8 | hi : in STD_LOGIC_VECTOR (3 downto 0); |
9 | lo : in STD_LOGIC_VECTOR (3 downto 0)); |
10 | end BlinkHiLo; |
11 | |
12 | architecture Behavioral of BlinkHiLo is |
13 | signal cnt : integer range 0 to 15 := 1; |
14 | signal o : std_logic := '0'; |
15 | begin
|
16 | process begin |
17 | wait until rising_edge(clk); |
18 | cnt <= cnt+1; |
19 | if (o='0' and cnt=to_integer(unsigned(lo))) then |
20 | cnt <= 1; -- bei 1 beginnen wegen Latency |
21 | o <= '1'; |
22 | end if; |
23 | if (o='1' and cnt=to_integer(unsigned(hi))) then |
24 | cnt <= 1; -- bei 1 beginnen wegen Latency |
25 | o <= '0'; |
26 | end if; |
27 | -- if (to_integer(unsigned(lo))=0) then -- Dauer-High
|
28 | -- o <= '1';
|
29 | -- end if;
|
30 | -- if (to_integer(unsigned(hi))=0) then -- Dauer-Low
|
31 | -- o <= '0';
|
32 | -- end if;
|
33 | end process; |
34 | outp <= o; |
35 | end Behavioral; |
hm, passt doch nicht so 100% :/ Die Sache ist jetzt folgende: Ich möchte die lowtime nur in 100µs-Steps einstellen. Der Bereich in der sich die lowtime befindet, soll zwischen 100µs bis 10ms einstellbar sein. Das würde aber bei CLK=40MHz->10ms/25ns=400.000 clockcycles entsprechen, wofür ich ein 19bit-Register benötigen würde, was ich aber definitiv nicht möchte (16bit Registertiefe is absolutes max.) und ich benötige so eine große Auflösung auch garnicht. Mein Ziel ist es also, über das low-Register die lowtime in 100µs-Steps einstellen zu können. Meine Idee war jetzt, ich multipliziere einfach den Registerwert mit 4.000. Steht also im Register eine "1"=0001, würde diese mit 4000 multipliziert werden, was wiederum eine lowtime von 100µs bedeuten würde (4000x25ns=100µs), bei einer "2"=0010 wären es 200µs,... bei "100"=1100100 wäre das maximum=10ms erreicht. Das Register müsste also max. 7bit tief sein. Allerdings scheint mich diese Multiplikation NULL weiterzubringen, sie funktioniert zwar in der Theorie (Modelsim), auf meinem CPLD ist aber nicht genügend Platz für diese Berechnung...verbraucht extrem viele Marcozellen, ich habe nur 144 :) Hier mein Code:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity topModule_19 is |
6 | Port ( CLK : in STD_LOGIC; |
7 | MSP : out STD_LOGIC; |
8 | DATA7 : in std_logic; |
9 | DATA6 : in std_logic; |
10 | DATA5 : in std_logic; |
11 | DATA4 : in std_logic; |
12 | DATA3 : in std_logic; |
13 | DATA2 : in std_logic; |
14 | DATA1 : in std_logic; |
15 | DATA0 : in std_logic; |
16 | --hightime=41580MCLK
|
17 | hi : in STD_LOGIC_VECTOR (15 downto 0):="1010001001101100"; |
18 | --lowtime=100µs=4000x1x25ns
|
19 | lo : in STD_LOGIC_VECTOR (6 downto 0):="0000001"); |
20 | end topModule_19; |
21 | |
22 | architecture Behavioral of topModule_19 is |
23 | signal cnt : integer range 0 to 65535 := 1; |
24 | signal o : std_logic := '0'; |
25 | begin
|
26 | process begin |
27 | wait until rising_edge(clk); |
28 | cnt <= cnt+1; |
29 | --Auflösung high=itime=100µs (25ns*4000=100µs)
|
30 | if (o='0' and cnt=4000 * to_integer(unsigned(lo))) then |
31 | cnt <= 1; -- bei 1 beginnen wegen Latency |
32 | o <= '1'; |
33 | end if; |
34 | if (o='1' and cnt=to_integer(unsigned(hi))) then |
35 | cnt <= 1; -- bei 1 beginnen wegen Latency |
36 | o <= '0'; |
37 | end if; |
38 | end process; |
39 | MSP <= o; |
40 | end Behavioral; |
Wie bekomme ich eine Auflösung von 100µs für die lowtime ohne das das meinen CPLD sprengt?
full well schrieb: > würde diese mit 4000 multipliziert Auf der Hardware können nur 2er-Potenzen durch simple Umverdrahtung optimiert werden! Probiers mal mit 4096...
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.