Bitfolge getriggert ausgeben

OP Persönliche Seite #5706358
Lesenswert?

Hallo,

ich moechte mit einem FPGA eine 64-stellige Bitfolgen ausgeben.
Die Bitlaenge soll 100ns betragen. Sonst ist das Signal high.
Die Ausgabe soll getriggert erfolgen.
Also benoetige ich ein Modul, mit zwei Eingaengen und einem Ausgang.
Die Bitfolge soll im VHDL code als Konstante hinterlegt werden.

Jetzt weis ich nicht so recht wie ich anfangen soll.
Ich habe zwei Ansaetze um die ich mich erstal kuemmern werde:
1. Einen Parallel-Reihen Umsetzer, wo die Eingaenge mit konstanten 
Signalen belegt sind. Wie ich diesen allerdings triggerbar mache, weis 
ich noch nicht.
2. Einen Zaehler nehmen und eine LUT. Bei der LUT trage ich dann meine 
gewuenschte Bitfolge ein und ich benoetige einen Zaehler, der beim 
Triggersignal einmal durchlaeuft und dann wieder auf den naechsten 
Triggerimpuls warted.

Geht das vielleicht auch einfacher, wie wurdet Ihr das machen?
Gast #5706364
Lesenswert?

qnd-snippets und ohne Garantie auf Tippfehler die wesentlichen 
Teilfunktionalitäten.
1
--Deklaration counter und ROM
2

3
constant ROM is std_logic_vector(63 downto 0) := x"FFFFFFFFFFFFFFFF";
4
subype T_count_idx is natural range 63 downto 0;
5
signal count_q:T_count_idx := T_count_idx'low;
6

7
--Steigende Flanke Trigger erkennen und einmal (run once) durchzählen:
8

9
--innerhalb getakteten process
10
trig_in_del_q <= trig_in;
11

12
if (trig_in_del_q = '0') and (trig_in = '1') then  --start count ny Loading index of MSb
13
 count_q <= T_count_idx'high;
