Forum: FPGA, VHDL & Co. Funktionsplan in VHDL übersetzen


von Monty M. (monty87)


Angehängte Dateien:

Lesenswert?

Hi Leute,

ich möchte gerne die Schaltung die in einer Art Funktionsplan im Anhang 
ist als Schaltung mit Xilinx 10.1 als VHDL übersetzen. Daher ich das 
noch nicht so richtig verstanden habe suche ich jemanden der das 
programmieren kann und dann so mit Kommentaren ausschmückt das ich es 
komplett verstehen kann und ähnliche Programme selbst schreiben kann. 
Das Board auf dem das Programm laufen soll ist ein Spartan-3A.

Ich würde mal behaupten ich hab schon ne ganz gute Vorbildung studiere 
nämlich E-Technik im 4 Semester. Nur von der VHDL Vorlesung im letzten 
Semester hab ich nicht so richtig viel mitgenommen und will meine 
Kenntnisse darum noch ein bisschen auffrischen.

Danke für eure Hilfe.

Grüße Monty

von Dieter (Gast)


Lesenswert?

>Ich würde mal behaupten ich hab schon ne ganz gute Vorbildung

Nur mit dem deutschen Satzbau hapert es noch ein wenig ;O)
Es gibt doch an deiner Universität bestimmt eine Bibliothek, und in 
dieser
Bibliothek gibt es doch ganz bestimmt auch ein paar Bücher zu VHDL. Und 
in diesen VHDL-Büchern gibt es doch bestimmt ähnliche Beispiele.
Also lauf ganz schnell in die Bibliothek und besorge dir ein VHDL-Buch, 
dann
bekommst das ganz bestimmt hin.

Viele Grüße,
Der Dieter

von abk (Gast)


Lesenswert?

Für das Spartan3E Starter Kit gibts den werkseitig mitgelieferten 
Quellcode auf der Xilinx-Homepage, da müsste so ein Drehgeber dabei 
sein.

von Monty M. (monty87)


Lesenswert?

Ich bin an einer kleinen pisseligen Fachhochschule und bei uns kann man 
garnichts rausfinden, weil man mit 5 Leuten studiert die auch keine 
Ahnung haben und unsere Bibliothek, wenn man sie so nen darf, auf dem 
Stand von Anno dazumal ist. Und mir wäre es sehr Lieb wenn mir einer bei 
dem Problem helfen würde das ich kein Rechtschreibtalent bin weis ich 
selber. Aber trotzdem DANKE!

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


Lesenswert?

> Nur von der VHDL Vorlesung im letzten Semester hab ich nicht so
> richtig viel mitgenommen und will meine
> Kenntnisse darum noch ein bisschen auffrischen.
Die Idee ist nicht schlecht...
Als Buchtipp: Reichardt/Schwarz  VHDL-Synthese

Das Ding, das du da als Zeichnung bietest, kann ich dir schnell in VHDL 
beschreiben. Aber du wirst es nicht synthetisieren können :-o

Denn ein solches Bauteil, wie einen Zähler, der synchrone UP- und 
DOWN-Eingänge hat, die aber aus einer asynchronen Flankenerkennung 
getriggert werden (die bekommt ja keinen Takt...). Nein, das kann nur 
schiefgehen.

Ich würde es so machen (du siehst z.B. keinen Reset, der ist nicht 
nötig):
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity test is
6
  port(
7
    clk    : in std_logic;
8
    btn_up : in std_logic;
9
    btn_dn : in std_logic;
10
    bcd10  : out std_logic_vector(3 downto 0);
11
    bcd1   : out std_logic_vector(3 downto 0)
12
    );
13
end test;
14
15
architecture beh of test is
16
  signal sr_up  : unsigned (3 downto 0) := "0000"; -- Schieberegister für Flankenerkennung
17
  signal sr_dn  : unsigned (3 downto 0) := "0000";
18
  signal count_up : std_logic := '0';  -- Flag für erkannte Flanke
19
  signal count_dn : std_logic := '0';
20
  signal cnt1   : integer 0 to 9 := 0; -- interner Zähler Einer
21
  signal cnt10  : integer 0 to 9 := 0; -- dito            Zehner
22
begin
23
  -- Flankenerkennung
24
  process begin
25
     wait until rising_edge(clk);
26
     sr_up <= sr_up(2 downto 0) & btn_up; -- Externes Signal eintakten
