Forum: FPGA, VHDL & Co. Probleme mit der Erstellung eines Automaten


von Lst (Gast)


Lesenswert?

Hallo.

Ich bin VHDL-Neuling und habe zwei Probleme beim unten stehenden 
Automaten. Ich nutze folgenden Baustein: Xilinx XC9572XL.

1. Kommen mehrere Warnungen darüber, dass ich Latches eingebaut habe:
Found 8-bit latch for signal <data_to_CPLD>. Latches may be generated 
from incomplete case or if statements. We do not recommend the use of 
latches in FPGA/CPLD designs, as they may lead to timing problems.

Bei dem ersten Problem weiß ich nicht ob das wirklich zum nicht 
Funktionieren meines Automaten führt oder ob der Fehler woanders liegt.

2.Zum Testen habe ich einen Ausgang angelegt (test_data_out) und auf 
LEDs gelegt. Nur leider scheint noch irgendwtwas nicht zu funktionieren, 
denn Ich sehe nicht die gewünschten Bytes die ich generiere.

Meine Frage nun also: Wenn ihr euch den Automaten anschaut, seht ihr 
irgendwelche groben Fehler?
Wie ihr seht habe ich den Ablauf in 2 Prozesse geteilt, wovon einer 
nicht taktflankengesteuert ist aber laut einigen Quellen soll das 
trotzdem gehen.

Ich würde mich sehr über Antworten von euch freuen, weil ich grad 
absolut nicht drauf komm, was da schiefläuft.

MfG Laura
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
4
ENTITY usb_automat IS
5
    PORT (
6
      clk : IN STD_LOGIC;
7
      reset : IN STD_LOGIC;
8
      RXF : IN STD_LOGIC; --RXF low: at least 1 byte in recieve buffer
9
      TXE : IN STD_LOGIC;  --TXE hight: transmit buffer full
10
      in_data : in STD_LOGIC_VECTOR(7 downto 0); -- data_to_PC
11
      data : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
12
13
      WR : OUT STD_LOGIC;  --When taken from a high to a low state, WR reads the 8 data lines and writes the byte into the FIFO's transmit buffer.
14
      RD : OUT STD_LOGIC; --When pulled low, RD# takes the 8 data lines from a high impedance state to the current byte in the FIFO's receive buffer.
15
      test_data_out : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) -- Output connected to LEDs 
16
    );
17
END usb_automat;
18
19
ARCHITECTURE BEHAVIOR OF usb_automat IS
20
    TYPE type_fstate IS (start,toPC1,toCPLD1,toPC2,toPC3,waitstate,toCPLD2);
21
   
22
   -- state signals
23
    SIGNAL fstate : type_fstate;
24
    SIGNAL next_state : type_fstate;
25
   
26
   -- output signals
27
    SIGNAL reg_WR : STD_LOGIC := '0';
28
    SIGNAL reg_RD : STD_LOGIC := '0';
29
   
30
   -- data signals
31
   SIGNAL data_to_PC : STD_LOGIC_VECTOR(7 DOWNTO 0); 
32
   SIGNAL data_to_CPLD : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
33
   
34
BEGIN
35
  data_to_PC <=in_data;
36
    -- set connection between internal output signals and output ports
37
    PROCESS (clk,next_state,reg_WR,reg_RD, data_to_CPLD, data_to_PC, data)
38
    BEGIN
39
        IF rising_edge(clk) THEN
40
            fstate <= next_state;
41
            WR <= reg_WR;
42
            RD <= reg_RD;
43
            test_data_out <= data_to_CPLD;
44
        END IF;
45
    END PROCESS;
46
   
47
    PROCESS (fstate,reset,RXF,TXE,clk, data_to_PC, data)
48
    BEGIN
49
        -- implement reset
50
      IF (reset='1') THEN
51
        next_state <= start;
52
        reg_WR <= '0';
53
        reg_RD <= '0';
54
      ELSE
55
        reg_WR <= '0'; -- ist das gut? Fallende Flanke wird produziert
56
        reg_RD <= '0'; -- genauso hier.
57
        CASE fstate IS
58
          WHEN start =>
59
              IF ((NOT((TXE = '1')) AND (RXF = '1'))) THEN
60
                next_state <= toPC1;
61
              ELSIF (((RXF = '1') AND (TXE = '1'))) THEN --TXE hight: transmit buffer full
62
                next_state <= start;
63
              ELSIF (NOT((RXF = '1'))) THEN --RXF low: at least 1 byte in recieve buffer
64
                next_state <= toCPLD1;
65
              ELSE
66
                next_state <= start;
67
              END IF;
68
              
69
          WHEN toPC1 =>
70
              reg_WR <= '1';
71
              next_state <= toPC2;
72
              
73
          WHEN toCPLD1 =>
74
              reg_RD <= '0';
75
              data_to_CPLD <= data;
76
              next_state <= toCPLD2;
77
              
78
          WHEN toPC2 =>
79
              next_state <= toPC3;
80
              
81
          WHEN toPC3 =>
82
              data <= data_to_PC; -- Setup data 
83
              reg_WR <= '0';
84
              next_state <= waitstate;
85
              
86
          WHEN waitstate =>
87
              next_state <= start;                
88
              
89
          WHEN toCPLD2 =>
90
              reg_RD <= '1';
91
              next_state <= waitstate;
92
              
93
          WHEN OTHERS =>   
94
              reg_WR <= 'X';
95
              reg_RD <= 'X';
96
              report "Reach undefined state";
97
              
98
        END CASE;
99
      END IF;
100
    END PROCESS;
101
END BEHAVIOR;

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


Lesenswert?

Lst schrieb:
> PROCESS (clk,next_state,reg_WR,reg_RD, data_to_CPLD, data_to_PC, data)
>     BEGIN
>         IF rising_edge(clk) THEN

Dieser Prozess ist nur auf clk sensitiv. Deshalb muss auch nur clk 
in die Liste...

Lst schrieb:
> WHEN OTHERS =>
>               reg_WR <= 'X';
>               reg_RD <= 'X';
>               report "Reach undefined state";
Unnötig. Weil du alle definierten Zustände verwendet hast, kann dieser 
Zustand NIEMALS erreicht werden.

> reg_WR <= '0'; -- ist das gut? Fallende Flanke wird produziert
Warum wird hier eine fallende Flanke produziert?

> Found 8-bit latch for signal <data_to_CPLD>.
Das ist klar, denn da wird in einem nicht getakteten Prozess was 
gespeichert:
          WHEN toCPLD1 =>
              data_to_CPLD <= data;

> Meine Frage nun also: Wenn ihr euch den Automaten anschaut, seht ihr
> irgendwelche groben Fehler?
Ausser den gemeldeten Latches nicht. Allerdings deuten Latches, die du 
nicht UNBEDINGT WILLST, gern auf eine Designschäche. Und zwar nicht 
wegen des VHDL-Codes, sondern wegen der zugrundeliegenden Überlegungen.

Ich würde dir raten:
Mach einfach mal eine Simulation. Das ist eine schöne übersichtliche 
FSM, also das ideale Beispiel, mal mit einer Simulation anzufangen.

OT: warum schreibst du deine Kommentare nicht einfach auf Deutsch in den 
Code?

BTW:
> RD : OUT STD_LOGIC; --When pulled low, RD# takes
Wenn ein Signal LOW-aktiv ist, dann solltest du dieses Signal auch so 
benennen. Hier würde sich nRD oder RDn anbieten...

von Lst (Gast)


Lesenswert?

Lothar Miller schrieb:

> Dieser Prozess ist nur auf clk sensitiv. Deshalb muss auch nur clk
> in die Liste...
Jo stimmt, die anderen kann man rausnehmen. Mach ich auch gleich mal

>> reg_WR <= '0'; -- ist das gut? Fallende Flanke wird produziert
> Warum wird hier eine fallende Flanke produziert?
Das bezieht sich auf den FTDI, der da später mal dranhängen soll 
(http://www.ftdichip.com/Support/Documents/DataSheets/DLP/dlp-usb245mv15.pdf).
Dieses Kommentar hatte ich nicht speziell für diesen Forenbeitrag 
geschireben. Ich bin mir an der Stelle unsicher ob, wenn ich die 
Ausgänge an dieser Stelle low schalte ob dann nicht der FTDI in dem 
moment reagiert (sind ja Handshake-Signale) und Daten anlegt, die ich in 
dem moment verpasse.

>
>> Found 8-bit latch for signal <data_to_CPLD>.
> Das ist klar, denn da wird in einem nicht getakteten Prozess was
> gespeichert:
>           WHEN toCPLD1 =>
>               data_to_CPLD <= data;
>
Das ist ja interessant, daran liegt das also. Danke!
Wenn ich den Process taktgesteuert mache brauche ich mehr Macrozellen, 
deshalb war ich ganz froh, dass es auch so gehen soll. Meinst du ich 
sollte da doch nochmal drüber nachdenken an der Process-Struktur was zu 
ändern (z.B. den zweiten Process auch taktgesteuert machen)?

> Ich würde dir raten:
> Mach einfach mal eine Simulation. Das ist eine schöne übersichtliche
> FSM, also das ideale Beispiel, mal mit einer Simulation anzufangen.

Mach ich.

> OT: warum schreibst du deine Kommentare nicht einfach auf Deutsch in den
> Code?

Keine Ahnung. Dachte das ist besser so :). Ich geb den Signalen auch 
keine deutschen Namen. Man weiß ja nie ob man den Code z.B. mal in einem 
englischsprachigem Forum hochlädt.Zudem ich hab auch englischsprachige 
Mitarbeiter.

> BTW:
>> RD : OUT STD_LOGIC; --When pulled low, RD# takes
> Wenn ein Signal LOW-aktiv ist, dann solltest du dieses Signal auch so
> benennen. Hier würde sich nRD oder RDn anbieten...

Gut zu wissen.

Vielen Dank auch für deine schnelle Antwort. Ich mache mich jetzt ans 
simulieren.

von Lst (Gast)


Lesenswert?

Bei der Simulation hab ich festgestellt:

test_data_out <= data_toCPLD <= "00001010" (Verbingundgsschema, kein 
VDHL-Code)
führt zum gewünschten Ergebnis, also dass in test_data_out mit der 
nächsten Taktflankte "00001010" steht.

Während
test_data_out <= data_toCPLD <= data <= "00001010"
dazu führt dass in test_data_out unknown (xxxxxxxx) steht. Und auch in 
data~result.

Jetzt bin ich am überlegen ob ich den inout port überhaupt richtig 
verwende.
Eigentlich muss ich bei CLPDs die Treiber doch nicht selber steuern wie 
bei einem Mikroprozessor die DDRs oder?

Momentan mach ich damit ja dies:
1
     -- in der Entity:
2
     data : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
3
4
     -- architecture:
5
     SIGNAL data_to_PC : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Daten, die über bidirektionalen Port an PC geschickt werden
6
     SIGNAL data_to_CPLD : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; -- daten die vom PC in den CPLD geschrieben werden
7
8
     --im getakteten Prozess:
9
     test_data_out <= data_to_CPLD;
10
11
     -- Zustand in dem Daten vom inout Port entgegengenommen werden:
12
     WHEN toCPLD1 =>
13
          data_to_CPLD <= data;
14
          next_state <= toCPLD2;
15
     -- Zustand in dem Daten an den inout Port gelegt werden:
16
     WHEN toPC3 =>
17
          data <= data_to_PC; -- Setup data 
18
          next_state <= waitstate;

Ist daran irgendwas nicht richtig?

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


Lesenswert?

Lst schrieb:
> Eigentlich muss ich bei CLPDs die Treiber doch nicht selber steuern wie
> bei einem Mikroprozessor die DDRs oder?
Oh doch. Du mußt die Tristate-Treiber aktiv in den hochohmigen Zustand 
schalten.
Wenn das RDn- und das WRn-Signal von aussen kommen, sieht das etwa so 
aus:
1
:
2
port ( ...
3
       data :inout std_logic_vector(7 downto 0);
4
:      
5
:      
6
signal write   : std_logic;
7
signal datain  : std_logic_vector(7 downto 0);
8
signal dataout : std_logic_vector(7 downto 0);
9
:
10
architecture machwas ....
11
:
12
   datain <= data;
13
   data   <= dataout when write='1' else (others=>'Z'); -- IO-Treiber umschalten
14
end machwas;

von Lst (Gast)


Lesenswert?

Oh man, das hat ich doch eigentlich auch so geplant...wieso habe ich das 
wieder ruasgeworfen?
Naja, ich probiers gleich mal aus. Danke nochmal für deine Hilfe!

von Lst (Gast)


Lesenswert?

Funktioniert.
Sehr schön!

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.