14
end if;
15
if (count_q /= T_count_idx'low) then  --decrement as long lower boundary reached
16
 count_q <= count_q - 1;
17
end if;
18

19

20

21
--64x1 ROM auslesen
22

23
data_out <= ROM(count_q);  --bit-counter is also address of ROM

Da fehlt noch jede menge drumherum (entity, architectur  Rahmen) aber 
das sollte mensch der guten Willens ist, einer VHDL-Syntax Beschreibung 
oder Beispielen entnehmen können.
Moderator (Firma: Titel) Persönliche Seite #5706381
Lesenswert?

Mark W. schrieb:
> Die Ausgabe soll getriggert erfolgen.
Woher kommt der Trigger? Wie lange ist der aktiv? Wenn der auch nur für 
1 Taktzyklus aktiv ist, dann ist es einfacher, sonst muss eine 
Flankenerkennung eingebaut werden. Und was soll passieren, wenn während 
der Übertragung erneut ein Trigger kommt: ignorieren, sofortiger 
Neustart der Übertragung oder Neustart nach Ende der Übertragung?

> 1. Einen Parallel-Reihen Umsetzer, wo die Eingaenge mit konstanten
> Signalen belegt sind. Wie ich diesen allerdings triggerbar mache, weis
> ich noch nicht.
Mal angenommen, der Trigger käme von extern, dann muss er 
einsynchronisiert und dann die Flanke erkannt werden. Mit der steigenden 
Flanke wird dann das Schieberegister geladen, sonst wird dauernd von 
rechts eine '1' eingeschoben:
1
:
2
constant PATTERN : std_logic_vector(63 downto 0) := x"1234567890abcdef";
3
signal sr_pattern : std_logic_vector(63 downto 0) : (others => '1');
4
signal sr_trigger : std_logic_vector(2 downto 0) : (others => '0');
5
:
6
   -- Trigger für Flankenerkennung einsynchronisieren 
7
   sr_trigger <= sr_trigger(1 downto 0) & in_trigger when rising_edge(clk);
8

9
   process begin
10
      wait until rising_edge(clk);
11
      -- ständig von rechts eine '1' einschieben
12
      sr_pattern <= sr_pattern(62 downto 0) & '1';
13
      if sr_trigger(2 downto 1)="01" then  -- aber bei steigender Flanke: Schieberegister laden
14
         sr_pattern <= PATTERN;
15
      end if;
16
   end process;
17
   
18
   serial_out <= sr_pattern(63);
19
:
OP Persönliche Seite #5706413
Lesenswert?

Danke Euch Beiden fuer die Beispiele. Ich sehe mir das mal an und 
versuche es umzusetzen.

Lothar M. schrieb:
> Mark W. schrieb:
>> Die Ausgabe soll getriggert erfolgen.
> Woher kommt der Trigger? Wie lange ist der aktiv? Wenn der auch nur für
> 1 Taktzyklus aktiv ist, dann ist es einfacher, sonst muss eine
> Flankenerkennung eingebaut werden.

Ich denke CLK wird 10MHz sein. Dann wollte ich mir mit einem Taktteiler 
den Trigger generieren, also syncron mit CLK. Benoetigen tue ich bis 
10kHz. Der Triggerpuls ist also laenger als die Bitfolge selbst.

> Und was soll passieren, wenn während
> der Übertragung erneut ein Trigger kommt: ignorieren, sofortiger
> Neustart der Übertragung oder Neustart nach Ende der Übertragung?
>
Kann ich erstmal ignorieren, weil ich das ausschliesse.
Moderator (Firma: Titel) Persönliche Seite #5706428
Lesenswert?

Mark W. schrieb:
> Ich denke CLK wird 10MHz sein. Dann wollte ich mir mit einem Taktteiler
> den Trigger generieren, also syncron mit CLK. Benoetigen tue ich bis
> 10kHz. Der Triggerpuls ist also laenger als die Bitfolge selbst.
Wenn du es schlau anstellst, dann nicht. Denn dann generierst du dir den 
Triggerimpuls so, dass er genau einen Taktzyklus lang aktiv ist. So 
funktioniert synchrones Design am einfachsten...
1
:
2
constant PATTERN : std_logic_vector(63 downto 0) := x"1234567890abcdef";
3
signal sr_pattern : std_logic_vector(63 downto 0) : (others => '1');
4
signal trigger : std_logic : '0';
5
signal trigger_cnt : integer range 0 to 1000000 := 0;
6
:
7
   -- Triggerimpuls erzeugen
8
   process begin
9
      wait until rising_edge(clk);
10
      trigger_cnt <= trigger_cnt+1;
11
      trigger     <= '0';
12
      if trigger_cnt=999999 then  -- Zeit abgelaufen
13
         trigger_cnt <= 0;
14
         trigger     <= '1';      -- trigger für 1 Taktzyklus aktiv
15
      end if;
16
   end process;
17

18
   -- Trigger für Flankenerkennung einsynchronisieren 
19
   sr_trigger <= sr_trigger(1 downto 0) & in_trigger when rising_edge(clk);
20

21
   process begin
22
      wait until rising_edge(clk);
23
      -- ständig von rechts eine '1' einschieben
24
      sr_pattern <= sr_pattern(62 downto 0) & '1';
25
      if trigger='1' then  -- mit Trigger: Schieberegister laden
26
         sr_pattern <= PATTERN;
27
      end if;
28
   end process;
29
   
30
   serial_out <= sr_pattern(63);
31
:
OP Persönliche Seite #5706996
Lesenswert?

Ich habe jetzt mal den Code von Lothar versucht, aber es geht nicht.
Ich bekomme immer Fehlermeldungen bezueglich der Deklaration der 
Signale.
Hier ist mein VHDL Code:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4

5
entity PULSER is
6

7
  port(
8
    clk  : in  std_logic;
9
    serial_out : out std_logic);
10

11
end PULSER;
12

13
architecture BEHAVIOR of PULSER is
14

15
  constant PATTERN : std_logic_vector(63 downto 0) := x"aaaaaaaaaaaaaaaa";
16
  signal sr_pattern : std_logic_vector(63 downto 0) : (others => '1');
17
  signal trigger : std_logic : '0';
18
  signal trigger_cnt : integer range 0 to 1000000 := 0;
19
begin
20
  
21
process begin
22
    wait until rising_edge(clk);
23
    trigger_cnt <= trigger_cnt+1;
24
    trigger <= '0';
25
    if trigger_cnt=999999 then
26
       trigger_cnt <= 0;
27
       trigger <= '1';
28
    end if;
29
end process;
30
  
31
  sr_trigger <= sr_trigger(1 downto 0) & in_trigger when rising_edge(clk);
32
  
33
process begin
34
    wait until rising_edge(clk);
35
    sr_pattern <= sr_pattern(62 downto 0) & '1';
36
    if trigger = '1' then
37
       sr_pattern <= PATTERN;
38
    end if;
39
end process;
40
  
41
serial_out <= sr_pattern(63);
42
  
43
end BEHAVIOR;
Und hier die Fehlermeldungen:

ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(16,52-16,53) 
(VHDL-1261) syntax error near :
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(23,3-23,14) 
(VHDL-1241) trigger_cnt is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(24,3-24,10) 
(VHDL-1241) trigger is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(26,6-26,17) 
(VHDL-1241) trigger_cnt is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(27,6-27,13) 
(VHDL-1241) trigger is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(25,6-25,17) 
(VHDL-1241) trigger_cnt is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(31,2-31,12) 
(VHDL-1241) sr_trigger is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(35,3-35,13) 
(VHDL-1241) sr_pattern is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(37,6-37,16) 
(VHDL-1241) sr_pattern is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(36,6-36,13) 
(VHDL-1241) trigger is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(41,15-41,25) 
(VHDL-1241) sr_pattern is not declared
ERROR - 
C:/AllMyFiles/LatticeDiamondProjects/Pulser01/pulser.vhd(13,1-43,14) 
(VHDL-1284) unit behavior ignored due to previous errors
Moderator (Firma: Titel) Persönliche Seite #5707017
Lesenswert?

Mark W. schrieb:
> signal sr_pattern : std_logic_vector(63 downto 0) : (others => '1');
> signal trigger : std_logic : '0';
Ja, da fehlen wohl noch 2 '=' Zeichen. Aber keine Sorge, du findest den 
richtigen Platz. Einfach mal die Zeile drüber oder drunter anschauen... 
;-)

