Forum: FPGA, VHDL & Co. State machine für SPI


von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Hallo Leute :),

für mein Spartan 3AN Starter Kit, habe ich einen SPI code geschrieben. 
Als Anfänger, fand ich die Aufgabe schwer, und habe es vorgezogen es als 
eine State-Machine zu codieren, damit ich einfach die Fehler finde.

Das User Guide findet man unter dieser Verbindung:

http://www.xilinx.com/support/documentation/boards_and_kits/ug334.pdf

Auf seite 76, findet man was ich codieren will (Figure 9-6 und 9-7).

Ich habe drei Fragen, und noch später werde ich mehr Fragen haben über 
diesen Code. Und wäre es sehr nett von euch, sie mir zu erkläre :)

1- Ist es eine gute Idee, den Code als State Machine zu schreiben?

2- Meine State Machine funktioniert leider nicht. Die States ändern sich 
nicht. Ich kann es nicht auf der Simulation zum laufen kriegen. Ich will 
erstmal die Entwicklung von SPI_SCK und AD_CONV sehen, wie sie im User 
Guide beschrieben wurden.

3- Warum sagt das Synthesiswerkzeug, dass es Latches geben wird, obwohl 
alle Variablen schon in Allen states definiert wurden?

Vielen Dank!!!
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use WORK.COMPONENTS.ALL;
4
5
-- Uncomment the following library declaration if using
6
-- arithmetic functions with Signed or Unsigned values
7
use IEEE.NUMERIC_STD.ALL;
8
9
-- Uncomment the following library declaration if instantiating
10
-- any Xilinx primitives in this code.
11
--library UNISIM;
12
--use UNISIM.VComponents.all;
13
14
entity ADCModule is
15
   Generic(BarSteps : Integer := 8; regBits : Integer := 14);
16
    Port ( AD_CONV : OUT  STD_LOGIC;
17
           SPI_SCK : OUT  STD_LOGIC;
18
           AD_DOUT : IN  STD_LOGIC;
19
        BarOut : OUT STD_LOGIC_VECTOR(BarSteps-1 downto 0);
20
        CLK : IN STD_LOGIC        
21
        );
22
end ADCModule;
23
24
architecture Behavioral of ADCModule is
25
  CONSTANT AD_CONV_PULSE_LENGTH : INTEGER := 2; --constants defining number of pulsess for each state
26
  CONSTANT AD_CONV_WAIT_LENGTH : INTEGER := 1;
27
  CONSTANT SPI_CLK_EN_LENGTH : INTEGER := 2;
28
  CONSTANT DATA_AC1_LENGTH : INTEGER := 14;
29
  CONSTANT DATA_AC_WAIT_LENGTH : INTEGER := 3;
30
  CONSTANT DATA_AC2_LENGTH : INTEGER := 14;
31
  CONSTANT SPI_CLK_END_LENGTH : INTEGER := 3;
32
  CONSTANT SPI_END_WAIT_LENGTH : INTEGER := 3;
33
34
35
  SIGNAL DATA_AC_EN : STD_LOGIC := '0';
36
  TYPE states is (START_STATE, AD_CONV_PULSE_STATE, AD_CONV_WAIT_STATE, SPI_CLK_EN_STATE, DATA_AC1_STATE, DATA_AC_WAIT_STATE, DATA_AC2_STATE, SPI_CLK_END_STATE, SPI_END_WAIT_STATE);
37
  SIGNAL pr_state : states := START_STATE;
38
  SIGNAL nx_state: states;
39
  SIGNAL SPI_CLK_EN, AD_CONV_EN : STD_LOGIC; --bits defining the state of SPI_CLK and AD_CONV being enabled or disabled. Usage is defined in StateControl process.
40
  SIGNAL dataBuffer1, dataBuffer2 : STD_LOGIC_VECTOR(regBits-1 downto 0) := (others => '0');
41
  SIGNAL temp : INTEGER := 0;
42
  
43
  
44
  -- states description:
45
  
46
  -- I defined here a Zero state as the state where both SPI_SCK and AD_CONV = 0.
47
  
48
  -- START_STATE: I wrote this state since the problem was with moving to successive states. I thought the problem was from the initial value. This state has no significant function.
49
  -- AD_CONV_PULSE_STATE: State defined in Fig. 9-6 by the pulse, whose length is minimum equals 4 ns.
50
  -- AD_CONV_WAIT_STATE: State defined in Fig. 9-6, by the Zero state between the pulse of AD_CONV and the first pulse of SPI_SCK.
51
  -- SPI_CLK_EN_STATE: Stated that has SPI_SCK enabled till the beginning of data reception.
52
  -- DATA_AC1_STATE: State that receives the first bunch of data.
53
  -- DATA_AC_WAIT_STATE: Stated defined in Fig. 9-6 by the Zero state between the reception of the two bunches of data.
54
  -- DATA_AC2_STATE: State that receives the second bunch of data.
55
  -- SPI_CLK_END_STATE: State that keeps the remenant of SPI_CLK pulses there.
56
  -- SPI_END_WAIT_STATE: A Zero state till the repetition of the whole operation.
57
begin
58
  StateContol:
59
  process(clk)
60
  begin
61
    if (rising_edge(clk)) then
62
      AD_CONV <= AD_CONV_EN;
63
      SPI_SCK <= clk AND SPI_CLK_EN;
64
      if (pr_state = START_STATE) then
65
        pr_state <= AD_CONV_PULSE_STATE;        
66
      else
67
        pr_state <= nx_state;
68
      end if;
69
    end if;
70
  end process;
71
  StateFunctionsDefinitions:
72
  process(pr_state)
73
    --VARIABLE dataBuffer1_VAR, dataBuffer2_VAR : STD_LOGIC_VECTOR(regBits-1 downto 0) := (others => '0');
74
    VARIABLE AD_CONV_EN_VAR, SPI_CLK_EN_VAR : STD_LOGIC := '0';
75
    VARIABLE CONV_PULSE_COUNTER_VAR : INTEGER := 0; -- counter for every state for timing
76
    VARIABLE AD_CONV_WAIT_COUNTER_VAR : INTEGER := 0;
77
    VARIABLE SPI_CLK_EN_COUNTER_VAR : INTEGER := 0;
78
    VARIABLE DATA_AC1_COUNTER_VAR : INTEGER := 0;
79
    VARIABLE DATA_AC_WAIT_COUNTER_VAR : INTEGER := 0;
80
    VARIABLE DATA_AC2_COUNTER_VAR : INTEGER := 0;
81
    VARIABLE SPI_CLK_END_COUNTER_VAR : INTEGER := 0;
82
    VARIABLE SPI_END_WAIT_COUNTER_VAR : INTEGER := 0;
83
  begin
84
    case pr_state is -- in every state, all counters are reset to avoid having latches, but not the one getting counted over in the current state
85
      when START_STATE =>
86
        AD_CONV_WAIT_COUNTER_VAR := 0;
87
        SPI_CLK_EN_COUNTER_VAR := 0;
88
        DATA_AC1_COUNTER_VAR := 0;
89
        DATA_AC_WAIT_COUNTER_VAR := 0;
90
        DATA_AC2_COUNTER_VAR := 0;
91
        SPI_CLK_END_COUNTER_VAR := 0;