27
     if (sr_up="0111") then  count_up <= '1';
28
     else                    count_up <= '0';
29
     end if;
30
  end process;
31
32
  -- Flankenerkennung
33
  process begin
34
     wait until rising_edge(clk);
35
     sr_dn <= sr_dn(2 downto 0) & btn_dn;
36
     if (sr_dn="0111") then  count_dn <= '1';
37
     else                    count_dn <= '0';
38
     end if;
39
  end process;
40
 
41
  -- Zähler
42
  process begin
43
     wait until rising_edge(clk);
44
     if (count_dn='1' and count_up='0') -- runter zählen
45
         if (cnt1>0) then
46
            cnt1 <= cnt1 - 1:
47
         else
48
            cnt1 <= 9;
49
            if (cnt10>0) then
50
               cnt10 <= cnt10 - 1:
51
            else 
52
               cnt10 <= 9;
53
         end if;
54
     end if;
55
     if (count_dn='0' and count_up='1') -- hoch zählen
56
         if (cnt1<9) then
57
            cnt1 <= cnt1 + 1:
58
         else
59
            cnt1 <= 0;
60
            if (cnt10<9) then
61
               cnt10 <= cnt10 + 1:
62
            else 
63
               cnt10 <= 0;
64
         end if;
65
     end if;
66
  end process;
67
68
  bcd10 <= std_logic_vector(to_unsigned(cnt10,4));  
69
  bcd1  <= std_logic_vector(to_unsigned(cnt1 ,4));  
70
end beh;
Wie gesagt: der Code oben setzt nicht genau den Schaltplan um. Aber die 
Funktion, die dort abgebildet ist, ist synthetisierbar beschrieben.

Sieh dich zum Thema Zähler und Flankenerkennung mal dort um:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
usw. usf......



> Ich bin an einer kleinen pisseligen Fachhochschule...
Ja nun, du selbst wolltest dort hin :-/
Dass die Schule klein ist, das wird nicht gerade die letzten zwei Jahre 
passiert sein...

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


Lesenswert?

Der Reset-Taster wird im Zähler zum Zurücksetzen der BCD-Werte 
verwendet, deshalb hier ein überarbeiteter Zähler:
1
entity test is
2
  port(
3
    reset  : in std_logic;
4
    clk    : in std_logic;
5
    btn_up : in std_logic;
6
    btn_dn : in std_logic;
7
    bcd10  : out std_logic_vector(3 downto 0);
8
    bcd1   : out std_logic_vector(3 downto 0)
9
    );
10
end test;
11
:
12
:
13
:
14
  -- Zähler
15
  process begin
16
     wait until rising_edge(clk);
17
     if (count_dn='1' and count_up='0') -- runter zählen
18
     :
19
     :
20
     end if;
21
     if (count_dn='0' and count_up='1') -- hoch zählen
22
     :
23
     :
24
     end if;
25
     if (reset='1') then -- neu dazu: Zurücksetzen des Zählers
26
         cnt10 <= 0;
27
         cnt1  <= 0;
28
     end if;
29
  end process;
30
:
31
:
Korrekterweise müsste der Reset-Eingang auch noch 
einsynchronisiert/eingetaktet  werden.

von Monty M. (monty87)


Lesenswert?

Auf jedenfall schon einmal DANKE. Ich werde es morgen Nachmittag sofort 
ausprobieren. Und das mit der kleinen Fachhochschule hat ja auch ab und 
zu Vorteile. Und wenn es Leute gibt die einem in so einem Forum wie hier 
so SUPER helfen ist das ja auch alles kein Problem ;-)

von Schrotty (Gast)


Lesenswert?


von Dieter (Gast)


Lesenswert?

>Ich bin an einer kleinen pisseligen Fachhochschule und bei uns kann man
>garnichts rausfinden, weil man mit 5 Leuten studiert die auch keine
>Ahnung haben und unsere Bibliothek, wenn man sie so nen darf, auf dem
>Stand von Anno dazumal ist.

Alles nur Ausreden! Selbst das älteste VHDL-Buch kann, sofern man
mal reinschauen würde, helfen. Gerade Zähler etc. werden in JEDEM
VHDL-Buch erläutert.
Früher oder später solltest du dich damit auseinandersetzen, denn
deine Hausaufgaben werden hier nicht immer gelöst werden.
Viel interessanter wäre doch folgender Ansatz: Du präsentierst DEINEN
VHDL-Code und die Leute hier geben ihren Senf dazu. Fändest du das nicht
zielführender ? Kritik@Lothar!


Gruß,
Der Dieter

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


Lesenswert?

> Kritik@Lothar!
[ignore]   ;-)

Was glaubst du, was der Prof, der solche Aufgaben stellt,
wohl sagt, wenn er mit meinem Code ankommt?
Denn das ist noch nicht in jeder Vorlesung angekommen:
- Synchroner Reset
- wait im Prozess
- Zähler und Statemachines mit nur 1 Prozess

Und eines ist (jedenfalls mir) klar:
Ich werde bei der Klausur nicht neben Monty Monty sitzen   :-o

von Monty M. (monty87)


Lesenswert?

Also ich weis nicht wie es bei euch ist aber bei uns auf der 
Fachhochschule gibt es keine Hausaufgaben. Und die Klausur ist auch 
schon seit letztem Semester vorbei. Auch danke für die Literturtipps ich 
werde mir auch davon mal ein paar Sachen angucken. Ich wollte ja nur mal 
sehen wie man sowas richtig macht.

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


Lesenswert?

> ich weis nicht wie es bei euch ist
War...
Als ich studiert habe, wurde VHDL gerade so als IEEE 1076 Standard 
genormt ;-)

> aber bei uns auf der Fachhochschule gibt es keine Hausaufgaben
Na gut, dann nenne das Kind eben Semesterarbeit oder wie auch immer. Ich 
hatte Zuhause jedenfalls immer was zu tun. Und wenns nur die 
Fernsehreparatur zum Geldverdienen war...

>> E-Technik im 4 Semester
> Und die Klausur ist auch schon seit letztem Semester vorbei.
Nach der Klausur ist vor der Klausur  ;-)

von utzerubbel (Gast)


Lesenswert?

wir haben nach euren angaben versucht,dass programm zu schreiben!( 
vielen dank)
leider funktioniert der zähler noch nicht richtig!
hat da noch einer eine idee???






------------------------------------------------------------------------ 
----------
-- Company:
-- Engineer:
--
-- Create Date:    10:06:14 10/05/2009
-- Design Name:
-- Module Name:    zaehler - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
------------------------------------------------------------------------ 
----------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;


entity test is
  port(
    clk,reset    : in std_logic;
    btn_up  : in std_logic;
   cou_up, co_u , cou_dn, co_d: out std_logic;
    btn_dn : in std_logic;
    bcd10  : out std_logic_vector(2 downto 0);
    bcd1   : out std_logic_vector(3 downto 0)
    );
end test;

architecture beh of test is
  signal count_up : std_logic;  -- Flag für erkannte Flanke
  signal count_dn : std_logic;
  signal co_down, co_up : std_logic;
  signal cnt1   : std_logic_vector(3 downto 0):= "0000"; -- interner 
Zähler Einer
  signal cnt10  : std_logic_vector(2 downto 0):= "000"; -- internet 
Zähler Zehner
  type ZUSTAENDE_UP is (AU,BU,CU);
  signal ZUSTAND_UP,FOLGEZUSTAND_UP: ZUSTAENDE_UP;
  type ZUSTAENDE_DN is (AD,BD,CD);
  signal ZUSTAND_DN,FOLGEZUSTAND_DN: ZUSTAENDE_DN;

 begin

 ZUSTANDSAKTUALISIERUNG_UP: process (CLK, RESET)
  begin
      if reset = '1' then ZUSTAND_UP <=AU;
      elsif clk = '1' and clk'event then
          ZUSTAND_UP <= FOLGEZUSTAND_UP;
      end if ;
  end process ZUSTANDSAKTUALISIERUNG_UP;

FOLGEZUSTANDSBERECHNUNG_UP : process (btn_up, ZUSTAND_UP)
  begin
      case ZUSTAND_UP is
          when AU =>   if btn_up = '1' then FOLGEZUSTAND_UP <= AU;
                  else             FOLGEZUSTAND_UP <= BU;
                  end if ;
                  count_up <= '0';
          when BU =>   if btn_up = '1' then FOLGEZUSTAND_UP <= CU;
                  else             FOLGEZUSTAND_UP <= BU;
                  count_up <= '0';
                  end if;
          when CU =>  if btn_up = '1' then FOLGEZUSTAND_UP <= AU;
                  else             FOLGEZUSTAND_UP <= BU;
                  end if ;
                  count_up <= '0';
      end case;
  end process FOLGEZUSTANDSBERECHNUNG_UP;



 ZUSTANDSAKTUALISIERUNG_DN:process (CLK,RESET)
  begin
      if reset = '1' then ZUSTAND_DN <=AD;
      elsif clk = '1' and clk'event then
          ZUSTAND_DN<=FOLGEZUSTAND_DN;
      end if ;
  end process ZUSTANDSAKTUALISIERUNG_DN;

FOLGEZUSTANDSBERECHNUNG_DN: process ( btn_dn,ZUSTAND_DN)
  begin
      case ZUSTAND_DN is
          when AD =>   if btn_dn = '1' then FOLGEZUSTAND_DN <= AD;
                  else             FOLGEZUSTAND_DN <= BD;
                  end if ;
                  count_dn <= '0';
          when BD =>   if btn_dn = '1' then FOLGEZUSTAND_DN <= CD;
                  else             FOLGEZUSTAND_DN <= BD;
                  count_dn <= '0';
                  end if;
          when CD =>  if btn_dn = '1' then FOLGEZUSTAND_DN <= AD;
                  else             FOLGEZUSTAND_DN <= BD;
                  end if ;
                  count_dn <= '1';
      end case;
  end process FOLGEZUSTANDSBERECHNUNG_DN;



  -- 1er Zähler
  process (reset,clk,count_dn,count_up)

  begin
   if reset = '1' then cnt1 <= "0000";
  elsif clk = '1' and clk'event then
     if count_dn='1' and count_up='0' then -- runter zählen
         if cnt1 = "0000" then cnt1 <= "1001";
         else cnt1 <= cnt1 - 1;
         end if;

     elsif (count_dn='0' and count_up='1') then-- hoch zählen
         if cnt1 = 9 then cnt1 <= "0000";
         else cnt1 <= cnt1 + 1;
         end if;
     else
      cnt1 <= cnt1;

     end if;
  end if;
  end process;

  -- 10er Zähler
process(reset,clk,co_down,co_up)

begin
   if reset = '1' then cnt10 <= "000";
  elsif clk = '1' and clk'event then
     if (co_down='1' and co_up='0')then -- runter zählen
         if cnt10 = 0 then cnt10 <= "101";
         else cnt10 <= cnt10 - 1;
         end if;

     elsif (co_down='0' and co_up='1') then-- hoch zählen
         if cnt10 = 5 then cnt10 <= "000";
         else cnt10 <= cnt10 + 1;
         end if;
     else
      cnt10 <= cnt10;

     end if;
  end if;
  end process;

  co_up <= '1' when co_up = '1' and cnt1 = 9 else '0';

  bcd10 <= cnt10;
  bcd1  <= cnt1;
  cou_up <= count_up;
  cou_dn <= count_dn;
  co_u <= co_up;

end beh;

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


Lesenswert?

> wir haben nach euren angaben versucht,dass programm zu schreiben!
Sicher nicht! :-/
Denn sowas macht man nicht:
1
use ieee.std_logic_1164.all;
2
use ieee.numeric_std.all;
3
use ieee.std_logic_arith.all;
4
use ieee.std_logic_unsigned.all;

Entweder so:
1
use ieee.std_logic_1164.all;
2
use ieee.numeric_std.all;

Oder so:
1
use ieee.std_logic_1164.all;
2
use ieee.std_logic_arith.all;
3
use ieee.std_logic_unsigned.all;
Siehe dazu den Beitrag "Redundanz in den IEEE Libs / Welche kann ich weg lassen?"

> leider funktioniert der zähler noch nicht richtig!
Was funktioniert nicht?

Wozu denn diese ganzen verwirrenden FSM?
Wie z.B. ZUSTANDSAKTUALISIERUNG_DN und Co: der Taster ist nicht 
entprellt und geht direkt in diese windige Flankenerkennung. Wie man 
eine Flanke eines Eingangssignals erfasst siehst du doch dort im 
Beitrag "Re: Funktionsplan in VHDL übersetzen"

BTW:
Ich habe dir doch eine maßgeschneiderte Lösung angeboten. Hast du daraus 
nichts gelernt?  :-/

von Monty (Gast)


Lesenswert?

Ja das braucht man jetzt auch nicht mehr "use ieee.numeric_std.all;". 
Das ist von der Veränderung des oberen Programms noch übrig geblieben. 
Das obere Programm mit dem Schieberegister als Flankenerkennung hat so 
garnicht funktioniert. Und da haben wir eine Eigene programmiert.

von Monty (Gast)


Lesenswert?

So

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

funktioniert hier in unserer Programmierung nicht. Denn da haben die 
Rechenoperationen nicht funktioniert + - usw.

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


Angehängte Dateien:

Lesenswert?

> Denn da haben die Rechenoperationen nicht funktioniert + - usw.
Klar. Man kann Vektoren mit dern numeric_std nicht so einfach 
addieren...
Dafür gibt es die Datentypen unsigned und signed.

Wie auch immer:
> Das obere Programm mit dem Schieberegister als Flankenerkennung hat so
> garnicht funktioniert.
Die Flankenerkennung funktioniert. Die verwende ich selber zigfach.
Den Code oben habe ich ohne Syntax-Check einfach so aus dem Kopf 
geschrieben. Damit waren da noch ein paar Typos drin:
- integer ohne range
- : statt ;
- zwei fehlende end if
Nach dem Beheben derselben läuft das Ding bei mir auf Anhieb (Aufwand 10 
Minuten, incl. Erstellen eines Projekts, Beheben der Fehler, Schreiben 
einer Testbench und Testen des Designs).
Fazit: Mitdenken schadet nicht :-/

von utzerubbel (Gast)


Lesenswert?

da ich das ganze gedöne hier nur mäßig verstehe, haben wir uns später 
einfach an den vorgaben unseres dozenten entlanggehangelt!
somit hatten wir dann wenigstens etwas,was einigermaßen,nur nicht 
richtig,funktioniert hat!
vielen dank für deine vorschläge!haben uns ja auch weiter gebracht,nur 
mitdenken....würde ich ja gerne...nur wie gesagt,verstehen tu ich das 
ganze noch nicht so richtig!
bist du demnach der meinung,wenn wir deine flankenerkennung wieder 
einsetzen,damit die taster nicht prellen,dass es dann funktioniert??

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


Lesenswert?

> bist du demnach der meinung,wenn wir deine flankenerkennung wieder
> einsetzen,damit die taster nicht prellen,dass es dann funktioniert??
Nein, denn das Herunterzählen der Zehnerstellen (co_down) ist noch nicht 
implementiert...

> damit die taster nicht prellen
Die Taster prellen sowieso. Du mußt dafür sorgen, dass dir das Prellen 
nichts ausmacht.
Die Flankenerkennung, die ich beschrieben habe, ist (abhängig vom Takt) 
ziemlich schnell. Da können also durchaus noch Preller im ms-Bereich 
durchkommen. Aber das gilt für eure Flankenerkennung noch mehr...
Abhilfe:
Das Abtastintervall verlängern und das Schieberegister nur einmal pro ms 
mit einem neuen Wert füllen. Dazu braucht es einen Vorteiler, der z.B. 
50MHz Taktfrequenz auf 1 ms herunterteilt.
1
  signal sr_up  : unsigned (3 downto 0) := "0000"; -- Schieberegister für Flankenerkennung
2
  signal sr_dn  : unsigned (3 downto 0) := "0000";
3
  signal count_up : std_logic := '0';  -- Flag für erkannte Flanke
4
  signal count_dn : std_logic := '0';
5
  signal mscnt    : integer 0 to 50000 := 0; -- Vorteiler 50MHz --> 1ms
6
begin
7
  -- Flankenerkennung
8
  process begin
9
     wait until rising_edge(clk);
10
     if (mscnt='0') then
11
        sr_up <= sr_up(2 downto 0) & btn_up; -- Externes Signal eintakten
12
        if (sr_up="0111") then  count_up <= '1';
13
        else                    count_up <= '0';
14
        end if;
15
     end if;
16
  end process;
17
18
  -- Flankenerkennung
19
  process begin
20
     wait until rising_edge(clk);
21
     if (mscnt='0') then
22
        sr_dn <= sr_dn(2 downto 0) & btn_dn;
23
        if (sr_dn="0111") then  count_dn <= '1';
24
        else                    count_dn <= '0';
25
        end if;
26
     end if;
27
  end process;
28
29
  -- 1ms-Takt
30
  process begin
31
     wait until rising_edge(clk);
32
     if (mscnt < 500000) then mscnt <= mscnt+1;
33
     else                     mscnt <= 0;
34
     end if;
35
  end process;

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.