Und den sr_trigger gibt es wie den in_trigger in der zweiten Variante 
nicht mehr, weil er nicht mehr nötig ist. Fazit: einfach die unnötige 
Eintakterei rauslöschen. Und dann sieht das nicht mehr so schlecht aus 
(zur Beschleunigung der Simulation zähle ich nur 1000 Pulse und starte 
neu).
Angehängte Dateien:
OP Persönliche Seite #5708076
Lesenswert?

Ich habe es jetzt bis zur Simulation hinbekommen.
Danke schon mal bis hierher. Jetzt kann ich mit den Parametern spielen 
und mir die Funktionen klar machen.
Hier ist dann der Code fuer die angehaengte simulation:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4

5
entity PULSER is
6

7
  port(
8
    clk  : in  std_logic;
9
    serial_out : out std_logic);
10

11
end PULSER;
12

13
architecture BEHAVIOR of PULSER is
14

15
  constant PATTERN : std_logic_vector(63 downto 0) := x"0123456789abcdef";
16
  signal sr_pattern : std_logic_vector(63 downto 0) := (others => '1');
17
  signal trigger : std_logic := '0';
18
  signal trigger_cnt : integer range 0 to 1000000 := 0;
19
begin
20
  
21
process begin
22
    wait until rising_edge(clk);
23
    trigger_cnt <= trigger_cnt+1;
24
    trigger <= '0';
25
    if trigger_cnt = 1000 then
26
       trigger_cnt <= 0;
27
       trigger <= '1';
28
    end if;
29
end process;
30
  
31
  --sr_trigger <= sr_trigger(1 downto 0) & in_trigger when rising_edge(clk);
32
  
33
process begin
34
    wait until rising_edge(clk);
35
    sr_pattern <= sr_pattern(62 downto 0) & '1';
36
    if trigger = '1' then
37
       sr_pattern <= PATTERN;
38
    end if;
39
end process;
40
  
41
serial_out <= sr_pattern(63);
42
  
43
end BEHAVIOR;

Und Testbench:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4

5
entity TEST is
6
end TEST;
7

8
architecture BEHAVIOR of TEST is
9
signal CLK: std_logic;
10
signal serial_out: std_logic;
11

12
component PULSER
13
  port(  CLK:     in   std_logic;
14
      serial_out: out std_logic);
15
end component;
16

17
for all: PULSER use entity work.PULSER(BEHAVIOR);
18
begin
19

20
Clock: process begin
21
  CLK <=   '0';
22
  wait for 100 ns;
23
  CLK <= '1';
24
  wait for 100 ns;
25
end process Clock;
26

27
C1: PULSER port map(CLK, serial_out);
28
end BEHAVIOR;

Allerdings ist mir eine Sache nicht ganz klar, und zwar was C1 in der 
vorletzten Zeile vom Testbench bedeutet.
Ist das die Verbindung vom Testbench, wo das DUT quasi angedockt wird?
Angehängte Dateien:
Moderator (Firma: Titel) Persönliche Seite #5708459
Lesenswert?

Mark W. schrieb:
> was C1 in der vorletzten Zeile vom Testbench bedeutet.
Dort wird eine Instanz namens C1 der zuvor bekannt gegebenen Komponente 
PULSER angelegt.
Das ist exakt das selbe, wie auch andere Untermodule in einem darüber 
liegenden VHDL
Modul eingebunden werden.

Eine Testbench ist verglichen mit anderen VHDL Modulen aber einfach zu 
erkennen: die Entity hat keine Ports, also keine Verbindung "nach 
außen".
Gast #5708551
Lesenswert?

Zur Unterscheidung bekommen bei mir (fast) alle Signale in der Testbench 
den Präfix 'tb_':
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4

5
entity TEST is
6
end TEST;
7

8
architecture BEHAVIOR of TEST is
9
signal tb_CLK: std_logic;
10
signal tb_serial_out: std_logic;
11

12
component PULSER
13
  port(  CLK:     in   std_logic;
14
      serial_out: out std_logic);
15
end component;
16

17
for all: PULSER use entity work.PULSER(BEHAVIOR);
18
begin
19

20
Clock: process begin
21
  tb_CLK <=   '0';
22
  wait for 100 ns;
23
  tb_CLK <= '1';
24
  wait for 100 ns;
25
end process Clock;
26

27
C1: PULSER port map(tb_CLK, tb_serial_out);
28
end BEHAVIOR;

Duke

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren