Forum: FPGA, VHDL & Co. Hilfe bei VHDL-Modul für ADC128S022 im DE0-Nano Board


von Gerd M. (Gast)



Lesenswert?

Hallo,
habe das DE0-Nano Cyclone IV Eval-Board. (Von mir ist dann auch der 
aktuelle Beitrag "Clock teilen oder Clock-Enable?")

Das Board hat einen ADC128S022, den ich seit geraumer Zeit zu steuern 
versuche, bzw. ein Modul in VHDL dafür zu entwerfen.

Datenblatt des ADC128S022:

http://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CC8QFjAB&url=http%3A%2F%2Fwww.ti.com%2Flit%2Fds%2Fsymlink%2Fadc128s022.pdf&ei=nrNhUMjEKsaQswan6oG4AQ&usg=AFQjCNFc66MAyUeuvsc3GqSMtDGBNhZlWg&cad=rja

Das Timing-Modell habe ich der Seite 8 des Datenblattes entnommen.
Der SCLK kann, so wie ich das verstanden habe, von 1,8MHz bis 3,2 MHz 
betragen?

Aus diesem Grund habe ich geplant den ADC mit 3,125MHz anzusteuern 
(ergibt sich so aus dem Teilerverhältnis ganz gut, denn das DE0-Nano 
stellt einen "Main-Clock" von 50MHz zu Verfügung.

Ich habe gedacht, das ganze modular aufzubauen. (Ich wollte das endlich 
mal ordentlicher angehen ;) ). Da im Datenblatt immer mit der fallenden 
FLanke gearbeitet wird, frage ich hier auch immer die fallende Flanke 
ab!

Ich habe nun also folgende vhd-Dateien mit den zugehörigen Entities:

"CLKDIV.vhd"  --> enthält einen einfachen generischen Taktteiler, der 
mir ein 3,125MHz Signal ableiten soll (aus den 50MHz)

"CLKENGEN.vhd" --> enthält einen Taktteiler, wobei hier nur ein enable 
Signal erzeugt wird ebenfalls 3,125MHz

"ADC_ADDR_CODER.vhd" --> enthält ein Modul, das an den ADC die 
Adressdaten (an DIN) senden soll, also können hier parallel 3Bit 
Adressdaten seriell an den ADC geschickt werden, auf diese Weise kann 
ein bestimmter der 8 ADC Kanäle des ADC128S022 abgefragt werden.
Des Weiteren wird das /CS also Chip Select Signal durchgeschleift, so 
dass später die Analog digital wandlung per Signal an oder ausgeschaltet 
werden kann.

"DATA-RECEIVE.vhd" --> enthält eine entity, die die vom ADC gesendeten 
Daten empfangen soll, dabei wird abgefragt, ob 4 mal low an "DOUT" 
angelegen hat.....




Nun das Problem:

Ich habe jedes Modul einzeln mit Modelsim simuliert und entsprechend 
existiert zu jedem Modul eine Test Bench. Nach meiner Auffassung 
scheinen die einzelnen Test funktional in Ordnung zu sein.


Dann wollte ich alle Module gemäß bild1.jpg vernetzten das übergeordnete 
Modul befindet sich in
"ADC128S022.vhd"
dazu habe ich ebenfalls eine Test Bench "gebastelt" leider funktionieren 
die einzelnen Module nun nicht mehr??? ich kann mir nicht erklären 
warum?

Da ich sonst nicht so viel mit Komponenten gearbeitet habe könnte was 
mit der Komponenteneinbindung schief gegangen sein??

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


Lesenswert?

Ich hatte noch nicht die Zeit, das Ganze anzusehen, aber das gibt mir zu 
denken:
1
use IEEE.STD_LOGIC_ARITH.ALL;
2
use IEEE.STD_LOGIC_UNSIGNED.ALL;
3
use IEEE.NUMERIC_STD.ALL;
Zuviel des Guten! Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"

> Das Timing-Modell habe ich der Seite 8 des Datenblattes entnommen.
Aha, simples SPI...
Ich mach das so:
http://www.lothar-miller.de/s9y/categories/45-SPI-Master

> Ich habe nun also folgende vhd-Dateien mit den zugehörigen Entities:
Warum jeden Dreizeiler mit 200% Overhead in ein eigenes Modul stecken?

> leider funktionieren die einzelnen Module nun nicht mehr???
Was funktioniert nicht mehr?