92
        SPI_END_WAIT_COUNTER_VAR := 0;
93
      
94
        AD_CONV_EN_VAR := '0';
95
        SPI_CLK_EN_VAR := '0';      
96
        nx_state <= AD_CONV_PULSE_STATE;
97
        
98
        
99
      when AD_CONV_PULSE_STATE =>
100
        AD_CONV_WAIT_COUNTER_VAR := 0;
101
        SPI_CLK_EN_COUNTER_VAR := 0;
102
        DATA_AC1_COUNTER_VAR := 0;
103
        DATA_AC_WAIT_COUNTER_VAR := 0;
104
        DATA_AC2_COUNTER_VAR := 0;
105
        SPI_CLK_END_COUNTER_VAR := 0;
106
        SPI_END_WAIT_COUNTER_VAR := 0;
107
        
108
        AD_CONV_EN_VAR := '1';
109
        SPI_CLK_EN_VAR := '0';
110
        if (CONV_PULSE_COUNTER_VAR < AD_CONV_PULSE_LENGTH) then
111
          CONV_PULSE_COUNTER_VAR := CONV_PULSE_COUNTER_VAR + 1;
112
        else
113
          nx_state <= AD_CONV_WAIT_STATE;
114
        end if;
115
        
116
        
117
      when AD_CONV_WAIT_STATE =>
118
        CONV_PULSE_COUNTER_VAR := 0;
119
        SPI_CLK_EN_COUNTER_VAR := 0;
120
        DATA_AC1_COUNTER_VAR := 0;
121
        DATA_AC_WAIT_COUNTER_VAR := 0;
122
        DATA_AC2_COUNTER_VAR := 0;
123
        SPI_CLK_END_COUNTER_VAR := 0;
124
        SPI_END_WAIT_COUNTER_VAR := 0;    
125
        
126
        AD_CONV_EN_VAR := '0';
127
        SPI_CLK_EN_VAR := '0';
128
        if (AD_CONV_WAIT_COUNTER_VAR < AD_CONV_WAIT_LENGTH) then
129
          AD_CONV_WAIT_COUNTER_VAR := AD_CONV_WAIT_COUNTER_VAR + 1;
130
        else
131
          nx_state <= SPI_CLK_EN_STATE;
132
        end if;
133
        
134
        
135
      when SPI_CLK_EN_STATE =>
136
        CONV_PULSE_COUNTER_VAR := 0;
137
        AD_CONV_WAIT_COUNTER_VAR := 0;
138
        DATA_AC1_COUNTER_VAR := 0;
139
        DATA_AC_WAIT_COUNTER_VAR := 0;
140
        DATA_AC2_COUNTER_VAR := 0;
141
        SPI_CLK_END_COUNTER_VAR := 0;
142
        SPI_END_WAIT_COUNTER_VAR := 0;          
143
      
144
        AD_CONV_EN_VAR := '0';
145
        SPI_CLK_EN_VAR := '1';
146
        if (SPI_CLK_EN_COUNTER_VAR < SPI_CLK_EN_LENGTH) then
147
          SPI_CLK_EN_COUNTER_VAR := SPI_CLK_EN_COUNTER_VAR + 1;
148
        else
149
          nx_state <= DATA_AC1_STATE;
150
        end if;
151
      
152
      
153
      when DATA_AC1_STATE =>
154
        CONV_PULSE_COUNTER_VAR := 0;
155
        AD_CONV_WAIT_COUNTER_VAR := 0;
156
        SPI_CLK_EN_COUNTER_VAR := 0;
157
        DATA_AC_WAIT_COUNTER_VAR := 0;
158
        DATA_AC2_COUNTER_VAR := 0;
159
        SPI_CLK_END_COUNTER_VAR := 0;
160
        SPI_END_WAIT_COUNTER_VAR := 0;          
161
      
162
        AD_CONV_EN_VAR := '0';
163
        SPI_CLK_EN_VAR := '1';
164
        if (DATA_AC1_COUNTER_VAR < DATA_AC1_LENGTH) then
165
          if (DATA_AC1_COUNTER_VAR < regBits) then
166
            dataBuffer1(regBits - DATA_AC1_COUNTER_VAR) <= AD_DOUT;
167
          end if;
168
          DATA_AC1_COUNTER_VAR := DATA_AC1_COUNTER_VAR + 1;
169
        else
170
          nx_state <= DATA_AC_WAIT_STATE;
171
        end if;
172
      
173
      
174
      when DATA_AC_WAIT_STATE =>
175
        CONV_PULSE_COUNTER_VAR := 0;
176
        AD_CONV_WAIT_COUNTER_VAR := 0;
177
        SPI_CLK_EN_COUNTER_VAR := 0;
178
        DATA_AC1_COUNTER_VAR := 0;
179
        DATA_AC2_COUNTER_VAR := 0;
180
        SPI_CLK_END_COUNTER_VAR := 0;
181
        SPI_END_WAIT_COUNTER_VAR := 0;    
182
        
183
        AD_CONV_EN_VAR := '0';
184
        SPI_CLK_EN_VAR := '1';
185
        if (DATA_AC_WAIT_COUNTER_VAR < DATA_AC_WAIT_LENGTH) then
186
          DATA_AC_WAIT_COUNTER_VAR := DATA_AC_WAIT_COUNTER_VAR + 1;
187
        else
188
          nx_state <= DATA_AC2_STATE;
189
        end if;
190
      
191
      
192
      when DATA_AC2_STATE =>
193
        CONV_PULSE_COUNTER_VAR := 0;
194
        AD_CONV_WAIT_COUNTER_VAR := 0;
195
        SPI_CLK_EN_COUNTER_VAR := 0;
196
        DATA_AC1_COUNTER_VAR := 0;
197
        DATA_AC_WAIT_COUNTER_VAR := 0;
198
        SPI_CLK_END_COUNTER_VAR := 0;
199
        SPI_END_WAIT_COUNTER_VAR := 0;    
200
        
201
        AD_CONV_EN_VAR := '0';
202
        SPI_CLK_EN_VAR := '1';
203
        if (DATA_AC2_COUNTER_VAR < DATA_AC2_LENGTH) then
204
          if (DATA_AC2_COUNTER_VAR < regBits) then
205
            dataBuffer2(regBits - DATA_AC2_COUNTER_VAR) <= AD_DOUT;
206
          end if;
207
          DATA_AC2_COUNTER_VAR := DATA_AC2_COUNTER_VAR + 1;
208
        else
209
          nx_state <= SPI_CLK_END_STATE;
210
        end if;
211
        
212
        
213
      when SPI_CLK_END_STATE =>
214
        CONV_PULSE_COUNTER_VAR := 0;
215
        AD_CONV_WAIT_COUNTER_VAR := 0;
216
        SPI_CLK_EN_COUNTER_VAR := 0;
217
        DATA_AC1_COUNTER_VAR := 0;
218
        DATA_AC_WAIT_COUNTER_VAR := 0;
219
        DATA_AC2_COUNTER_VAR := 0;
220
        SPI_END_WAIT_COUNTER_VAR := 0;          
221
      
222
        AD_CONV_EN_VAR := '0';
223
        SPI_CLK_EN_VAR := '1';
224
        if (SPI_CLK_END_COUNTER_VAR < SPI_CLK_END_LENGTH) then
225
          SPI_CLK_END_COUNTER_VAR := SPI_CLK_END_COUNTER_VAR + 1;
226
        else
227
          nx_state <= SPI_END_WAIT_STATE;
228
        end if;
229
        
230
      when SPI_END_WAIT_STATE =>
231
        CONV_PULSE_COUNTER_VAR := 0;
232
        AD_CONV_WAIT_COUNTER_VAR := 0;
233
        SPI_CLK_EN_COUNTER_VAR := 0;
234
        DATA_AC1_COUNTER_VAR := 0;
235
        DATA_AC_WAIT_COUNTER_VAR := 0;
236
        DATA_AC2_COUNTER_VAR := 0;
237
        SPI_CLK_END_COUNTER_VAR := 0;
238
      
239
        AD_CONV_EN_VAR := '0';
240
        SPI_CLK_EN_VAR := '0';
241
        if (SPI_END_WAIT_COUNTER_VAR < SPI_END_WAIT_LENGTH) then
242
          SPI_END_WAIT_COUNTER_VAR := SPI_END_WAIT_COUNTER_VAR + 1;
243
        else
244
          nx_state <= AD_CONV_PULSE_STATE;
245
        end if;
246
    end case;
247
    temp <= CONV_PULSE_COUNTER_VAR;
248
    AD_CONV_EN <= AD_CONV_EN_VAR;
249
    SPI_CLK_EN <= SPI_CLK_EN_VAR;
250
  end process;
251
end Behavioral;

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


Lesenswert?

Samer Afach schrieb:
> 1- Ist es eine gute Idee, den Code als State Machine zu schreiben?
Ich denke, das ist sinnvoll. Fast alles, das einen Ablauf hat, muß in 
einer oder mehreren Statemachines umgesetzt werden.

> 2- Meine State Machine funktioniert leider nicht.
Das ist schade.

> Die States ändern sich
> nicht. Ich kann es nicht auf der Simulation zum laufen kriegen.
Wie sieht deine Testbench aus?

> 3- Warum sagt das Synthesiswerkzeug, dass es Latches geben wird, obwohl
> alle Variablen schon in Allen states definiert wurden?
Darum z.B.:
1
 if (CONV_PULSE_COUNTER_VAR < AD_CONV_PULSE_LENGTH) then
2
       CONV_PULSE_COUNTER_VAR := CONV_PULSE_COUNTER_VAR + 1;   -- kombinatorische Schleife!!!
3
 else
4
       nx_state <= AD_CONV_WAIT_STATE;
5
 end if;
Das ist übrigens eigentlich kein Latch, sondern viel schlimmer:
Eine kombinatorische Schleife!!!
http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife
Das passiert Anfängern bei der Zwei-Prozess-Schreibweise gern...   :-/
Ich empfehle dann imerr sich mal die Ein-Prozess-Schreibweise anzusehen:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

Ein paar echte Latches hast du natürlich trotzdem noch:
1
        if (DATA_AC1_COUNTER_VAR < DATA_AC1_LENGTH) then
2
          if (DATA_AC1_COUNTER_VAR < regBits) then
3
            dataBuffer1(regBits - DATA_AC1_COUNTER_VAR) <= AD_DOUT; -- Ein Latch, weil kein Defaultwert für dataBuffer1
4
          end if;
5
          DATA_AC1_COUNTER_VAR := DATA_AC1_COUNTER_VAR + 1;
6
        else

BTW:
> AD_DOUT : IN  STD_LOGIC;
Sehr naheliegend...

Es ist schlecht, unnötig Variablen zu verwenden.
Wo lernt man diesen üblen Stil (Zweiprozessschreibweise mit Variablen)?

Samer Afach schrieb:
1
  if (rising_edge(clk)) then         -- eine STEIGENDE Flanke von clk
2
     SPI_SCK <= clk AND SPI_CLK_EN;  -- --> was meinst du: welchen Pegel hat clk an dieser Stelle IMMER?

Mir ist dein Code undurchschaubar (und das mag was heißen...).
DIE GROSSGESCHRIEBENEN VARIABLENNAMEN KRATZEN MIR DAS AUGE RAUS.
Daher mein Vorschlag: Sieh dir mal meinen SPI-Master an...
http://www.lothar-miller.de/s9y/categories/45-SPI-Master
Das ist sogar einen kleine Stimuli-Testbench dabei.

Alles in allem würde ich mal ein Blinklicht
http://www.lothar-miller.de/s9y/archives/80-Hello-World!.html
und dann ein Lauflicht für den Anfang empfehlen
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Vielen Dank für die Erklärung. Ich glaube es wird mir lange dauern bis 
ich das alles lese. Ich tue das während des Wochenendes.

Ich habe manche Fehler kontrolliert, wie den einen mit rising_edge, den 
du erklärt hast. Ich wollte das nur als Verbindung zwischen dem Signal 
und dem Output stellen. Ich habe es außer der Prozesse wiedergestellt.

Gibt es ein gutes Standard für Variablennamen, Funktionen und andere 
Namen auf VHDL? auf C++ gibt es viele, wie

counterLimit -> für variable
getValue -> für member funktionen
SeparateVars -> unabhängige funktionen
Vector3D -> Klassen
usw...

Weil diese sprache case insensitive ist, konnte ich kein Standard 
benutzen. Hast du einen Vorschlag dafür?

Würdest du meine Neue Posts hier merken, wenn ich sie in einem oder zwei 
Tage poste?

Vielen Dank

von Matthias N. (vbchaos)


Lesenswert?

Ich finds in VHDL angenehm, signale und variablen klein, constante, 
typen und generics groß zu schreiben. Daran erkenne ich immer obs etwas 
veränderliches oder konstantes ist.
Ist in VHDL ein bisschen geschmacksache weil case insensitive, aber 
allgemein schreibt man variablen/signals klein, schon du Umschalt-taste 
und die DEL taste :)

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


Lesenswert?

Samer Afach schrieb:
> Würdest du meine Neue Posts hier merken, wenn ich sie in einem oder zwei
> Tage poste?
Ja.

> Weil diese sprache case insensitive ist, konnte ich kein Standard
> benutzen. Hast du einen Vorschlag dafür?
Es gibt keinen Standard, aber man (wie erwähnt) die Groß- und 
Kleinschreibung sinnvoll nutzen. Auf jeden Fall ist komplett 
großegeschriebener längerer Text unlesbar.

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Hallo wieder :-),

ich habe viele änderungen gemacht, nachdem ich die Seiten gelesen habe,
die du mir vorgeschlagen hast :-).

Im bezug von kombinatorischen Schleifen, ich habe es gesehen, dass das
Synthesiswerkzeug automatisch die auf einen Addierer konvertiert. Es
sagt während des Synthesisprozess:

"Found 32-bit adder for signal <conv_pulse_counter_var$addsub0000>
created at line 115."

Alle kombinatorische Schleifen bekommen diese Behandlung.

Vorher, als ich eine Frage über einen Counter hier gestellt habe, hat
jemand diese Webseite mir gegeben>

http://www.lothar-miller.de/s9y/archives/2-Tastene...

damit ich einen Counter mit Switch machen kann ohne Prellen. Darin gibt
es eine kombinatorische Schleife. Ich verstehe nicht warum dort es
erlaubt ist, und hier nicht. Kannst du bitte erklären?

