Forum: FPGA, VHDL & Co. VHDL: "einfach" Signalerzeugung


von Full W. (realjey)


Angehängte Dateien:

Lesenswert?

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

von P. S. (sw1ft)


Lesenswert?

schau dir mal das Programm auf Lothar Miller seiner Seite an zum LED 
blinken. Das ist so ziemlich genau das was du suchst.

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


Lesenswert?

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?

von Full W. (realjey)


Angehängte Dateien:

Lesenswert?

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

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


Lesenswert?

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;

von Full W. (realjey)


Lesenswert?

das passt einwandfrei :) thx!

von Full W. (realjey)


Lesenswert?

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?

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


Lesenswert?

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
Noch kein Account? Hier anmelden.