von Gerd M. (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Das Timing-Modell habe ich der Seite 8 des Datenblattes entnommen.
> Aha, simples SPI...
> Ich mach das so:
> http://www.lothar-miller.de/s9y/categories/45-SPI-Master

Ok ich denke mit einigen Inspiration von deinem SPI werde ich das jetzt 
auch etwas klarer hinbekommen.... ich hatte das jetzt irgendwie zu sehr 
"modularisieren" wollen!!!

Aber ein Bestätigen, dass Senden oder Empfang fertig ist, gibt der ADC 
nicht, sowie dein SPI drauf wartet also "tx_done" z.B.?

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


Lesenswert?

Gerd M. schrieb:
> Aber ein Bestätigen, dass Senden oder Empfang fertig ist, gibt der ADC
> nicht,
Nein. Denn der ADC ist ein Slave. Er wird also genau dann fertig sein, 
wenn dein Master fertig ist. Das ist nach 16 SCLK Takten der Fall, 
denn SPI sind ja nur zwei gekoppelte Schieberegister:
http://www.lothar-miller.de/s9y/categories/17-SPI
Um die Sache zu vereinfachen, empfehle ich dir den Modus im Bild 2 auf 
Seite 8. Dort wird mit CS nach jedem Frame neu synchronisiert.

> sowie dein SPI drauf wartet also "tx_done" z.B.?
Mein SPI generiert das tx_done für die Ansteuerung durch ein 
übergeordnetes Modul. Das ieht dann am tx_done, dass die nächste 
Übertragung gestartet werden darf.

Und eine unangenehme Sache ist an diesem ADC: mit der ersten Übertragung 
sendest du die Adresse für die Kanalauswahl der zweiten Wandlung. Bei 
der zweiten Wandlung sendest du die Kanalauswahl für die dritte 
Wandlung. Du weißt also vorher schon (bzw. du musst wissen), was als 
Nächstes gewandelt wird.
Aber umgekehrt ist die Sache wesentlich unangenehmer: bei der zweite 
Wandlung bekommst du das Ergebnis des Kanals, den du in der ersten 
Wandlung ausgewählt hast. Und du siehst an diesem Ergebnis nicht mehr, 
welcher das war! Du musst dir also merken, welches der zuvor 
ausgewählte Kanal war.
Ist doch nicht so schlimm, sagst du jetzt. Aber, glaub mir, du wirst 
noch ein paar mal drüber stolpern...  :-/

Der AD7490 macht das besser: er sendet in jedem Paket sowohl die 
Kanaladresse wie auch das zugehörige Wandlungsergebins zurück. Bei 
diesem ADC musst du dir also nichts merken.

von Gerd M. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hab mich jetzt an deinem SPI orientiert.... allerdings "hau'" ich 
die Daten direkt raus bzw. empfange sie.

Das Empfangen scheint zu funktionieren aber die TX_DATA packt der nicht 
seriell auf den MOSI......

alles weitere, wie welche Kanal wurde gelesen etc. kommt dann später...

hier scheint was nicht zu gehen:
-- transmitting shift register
transmit_reg: process (CLK)
begin
  if (CLK'event and CLK = '1') then
    if TX_ENABLE = '1' then
      if (SPICLK ='1' and SPICLKLAST = '0') then
         TX_REG <= TX_REG(TX_REG'left-1 downto 0) & TX_REG(0);
      end if;
    end if;
  end if;
end process transmit_reg;

SCLK <= SPICLK;
MOSI <= TX_REG(TX_REG'left);
RX_DATA <= RX_REG_VALID;


dieser Befehl TX_REG'left gibt doch nur den größten Index...?

von Gerd M. (Gast)


Lesenswert?

hmmmh wenn ich das Senden wie folgt mit nem Zähler CNT machen klappt's!!

transmit_reg: process (CLK)
begin
  if (CLK'event and CLK = '1') then
    if TX_ENABLE = '1' then
      if (SPICLK ='1' and SPICLKLAST = '0') then
        MOSI_TEMP <= TX_REG(CNT);
        CNT <= CNT -1;
         --TX_REG <= TX_REG(TX_REG'left-1 downto 0) & TX_REG(0);
      end if;
    else
      CNT <= 15;
    end if;
  end if;
end process transmit_reg;

SCLK <= SPICLK;
MOSI <= MOSI_TEMP;
--MOSI <= TX_REG(TX_REG'left);
RX_DATA <= RX_REG_VALID;


Zeit für die Synthese?

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


Lesenswert?

Gerd M. schrieb:
> dieser Befehl TX_REG'left gibt doch nur den größten Index...?
Ja, das MSB...

Gerd M. schrieb:
> hmmmh wenn ich das Senden wie folgt mit nem Zähler CNT machen klappt's!!
Ändert sich wenigstens das Schieberegister:
TX_REG <= TX_REG(TX_REG'left-1 downto 0) & TX_REG(0);

> hmmmh wenn ich das Senden wie folgt mit nem Zähler CNT machen klappt's!!
Multipexer sind eher aufwendiger in FPGAs, weil viel Logik gebraucht 
wird...

von Gerd M. (Gast)


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
> Ändert sich wenigstens das Schieberegister:
> TX_REG <= TX_REG(TX_REG'left-1 downto 0) & TX_REG(0);
 als das gibt mir Quartus 2 dazu als Meldung heraus:

Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[15]" at ADC_SPI.vhd(111)
Error (10029): Constant driver at ADC_SPI.vhd(51)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[14]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[13]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[12]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[11]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[10]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[9]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[8]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[7]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[6]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[5]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[4]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[3]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[2]" at ADC_SPI.vhd(111)
Error (10028): Can't resolve multiple constant drivers for net 
"TX_REG[1]" at ADC_SPI.vhd(111)
Error (12153): Can't elaborate top-level user hierarchy
Error: Quartus II 32-bit Analysis & Synthesis was unsuccessful. 17 
errors, 3 warnings
  Error: Peak virtual memory: 366 megabytes
  Error: Processing ended: Wed Sep 26 16:09:10 2012
  Error: Elapsed time: 00:00:01
  Error: Total CPU time (on all processors): 00:00:01
Error (293001): Quartus II Full Compilation was unsuccessful. 19 errors, 
3 warnings



Also zumiindest klappt die "testweise" Adressierung über
TX_DATA <= "0111000000000000";

obwohl es eigentlich so sein müsste:
TX_DATA <= "0011100000000000";

um Channel7 anzusprechen!??!

Ich hoffe, ich hab hier nicht zu sehr genervt!

Also Vielen Dank soweit jetzt klappt das auch so langsam mit dem SPI 
(zumindest ein wenig). hätte nicht gedacht, dass das so "unkritisch" 
ist... lief nach erfolgreicher Simu auch auf dem FPGA!!

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


Lesenswert?

Fehlerursache: du treibst tx_reg gleichzeitig aus 2 Prozessen.

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.