Ich habe auch das State machine in einem Process geschrieben, nicht mehr
zwei :-), und die großgeschriebene Namen habe ich korrigiert :-), nur
konstante haben großgeschriebene Buchstaben.

Kannst du bitte einen Augenblick auf dem neuen Code haben, und mir sagen
ob solcher Code für den SPI funktionieren würde, den man im User Guide
auf Seite 76 findet? Die Simulation zeigt gute Ergebnisse. Ich mache mir
sorge nur um das erste Input von Analog voltage Vin1. Das BarOut ist der
Ergebnis, den ich als Bar graph auf 8 leds sehen möchte, für jeden
Analog input.

Hier ist das User Guide:

http://www.xilinx.com/support/documentation/boards...

Ich bekomme gute Ergebnisse auf Simulation (angeblich), aber trotzdem
gibt das Synthesiswerkzeug komische Warnungen. Es sagt dass, z.B.,
BarOut_0 ein Konstant ist. Und auch dataBuffer1_VAR unverbunden ist...
ich verstehe nicht wie das konstant sein kann, wenn es durch ein State
geändert werden würde!!!

WARNING:Xst:1710 - FF/Latch <BarOut_0> (without init value) has a
constant value of 0 in block <ADCModule>. This FF/Latch will be trimmed
during the optimization process.
WARNING:Xst:2677 - Node <dataBuffer1_VAR_2> of sequential type is
unconnected in block <ADCModule>.
WARNING:Xst:2677 - Node <dataBuffer1_VAR_0> of sequential type is
unconnected in block <ADCModule>.
WARNING:Xst:2677 - Node <dataBuffer1_VAR_1> of sequential type is
unconnected in block <ADCModule>.
...

Vielen Dank.

Hier ist der Code und das Test Bench:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use STD.textio.all;
4
use IEEE.std_logic_textio.all;
5
6
-- Uncomment the following library declaration if using
7
-- arithmetic functions with Signed or Unsigned values
8
use IEEE.NUMERIC_STD.ALL;
9
10
-- Uncomment the following library declaration if instantiating
11
-- any Xilinx primitives in this code.
12
--library UNISIM;
13
--use UNISIM.VComponents.all;
14
15
entity ADCModule is
16
   Generic(BarSteps : Integer := 8; regBits : Integer := 14);
17
    Port ( ad_conv : OUT  STD_LOGIC;
18
           SPI_SCK : OUT  STD_LOGIC;
19
           AD_DOUT : IN  STD_LOGIC;
20
        BarOut : OUT STD_LOGIC_VECTOR(BarSteps-1 downto 0);
21
        CLK : IN STD_LOGIC        
22
        );
23
end ADCModule; 
24
25
architecture Behavioral of ADCModule is
26
  CONSTANT AD_CONV_PULSE_LENGTH : INTEGER := 0; --constants defining number of pulsess for each state
27
  CONSTANT AD_CONV_WAIT_LENGTH : INTEGER := 0;
28
  CONSTANT SPI_CLK_EN_LENGTH : INTEGER := 0;
29
  CONSTANT DATA_AC1_LENGTH : INTEGER := 14;
30
  CONSTANT DATA_AC_WAIT_LENGTH : INTEGER := 0;
31
  CONSTANT DATA_AC2_LENGTH : INTEGER := 14;
32
  CONSTANT SPI_CLK_END_LENGTH : INTEGER := 0;
33
  CONSTANT SPI_END_WAIT_LENGTH : INTEGER := 3;
34
35
 
36
  TYPE states is (ad_conv_pulse_state, ad_conv_wait_state, spi_clk_en_state, data_ac1_state, data_ac_wait_state, data_ac2_state, spi_clk_end_state, spi_end_wait_state);
37
  SIGNAL pr_state : states := ad_conv_pulse_state;
38
  SIGNAL nx_state: states;
39
  SIGNAL spi_clk_en, ad_conv_en : STD_LOGIC; --bits defining the state of SPI_CLK and ad_conv being enabled or disabled. Usage is defined in StateControl process.
40
  SIGNAL dataBuffer1, dataBuffer2 : STD_LOGIC_VECTOR(regBits-1 downto 0) := (others => '0');
41
  SIGNAL temp : INTEGER := 0;
42
43
  
44
  
45
  -- states description:
46
  
47
  -- I defined here a Zero state as the state where both SPI_SCK and ad_conv = 0.
48
  
49
  -- ad_conv_pulse_state: State defined in Fig. 9-6 by the pulse, whose length is minimum equals 4 ns.
50
  -- ad_conv_wait_state: State defined in Fig. 9-6, by the Zero state between the pulse of ad_conv and the first pulse of SPI_SCK.
51
  -- spi_clk_en_state: Stated that has SPI_SCK enabled till the beginning of data reception.
52
  -- data_ac1_state: State that receives the first bunch of data.
53
  -- data_ac_wait_state: Stated defined in Fig. 9-6 by the Zero state between the reception of the two bunches of data.
54
  -- data_ac2_state: State that receives the second bunch of data.
55
  -- spi_clk_end_state: State that keeps the remenant of SPI_CLK pulses there.
56
  -- spi_end_wait_state: A Zero state till the repetition of the whole operation.
57
begin
58
  ad_conv <= ad_conv_en;
59
  SPI_SCK <= clk AND spi_clk_en;  
60
  StateContol:
61
  process(clk)
62
    VARIABLE dataBuffer1_VAR, dataBuffer2_VAR : STD_LOGIC_VECTOR(regBits-1 downto 0) := (others => '0');
63
    VARIABLE ad_conv_en_var, spi_clk_en_var : STD_LOGIC := '0';
64
    VARIABLE conv_pulse_counter_var : INTEGER := 0; -- counter for every state for timing
65
    VARIABLE ad_conv_wait_counter_var : INTEGER := 0;
66
    VARIABLE spi_clk_en_counter_var : INTEGER := 0;
67
    VARIABLE data_ac1_counter_var : INTEGER := 0;
68
    VARIABLE data_ac_wait_counter_var : INTEGER := 0;
69
    VARIABLE data_ac2_counter_var : INTEGER := 0;
70
    VARIABLE spi_clk_end_counter_var : INTEGER := 0;
71
    VARIABLE spi_end_wait_counter_var : INTEGER := 0;
72
    
73
    variable my_line : line;
74
  begin
75
76
    if (rising_edge(clk)) then
77
78
      pr_state <= nx_state;
79
      
80
      
81
      case pr_state is -- in every state, all counters are reset to avoid having latches, but not the one getting counted over in the current state
82
      when ad_conv_pulse_state =>
83
        ad_conv_wait_counter_var := 0;
84
        spi_clk_en_counter_var := 0;
85
        data_ac1_counter_var := 0;
86
        data_ac_wait_counter_var := 0;
87
        data_ac2_counter_var := 0;
88
        spi_clk_end_counter_var := 0;
89
        spi_end_wait_counter_var := 0;
90
        
91
        ad_conv_en_var := '1';
92
        spi_clk_en_var := '0';
93
        if (conv_pulse_counter_var < AD_CONV_PULSE_LENGTH) then
94
        --write(my_line, conv_pulse_counter_var);
