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?
Blubb schrieb:> Warum nicht einen UART oder SPI core nehmen und gescheit verschalten &> parametretisieren?
Darueber bin ich auch schon gestolpert. Im Prinzip suche ich sowas.
Ich bin aber Anfaenger, was VHDL betrifft und aus den Beispielen kann
ich mir die Funktion nicht immer komplett herleiten.
Deswegen suche ich was Einfaches und Nachvollziebares.
--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
endif;
15
if(count_q/=T_count_idx'low)then--decrement as long lower boundary reached
16
count_q<=count_q-1;
17
endif;
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.
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:
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.
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...
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:
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
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).
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:
--sr_trigger <= sr_trigger(1 downto 0) & in_trigger when rising_edge(clk);
32
33
processbegin
34
waituntilrising_edge(clk);
35
sr_pattern<=sr_pattern(62downto0)&'1';
36
iftrigger='1'then
37
sr_pattern<=PATTERN;
38
endif;
39
endprocess;
40
41
serial_out<=sr_pattern(63);
42
43
endBEHAVIOR;
Und Testbench:
1
libraryieee;
2
useieee.std_logic_1164.all;
3
useieee.numeric_std.all;
4
5
entityTESTis
6
endTEST;
7
8
architectureBEHAVIORofTESTis
9
signalCLK:std_logic;
10
signalserial_out:std_logic;
11
12
componentPULSER
13
port(CLK:instd_logic;
14
serial_out:outstd_logic);
15
endcomponent;
16
17
forall:PULSERuseentitywork.PULSER(BEHAVIOR);
18
begin
19
20
Clock:processbegin
21
CLK<='0';
22
waitfor100ns;
23
CLK<='1';
24
waitfor100ns;
25
endprocessClock;
26
27
C1:PULSERportmap(CLK,serial_out);
28
endBEHAVIOR;
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?
Mark W. schrieb:> Ist das die Verbindung vom Testbench, wo das DUT quasi angedockt wird?
Ja: du erzeugst damit in der Testbench eine Instanz deiner Komponente
Pulser.
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".
Danke Euch Beiden, ich glaube, ich habe es verstanden mit der Instanz.
Ich kann den Namen offenbar frei waehlen, deswegen hatte ich mich
Anfangs gewundert, weil das nirgends auftaucht.
Und in meinem Buch steht nur, dass deklarierte Signale als aktuelle
Signale an die als Komponente C1 platzierte Entity uebergeben werden.
Ja, gute Idee.
Mir ist auch schon aufgefallen, dass es viele verschiedene
"Schreibstile" und Hervorhebungsmerkmale gibt.
Auch mit dem Einruecken muss man erstmal klarkommen.
Ich achte darauf, was mir am Besten entgegen kommt.
Mark W. schrieb:
C1: PULSER port map(CLK, serial_out);
Ich empfehle hier, nicht die implizite Zuordnung per Position zu nehmen,
sondern explizit den Port dem Signal zuzuordnen:
C1: PULSER port map(CLK=>CLK, serial_out=>serial_out);