95
        --writeline(output, my_line);        
96
          conv_pulse_counter_var := conv_pulse_counter_var + 1;
97
        --write(my_line, conv_pulse_counter_var);
98
        --writeline(output, my_line);            
99
        else
100
          nx_state <= ad_conv_wait_state;
101
        end if;
102
        
103
        
104
      when ad_conv_wait_state =>
105
        conv_pulse_counter_var := 0;
106
        spi_clk_en_counter_var := 0;
107
        data_ac1_counter_var := 0;
108
        data_ac_wait_counter_var := 0;
109
        data_ac2_counter_var := 0;
110
        spi_clk_end_counter_var := 0;
111
        spi_end_wait_counter_var := 0;    
112
        
113
        ad_conv_en_var := '0';
114
        spi_clk_en_var := '0';    
115
        if (ad_conv_wait_counter_var < AD_CONV_WAIT_LENGTH) then
116
          --write(my_line, ad_conv_wait_counter_var);
117
          --writeline(output, my_line);
118
          ad_conv_wait_counter_var := ad_conv_wait_counter_var + 1;
119
        else
120
          nx_state <= spi_clk_en_state;
121
        end if;
122
        
123
          --write(my_line, string'("Hello"));
124
          --writeline(output, my_line);
125
126
          
127
      when spi_clk_en_state =>
128
        conv_pulse_counter_var := 0;
129
        ad_conv_wait_counter_var := 0;
130
        data_ac1_counter_var := 0;
131
        data_ac_wait_counter_var := 0;
132
        data_ac2_counter_var := 0;
133
        spi_clk_end_counter_var := 0;
134
        spi_end_wait_counter_var := 0;          
135
      
136
        ad_conv_en_var := '0';
137
        spi_clk_en_var := '1';
138
        if (spi_clk_en_counter_var < SPI_CLK_EN_LENGTH) then
139
          spi_clk_en_counter_var := spi_clk_en_counter_var + 1;
140
        else
141
          nx_state <= data_ac1_state;
142
        end if;
143
      
144
      
145
      when data_ac1_state =>
146
        conv_pulse_counter_var := 0;
147
        ad_conv_wait_counter_var := 0;
148
        spi_clk_en_counter_var := 0;
149
        data_ac_wait_counter_var := 0;
150
        data_ac2_counter_var := 0;
151
        spi_clk_end_counter_var := 0;
152
        spi_end_wait_counter_var := 0;    
153
      
154
        ad_conv_en_var := '0';
155
        spi_clk_en_var := '1';
156
        if (data_ac1_counter_var < DATA_AC1_LENGTH) then
157
          --if (data_ac1_counter_var < regBits) then
158
--            write(my_line, data_ac1_counter_var);
159
--            writeline(output, my_line);
160
--            write(my_line, DATA_AC1_LENGTH);
161
--            writeline(output, my_line);
162
--            write(my_line, DATA_AC1_LENGTH);
163
--            writeline(output, my_line);
164
--            
165
            dataBuffer1_VAR(regBits - data_ac1_counter_var - 1) := AD_DOUT;
166
          --end if;
167
          data_ac1_counter_var := data_ac1_counter_var + 1;
168
        else
169
          nx_state <= data_ac_wait_state;
170
        end if;
171
      
172
      
173
      when data_ac_wait_state =>
174
        conv_pulse_counter_var := 0;
175
        ad_conv_wait_counter_var := 0;
176
        spi_clk_en_counter_var := 0;
177
        data_ac1_counter_var := 0;
178
        data_ac2_counter_var := 0;
179
        spi_clk_end_counter_var := 0;
180
        spi_end_wait_counter_var := 0;    
181
        
182
        ad_conv_en_var := '0';
183
        spi_clk_en_var := '1'; --here switch back to 1 during tests
184
        if (data_ac_wait_counter_var < DATA_AC_WAIT_LENGTH) then
185
          data_ac_wait_counter_var := data_ac_wait_counter_var + 1;
186
        else
187
          nx_state <= data_ac2_state;
188
        end if;
189
      
190
      
191
      when data_ac2_state =>
192
        conv_pulse_counter_var := 0;
193
        ad_conv_wait_counter_var := 0;
194
        spi_clk_en_counter_var := 0;
195
        data_ac1_counter_var := 0;
196
        data_ac_wait_counter_var := 0;
197
        spi_clk_end_counter_var := 0;
198
        spi_end_wait_counter_var := 0;    
199
        
200
        ad_conv_en_var := '0';
201
        spi_clk_en_var := '1';
202
        if (data_ac2_counter_var < DATA_AC2_LENGTH) then
203
          --if (data_ac2_counter_var < regBits) then
204
            dataBuffer2_VAR(regBits - data_ac2_counter_var - 1) := AD_DOUT;
205
          --end if;
206
          data_ac2_counter_var := data_ac2_counter_var + 1;
207
        else
208
          nx_state <= spi_clk_end_state;
209
        end if;
210
        
211
        
212
      when spi_clk_end_state =>
213
        conv_pulse_counter_var := 0;
214
        ad_conv_wait_counter_var := 0;
215
        spi_clk_en_counter_var := 0;
216
        data_ac1_counter_var := 0;
217
        data_ac_wait_counter_var := 0;
218
        data_ac2_counter_var := 0;
219
        spi_end_wait_counter_var := 0;          
220
      
221
        ad_conv_en_var := '0';
222
        spi_clk_en_var := '1';
223
        if (spi_clk_end_counter_var < SPI_CLK_END_LENGTH) then
224
          spi_clk_end_counter_var := spi_clk_end_counter_var + 1;
225
        else
226
          nx_state <= spi_end_wait_state;
227
        end if;
228
        
229
      when spi_end_wait_state =>
230
        conv_pulse_counter_var := 0;
231
        ad_conv_wait_counter_var := 0;
232
        spi_clk_en_counter_var := 0;
233
        data_ac1_counter_var := 0;
234
        data_ac_wait_counter_var := 0;
235
        data_ac2_counter_var := 0;
236
        spi_clk_end_counter_var := 0;
237
      
238
        ad_conv_en_var := '0';
239
        spi_clk_en_var := '0';
240
        if (spi_end_wait_counter_var < SPI_END_WAIT_LENGTH) then
241
          spi_end_wait_counter_var := spi_end_wait_counter_var + 1;
242
        else
243
          nx_state <= ad_conv_pulse_state;
244
        end if;
245
    end case;
246
      temp <= conv_pulse_counter_var;
247
      ad_conv_en <= ad_conv_en_var;
248
      spi_clk_en <= spi_clk_en_var;
249
      if(pr_state = spi_end_wait_state) then
250
        dataBuffer1 <= dataBuffer1_VAR;
251
        dataBuffer2 <= dataBuffer2_VAR;
252
      end if;
253
    end if;
254
  end process;
255
  process(ad_conv_en)
256
    VARIABLE barVec : STD_LOGIC_VECTOR(barSteps-1 downto 0) := (others => '0');
257
    VARIABLE count : INTEGER := 0;
258
  begin
259
    if (rising_edge(ad_conv_en)) then
260
    For count in 0 to barSteps - 1 loop
261
      if (unsigned(dataBuffer1) < (2048*count)) then
262
        barVec(count) := '1';
263
      else
264
        barVec(count) := '0';
265
      end if;
266
    end loop;
267
    BarOut <= barVec;
268
    end if;
269
  end process;
270
end Behavioral;
-----------------Test Bench-----------------------
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
use STD.textio.all;
4
use IEEE.std_logic_textio.all;
5
6
-- Uncomment the following library declaration if using
7
-- arithmetic functions with Signed or Unsigned values
8
USE ieee.numeric_std.ALL;
9
 
10
ENTITY ADCModuleTestBench IS
11
END ADCModuleTestBench;
12
 
13
ARCHITECTURE behavior OF ADCModuleTestBench IS 
14
 
15
    -- Component Declaration for the Unit Under Test (UUT)
16
 
17
    COMPONENT ADCModule
18
    PORT(
19
         AD_CONV : OUT  std_logic;
20
         SPI_SCK : OUT  std_logic;
21
         AD_DOUT : IN  std_logic;
22
         BarOut : OUT  std_logic_vector(7 downto 0);
23
         CLK : IN  std_logic
24
        );
25
    END COMPONENT;
26
    
27
28
   --Inputs
29
   signal AD_DOUT : std_logic := '0';
30
   signal CLK : std_logic := '0';
31
32
   --Outputs
33
   signal AD_CONV : std_logic;
34
   signal SPI_SCK : std_logic;
35
   signal BarOut : std_logic_vector(7 downto 0);
36
  constant numtoconv : std_logic_vector(13 downto 0) := std_logic_vector(to_unsigned(10922,14));
37
38
   -- Clock period definitions
39
   constant CLK_period : time := 20 ns;
40
 
41
BEGIN
42
 
43
  -- Instantiate the Unit Under Test (UUT)
44
   uut: ADCModule PORT MAP (
45
          AD_CONV => AD_CONV,
46
          SPI_SCK => SPI_SCK,
47
          AD_DOUT => AD_DOUT,
48
          BarOut => BarOut,
49
          CLK => CLK
50
        );
51
52
   -- Clock process definitions
53
   CLK_process :process
54
   begin
55
    CLK <= '0';
56
    wait for CLK_period/2;
57
    CLK <= '1';
58
    wait for CLK_period/2;
59
   end process;
60
 
61
62
   -- Stimulus process
63
   stim_proc: process(AD_CONV,SPI_SCK)
64
    variable clk_count : integer := 0;
65
    variable indexcount : integer := 14;
66
    variable my_line : line;    
67
   begin    
68
      -- hold reset state for 100 ns.
69
  if(rising_edge(ad_conv))then
70
    clk_count := 0;
71
    indexcount := 14;
72
  end if;
73
  if(rising_edge(spi_sck))then
74
  write(my_line, clk_count);
75
  writeline(output, my_line);
76
  write(my_line, indexcount);
77
  writeline(output, my_line);
78
  
79
  If (clk_count < 2) then
80
    clk_count := clk_count + 1;
81
  else 
82
    if (indexcount = 0) then
83
      --clk_count := 0;
84
      --indexcount := 14;
85
    else
86
      AD_DOUT <= numtoconv(indexcount - 1);
87
      indexcount := indexcount - 1;
88
    end if;
89
  end if;
90
91
      -- insert stimulus here 
92
  end if;
93
   end process;
94
95
END;


Ich bedanke mich sehr bei deinem Geduld :-)

von berndl (Gast)


Lesenswert?

Samer Afach schrieb:
> process(clk)
>     VARIABLE dataBuffer1_VAR, dataBuffer2_VAR : STD_LOGIC_VECTOR(regBits-1 
downto 0) := (others => '0');
>     VARIABLE ad_conv_en_var, spi_clk_en_var : STD_LOGIC := '0';
>     VARIABLE conv_pulse_counter_var : INTEGER := 0; -- counter for every state 
for timing
>     VARIABLE ad_conv_wait_counter_var : INTEGER := 0;
>     VARIABLE spi_clk_en_counter_var : INTEGER := 0;
>     VARIABLE data_ac1_counter_var : INTEGER := 0;
>     VARIABLE data_ac_wait_counter_var : INTEGER := 0;
>     VARIABLE data_ac2_counter_var : INTEGER := 0;
>     VARIABLE spi_clk_end_counter_var : INTEGER := 0;
>     VARIABLE spi_end_wait_counter_var : INTEGER := 0;

OMG, dir ist hoffentlich klar, dass du hier 8 counter mit einer Breite 
von 32bit generierst? Du kannst auch in jedem state den gleichen counter 
wieder verwenden! Und dieses Gedoens mit Variablen hat Lothar ja schon 
angesprochen: Warum macht man sowas? Man hat den Eindruck, dass die 
Leute von 'echter' HW keine Ahnung haben...

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

ich habe schon in meinem Code ranges gestellt. Ich benutze viele 
Variablen nur sicher zu sein dass keine Probleme passieren können, weil 
ich ein Anfänger bin. Später wenn es richtig funktioniert, schritt für 
schritt, kann man es optimieren bis es super Optimum ist :)

Findet ihr was falsches noch Leute? :)

von Samer A. (Firma: Personal) (thedestroyer)


Angehängte Dateien:

Lesenswert?

Ich habe viele Änderungen gemacht, und ich habe eine andere State 
Machine hinzufügt für den Amplifier in Seite 74.

Ich bekomme viele Warnungen mit latches on trimms von variable. Könnt 
Ihr bitte den Code checken und mir sagen wie man diese Fehler reparieren 
kann?

Die Arbeite ist fast fertig. Es wäre sehr schön wenn ihr mir helfen 
könntet :)

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


Lesenswert?

Samer Afach schrieb:
> Vorher, als ich eine Frage über einen Counter hier gestellt habe, hat
> jemand diese Webseite mir gegeben>
Das war ich.
> http://www.lothar-miller.de/s9y/archives/2-Tastene...
Meintest du den da:
http://www.lothar-miller.de/s9y/archives/2-Tastenentprellung.html
> damit ich einen Counter mit Switch machen kann ohne Prellen.
Ich meine aber geschrieben zu haben dass man diese Code nicht verwenden 
soll, denn damit
1
kommt oft eine unangenehme Überraschung: der Zähler zählt viel zu viele 
2
Impulse, die State-Machine springt wild hin- und her.
3
Mit einer Beschreibung wie dieser wird das unausweichlich passieren: ...
> Darin gibt es eine kombinatorische Schleife.
Dort gibt es sicher keine kombinatorische Schleife, weil nur in 
getakteten Prozessen gezählt wird. Getaktete Prozesse können keine 
kombinatorischen Schleifen haben!
> Ich verstehe nicht warum dort es erlaubt ist, und hier nicht.
Wie gesagt: die kombinatorische Schleife ist nicht "erlaubt", sondern 
nicht vorhanden.
> Kannst du bitte erklären?
Mir fällt kein Fall ein, wo eine kombinatorische Schleife "erlaubt" sein 
könnte...

Samer Afach schrieb:
> Findet ihr was falsches noch Leute? :)
Die Denkweise:
> Ich benutze viele Variablen nur sicher zu sein dass keine Probleme
> passieren können, weil ich ein Anfänger bin.
Viele Probleme passieren WEGEN Variablen.

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Ah ja! dann heißt das, dass wie ich es jetzt benutze (mit getaktete 
Prozesse) macht keine kombinatorische Schleifen! danke für die 
Erklärung.

Jetzt bekomme ich Warnungen nur wegen "dataBuffer1", "dataBuffer1_var" 
und BarOut_0, die Counters Variablen machen keine Probleme mehr.

Kannst du bitte den Code angucken und synthesieren lassen und mir sagen, 
wie ich diese Warnungen vermeiden kann? das wäre sehr nett von dir :-). 
Ich habe schon alles versucht was ich kann!

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


Lesenswert?

Samer Afach schrieb:
> Jetzt bekomme ich Warnungen nur wegen "dataBuffer1", "dataBuffer1_var"
> und BarOut_0,
Siehe den Beitrag "Re: State machine für SPI" ab
>>>>> Ein paar echte Latches hast du...
1
dataBuffer1(regBits - DATA_AC1_COUNTER_VAR) <= AD_DOUT; -- Latch
Das ist ein Latch, weil dataBuffer1 nicht getaktet ist. Oder auch, weil 
kein Defaultwert für dataBuffer1 angegeben wurde (was aber auch sinnlos 
wäre...).

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Vielen Dank für deine Antwort.

Ich kann noch nicht verstehen wie ich dataBuffer1 takten lassen kann :(. 
Es liegt schon unter rising_edge(clk). Was könnte man noch takten?

Soll ich den Befehl in einem anderen Prozess stellen? bitte schreib 
einen kleinen Code, darin sieht man wie ich dataBuffer1 takten lassen 
kann.

Ich weiß ich frage schon viel an, aber das ist mein erster echter Code 
mit echten Anwendung :)

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


Lesenswert?

Samer Afach schrieb:
> Ich kann noch nicht verstehen wie ich dataBuffer1 takten lassen kann :(.
> Es liegt schon unter rising_edge(clk).
Richtig. Das habe ich übersehen... :-/

> Jetzt bekomme ich Warnungen nur wegen "dataBuffer1", "dataBuffer1_var"
> und BarOut_0, die Counters Variablen machen keine Probleme mehr.
Ich habe das mal synthetisiert (Xilinx ISE13.1) und bekomme folgende 
Warnungen:
1
WARNING:Xst:646 - Signal <dataBuffer2> is assigned but never used. This unconnected signal will be trimmed during the optimization process.
2
WARNING:Xst:1710 - FF/Latch <BarOut_0> (without init value) has a constant value of 0 in block <ADCModule>. This FF/Latch will be trimmed during the optimization process.
3
WARNING:Xst:1710 - FF/Latch <BarOut_0> (without init value) has a constant value of 0 in block <ADCModule>. This FF/Latch will be trimmed during the optimization process.
4
WARNING:Xst:2677 - Node <dataBuffer1_VAR_0> of sequential type is unconnected in block <ADCModule>.
5
WARNING:Xst:2677 - Node <dataBuffer1_VAR_1> of sequential type is unconnected in block <ADCModule>.
6
WARNING:Xst:2677 - Node <dataBuffer1_VAR_2> of sequential type is unconnected in block <ADCModule>.
7
WARNING:Xst:2677 - Node <dataBuffer1_VAR_5> of sequential type is unconnected in block <ADCModule>.
8
WARNING:Xst:2677 - Node <dataBuffer1_VAR_3> of sequential type is unconnected in block <ADCModule>.
9
WARNING:Xst:2677 - Node <dataBuffer1_VAR_4> of sequential type is unconnected in block <ADCModule>.
10
WARNING:Xst:2677 - Node <dataBuffer1_VAR_8> of sequential type is unconnected in block <ADCModule>.
11
WARNING:Xst:2677 - Node <dataBuffer1_VAR_6> of sequential type is unconnected in block <ADCModule>.
12
WARNING:Xst:2677 - Node <dataBuffer1_VAR_7> of sequential type is unconnected in block <ADCModule>.
13
WARNING:Xst:2677 - Node <dataBuffer1_VAR_9> of sequential type is unconnected in block <ADCModule>.
14
WARNING:Xst:2677 - Node <dataBuffer1_VAR_10> of sequential type is unconnected in block <ADCModule>.
15
WARNING:Xst:2677 - Node <dataBuffer1_0> of sequential type is unconnected in block <ADCModule>.
16
WARNING:Xst:2677 - Node <dataBuffer1_1> of sequential type is unconnected in block <ADCModule>.
17
WARNING:Xst:2677 - Node <dataBuffer1_2> of sequential type is unconnected in block <ADCModule>.
18
WARNING:Xst:2677 - Node <dataBuffer1_3> of sequential type is unconnected in block <ADCModule>.
19
WARNING:Xst:2677 - Node <dataBuffer1_4> of sequential type is unconnected in block <ADCModule>.
20
WARNING:Xst:2677 - Node <dataBuffer1_5> of sequential type is unconnected in block <ADCModule>.
21
WARNING:Xst:2677 - Node <dataBuffer1_6> of sequential type is unconnected in block <ADCModule>.
22
WARNING:Xst:2677 - Node <dataBuffer1_7> of sequential type is unconnected in block <ADCModule>.
23
WARNING:Xst:2677 - Node <dataBuffer1_8> of sequential type is unconnected in block <ADCModule>.
24
WARNING:Xst:2677 - Node <dataBuffer1_9> of sequential type is unconnected in block <ADCModule>.
25
WARNING:Xst:2677 - Node <dataBuffer1_10> of sequential type is unconnected in block <ADCModule>.
Daran ist nichts Schlimmes. Hier sagt der Synthesizer einfach, dass 
diese signale im Design nicht verwendet werden und daher entweder gar 
nicht erzeugt oder wegoptimiert werden.

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Danke sehr für deine Antwort.

Also mit dataBuffer2, ist es mir egal. Es ist nicht verbunden und ich 
brauche es nicht. Aber die anderen sind verwirrend. Schau mal die 
Simulation Ergebnisse (ich habe sie schonmal gepostet hier). Man sieht 
das BarOut_0 und dataBuffer1/_var ändern sich, und eigentlich sind sie 
wichtig, weil sie kontrollieren die Ergebnisse vom ADC!

Wie kann das Synthesiswerkzeug sagen, dass sie unverbunden sind, und die 
Simulation gibt die richtigen Ergebnisse durch diese 2 Variablen?

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


Lesenswert?

Samer Afach schrieb:
> Man sieht das BarOut_0 und dataBuffer1/_var ändern sich
Nein. BarOut(0) ändert sich nie!
1
   For count in 0 to barSteps - 1 loop                  -- count = 0..7
2
      if (unsigned(dataBuffer1) < (2048*count)) then    -- ein unsigned Wert kann nie kleiner als 0 (0*2048) sein!
3
         barVec(count) := '1';
4
      else                      
5
         barVec(count) := '0';                          -- deshalb ist barVec(0) immer '0'
6
      end if;
7
   end loop;
8
   BarOut <= barVec;


> dataBuffer1/_var
Ist nicht weiter verwendet und wird deshalb rausoptimiert.
>> Node <dataBuffer1_VAR_0> ... is unconnected in block <ADCModule>

von Johann (Gast)


Lesenswert?

Ist das nicht alles ein wenig too much für eine SPI-Verbindung?

Wenn ich einen Sender bauen möchte dann benötigt man ja nur einen CLK, 
eine Datenleitung und eine CS Leitung.

Dann baut man ein Modul wo man 8Bit parallel reingibt ein seriell wieder 
rauskommt. Man kann dann noch eine Busy Leitung oder einen zusätzlich 
Buffer integrien.

Jedoch ist es nur ein Schieberegister.

SPI_DATA <= SPI_BUFFER(7);

SPI_BUFFER <= SPI_BUFFER(6 downto 0) & SPI_BUFFER(7);

Dann benötigt man noch einen Counter der bis 8 läuft. Den SPI-Clock muss 
man nicht mal unterbrechen der kann immer laufen

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


Lesenswert?

Johann schrieb:
> Ist das nicht alles ein wenig too much für eine SPI-Verbindung?
Na gut, da ist die Verwaltung auch noch mit drin, aber ich hatte im 
Beitrag "Re: State machine für SPI" schon angemerkt, 
dass das kürzer gehen würde.

> Den SPI-Clock muss man nicht mal unterbrechen der kann immer laufen
Davor sollte man aber das Datenblatt genau lesen, bei manchen Devices 
darf der Takt erst nach dem CS anfangen. Zumindest ist ein 
durchlaufender Takt im DB nicht spezifizert...

von PittyJ (Gast)


Lesenswert?

Meinen Senf auch noch mal dazu:

Ich hatte mal Probleme, als ich SPI-Takt und Daten gleichzeitig 
behandelt habe. Wenn der SPI-Takt steigt, dann mussten aber schon die 
SPI-Daten gültig anliegen.
Also habe ich noch eine Schicht darunter implementiert, der mit 4fachen 
SPI-Takt arbeitet, und dann die Daten schon eine 4tel Impuls vorher auf 
die Leitung gelegt hat, und dann erst den Takt aktivierte.

Das Verfahren konnte ich in dem Wust der Variablen und States hier nicht 
erkennen.

Mein Verfahren kamm dann auch mit weniger States und ohne Variablen aus.

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


Lesenswert?

PittyJ schrieb:
> Ich hatte mal Probleme, als ich SPI-Takt und Daten gleichzeitig
> behandelt habe.
Das ist vom SPI auch anders vorgesehen... :-o

An der einen Flanke werden Daten übernommen, an (besser wegen) der 
anderen werden sie geändert:
http://www.lothar-miller.de/s9y/categories/17-SPI
Soweit die Idee, aber in der Praxis ist SPI ja nur gekoppelte 
Schieberegister, und dei reagieren auf die selbe Flanke. Also wird mit 
der Taktflanke das vorher anliegende Datum übernommen und wegen der 
Taktflanke das am Ausgang ausgegeben.
Der ungünstigste Fall ist, wenn die Daten erst ein paar ns vor dem Takt 
(oder gar erst gleichzeitig mit dem Takt) stabil sind. Dann wird 
zwingend die Setup-Zeit des Flipflops verletzt.

> Wenn der SPI-Takt steigt, dann mussten aber schon die SPI-Daten gültig
> anliegen.
Dann werden Sie entweder:
- mit der fallenden Flanke ausgegeben
oder:
- einen Takt früher mit der steigenden Flanke ausgegeben

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Vielen Dank für eure Erklärungen :)

Also jetzt bekomme ich Warnung mit Place & Route. Ich weiß nicht ob man 
das ignorieren darf.

WARNING:Route:455 - CLK Net:ad_conv_en may have excessive skew because
      0 CLK pins and 1 NON_CLK pins failed to route using a CLK 
template.
WARNING:Route:455 - CLK Net:downClk6 may have excessive skew because
      0 CLK pins and 2 NON_CLK pins failed to route using a CLK 
template.

Ich habe danach gelesen:

http://www.xilinx.com/support/answers/21723.htm

es wurde vorgeschlagen, dass ich diese Warnung ignorieren darf, nur mit 
besonderer Bedingung:

"If the loads on the net shown in FPGA Editor are in accord with your 
design, the skew reported in the PAR report is not critical for the 
design, and the timing constraint requirement on that net is met, then 
this warning can be safely ignored."

Was heißt genau "in accord with your design"? ich habe den Kabeln 
verfolgen auf FPGA Editor, und habe nichts verstanden. Gibt es etwas, 
dass ich in meinem Code ändern soll diese Warnung vernichten zu können? 
oder muss ich was mit was anderes tun?

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Ich habe das Problem gelöst! ich habe dafür nur alle andere Prozesse in 
dem ersten Prozess gestellt. Also jetzt gibt es nur ein Prozess mit 
alllllleeeeeeeennnnn Befehlen zusammen!!!

Macht das sinn? warum kriege ich immer Probleme wenn ich mehr als ein 
Prozess benutze?

Vielen Dank!

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


Lesenswert?

Samer Afach schrieb:
> Also jetzt gibt es nur ein Prozess mit
> alllllleeeeeeeennnnn Befehlen zusammen!!!
> Macht das sinn?
Wenn klappt ist es ja gut, es wird eben mit einem Monsterprozess schnell 
ein wenig unübersichtlich...

> warum kriege ich immer Probleme wenn ich mehr als ein Prozess benutze?
Das hier kommt daher, dass du 2 Takte verwendest:
> WARNING:Route:455 - CLK Net:ad_conv_en may have excessive skew because
>       0 CLK pins and 1 NON_CLK pins failed to route using a CLK
> template.
> WARNING:Route:455 - CLK Net:downClk6 may have excessive skew because
>       0 CLK pins and 2 NON_CLK pins failed to route using a CLK
> template.
Ein Takt ist alles, was auf rising_edge() oder auf 'event reagiert. Und 
dann gelten meine Postulate:
1
Ein Design (insbesondere ein Anfängerdesign) hat genau 1 Takt, 
2
der immer auf dieselbe Flanke aktiv ist. 
3
Es gibt keinen (und schon gar keinen asynchronen) Reset.
4
Externe Signale werden über 2 Flipflops einsynchronisiert.
5
Jede Abweichung von diesen Regeln muß fundiert begründet werden können.

BTW:
zu deiner extensiven Verwendung von Variablen lies mal den 
Beitrag "Variable vs Signal"

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Vielen Dank man. Ich bedanke mich seeeeeeeeeeeehr bei dir :-)

ich habe zu viel von dir gelernt, seitdem ich mit VHDL angefangen habe 
:-)

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


Lesenswert?

Samer Afach schrieb:
> Vielen Dank
Keine Ursache. Nur nicht aufgeben...  ;-)

BTW: leih dir mal VHDL-Synthese von Reichardt&Schwarz aus...

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Ich habe schon The Designer's Guide to VHDL bestellt :-) (du hast mir 
über dieses Buch erzählt). Ich habe die PDF Version angeguckt und hat es 
mir gefallen!

Wenn du eine PDF Version dieses Buchs hast, wäre schön wenn du es mir 
schicken kannst :-). Leider habe ich keine Bibliothek bei mir (es ist 
kompliziert).

Danke wieder!

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


Lesenswert?

Samer Afach schrieb:
> Wenn du eine PDF Version dieses Buchs hast, wäre schön wenn du es mir
> schicken kannst :-)
Tut mir leid, habe ich nicht.

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.