Wir organisieren die Interaktion zwischen PC und DAC / ADC mithilfe von FPGA

In der modernen digitalen Welt besteht kein Zweifel an der Notwendigkeit von DAC / ADC ( Digital-Analog-Wandler / Analog-Digital-Wandler ): Sie werden zur Verarbeitung von Signalen von verschiedenen Sensoren, in Tongeräten, TV-Tunern, Videoeingangskarten, Videokameras usw. verwendet.



Die Verwendung oder das Debuggen eines DAC / ADC kann jedoch aufgrund der vom Hardwarehersteller festgelegten Einschränkungen schwierig sein, z. B. hinsichtlich der verwendeten Software oder der Steuerung des Geräts. Dies schlägt vor, ein eigenes Interaktionsmodell zu entwerfen.



In diesem Artikel werden wir die Möglichkeit betrachten, die Interaktion zwischen einem PC und einem DAC / ADC mithilfe von FPGAs zu organisieren.









Vorwort



Der Hauptzweck dieses Artikels besteht darin, die Lösung eines bestimmten Problems sowie die Vertrautheit mit den Interaktionsschnittstellen von integrierten Schaltkreisen (ICs) zu beschreiben. Der Hauptzweck des DAC / ADC wird hier nicht berücksichtigt.



Dieser Artikel erfordert einige Kenntnisse in objektorientierter Programmierung und Schaltung. Wenn Sie mit diesen Konzepten nicht vertraut sind, wird empfohlen, mit ihnen zu beginnen.



Ich hoffe, dass die Erfahrung einer Person, die zum ersten Mal auf das Problem der Kommunikation elektronischer Geräte stößt, für jemanden nützlich sein wird.



Viel Glück und neue Erfolge an alle!



Ein kleines Bildungsprogramm zu Schnittstellen



Haftungsausschluss



Wenn Sie mit der Struktur der Hauptschnittstellen für die IC-Kommunikation vertraut sind, können Sie diesen Punkt sicher überspringen.



Bildungsprogramm



, .



, (, .) . , .



, . , , , .. , . . – , . , . , .



, .





( ), :



  • «-»;
  • «»;
  • «» («»).


«-» — , . , — .







«» (, « » «») , . . , , , . .







( «») . , , , - . .









:



  • ;
  • ;
  • -.


, . . . , .







, . , , .







(-/)





:



  • ();
  • ();
  • ().


. .







, .

: , «» .







. .









:



  • ;
  • .


. . . ( – , – , , ). « » ( ). .







, , .







?



() SPI I2C UART.



I2C



I2C – . I2C . I2C «-», .



, , . , . 7- 16 . , 112 . I2C (SDA) (SCL).





I2C



SPI



SPI – , .



SPI «-». MOSI SCLK, . MISO, . SS.





SPI



UART



UART – – , .

RxD ( ) TxD ( ).



UART TxD . . UART , , UART , . , . 8 ( ), , .

UART «-». , UART . « » «».





UART





Was ist das DAC?









Zunächst scheint dies nicht der



Fall zu sein. Definieren wir zunächst den verwendeten DAC / ADC: Die Debug-Karte für analoge Geräte AD9993-EBZ ist ein Gerät, das vier 14-Bit-ADCs und zwei 14-Bit-DACs kombiniert.



Die Betriebsmodi dieses IC werden durch Ändern des Zustands seiner internen Register gesteuert. Der AD9993 verwendet 66 Register mit einer gespeicherten (verarbeiteten) Wortgröße von 8 Bit, deren Adressen durch dreistellige Hexadezimalwerte (12 Datenbits) beschrieben werden. Es werden zwei Arten von Befehlen unterstützt - Lesebefehl und Schreibbefehl. Mit anderen Worten, um den Betrieb des IC zu korrigieren, ist es notwendig, einen Befehl zu senden, um einen gültigen 8-Bit-Wert an eine bestimmte Registeradresse zu schreiben. Der Zugriff auf die Register dieses IC erfolgt über die serielle Peripherieschnittstelle (SPI), deren Verbindung auf der Debug-Karte über den 40-poligen FIFO_0-Anschluss oder über eine zusätzlich installierte Kontaktgruppe erfolgt.





Wie dieser (FIFO_0 - oberer grauer Stecker)



Grundlegende Anforderungen für SPI-Grenzparameter:



  • Maximale Datenübertragungsfrequenz - 25 MHz;
  • Die Dauer der oberen und unteren Pegel auf der Synchronisationssignalerzeugungsleitung beträgt 10 ns;
  • Pegeleinstellzeit auf Datenübertragungsleitungen und auf Auflösungsleitungen - 2 ns;
  • Pegelhaltezeit auf Datenübertragungsleitungen und auf Auflösungsleitung - 2 ns;
  • Die garantierte Gültigkeitsdauer eines Datenbits auf der Übertragungsleitung des Slave-Geräts beträgt 2 ns.


Eine vollständige Beschreibung der Funktionen des Geräts finden Sie in der Dokumentation .



Was sagt der Hersteller?



Empfohlenes Kontrollschema



Basierend auf der AD9993-EBZ-Dokumentation wird zur Steuerung des IC empfohlen, eine HSC-ADC-EVALC-Debug-Karte für analoge Geräte zu verwenden, die über einen 40-poligen Anschluss mit dem IC und über die USB-Schnittstelle mit einem PC verbunden ist.



SPIController wird als Steuerungssoftware verwendet.





Empfohlene





analoge Geräte HSC-ADC-EVALC-Schaltung (basierend auf Xilinx Virtex-4 FPGA)



Nachteile:



  • Hoher Preis. Das Debugboard HSC-ADC-EVALC auf der offiziellen Website von Analog Devices wird für 698,28 USD angeboten.
  • Unbequeme Benutzeroberfläche. Die SPIController-Software bietet neben der Hauptfunktion zum Schreiben und Lesen von Registern keine Möglichkeit zum Speichern oder geplanten Starten von Befehlen.
  • . SPI SPIController, . Analog Devices, SPI.




SPIController



:



  • .


HSC-ADC-EVALC



Es ist zu beachten, dass die Verwendung der HSC-ADC-EVALC-Karte für analoge Geräte als DAC / ADC-Steuergerät nicht ihr Hauptzweck ist.



Der HSC-ADC-EVALC wird hauptsächlich als Pufferspeicherkarte für den ADC verwendet, verfügt jedoch auch über die Funktionalität, Debugkarten über SPI zu konfigurieren, wenn die angeschlossenen Karten dies unterstützen.



Eigenes Interaktionsmodell



Grund für die Verwendung eines Zwischengeräts



Es ist offensichtlich, dass die Interaktion zwischen dem DAC / ADC und dem PC nicht direkt organisiert werden kann, da der SPI, mit dem der AD9993-EBZ programmiert ist, keine typische Schnittstelle eines modernen PCs ist.



Um dieses Problem zu lösen, musste ein Zwischengerät verwendet werden, das Daten von der von einem Computer gesendeten USB-Schnittstelle in das vom IC unterstützte SPI-Schnittstellenformat konvertiert.



Bei der Ausarbeitung der Optionen fiel die Wahl auf die Verwendung des Terasic DE10-Nano-Debug-Boards, das auf dem Cyclone V FPGA basiert.





Eigenes Interaktionsmodell



Warum ist FPGA so cool?



Die Hauptvorteile der Verwendung von FPGAs:



  • . DE10-Nano , , , . IDE, Verilog.
  • . DE10-Nano HSC-ADC-EVALC ($110 $698.28). DE10-Nano , .
  • . , .
  • . FPGA- (FPGA – field-programmable gate array – , ), ( ). rocketboards c .




...



Während des Entwurfs des Interaktionsmodells wurde beschlossen, die SPI-Schnittstelle basierend auf GPIO (General Purpose Pins) zu implementieren, deren Kontaktbasis auf dem DE10-Nano verfügbar ist. Die Implementierung eines FPGA-basierten SPI-Controllers sollte aufgrund der großen Menge an Materialien zu einem ähnlichen Thema keine besonderen Probleme verursachen.



Die Implementierung des Anschlusses des FPGA an den Computer über die USB-Schnittstelle verursachte jedoch Schwierigkeiten.



DE10-Nano verfügt über folgende USB-Anschlüsse:



  • USB-Mini-B mit FT232R-Chip, der eine UART-zu-USB-Verbindung realisiert.
  • USB mini-B wird vom SMSC USB3300-Chip gesteuert, der die physische Schicht der USB-Schnittstelle implementiert und zum Programmieren von FPGAs verwendet wird.


Die Verwendung dieser Ports wird durch die Tatsache erschwert, dass der DE10-Nano mit diesen Ports über das sogenannte HPS ( Hard Processor System ) kommuniziert - ein Teil des Cylone V-Chips, der ein Mikroprozessormodul, einen ARM Cortex-Prozessor, Flash-Speichercontroller und vieles mehr enthält. Der Hauptunterschied zwischen HPS und FPGAs besteht darin, dass HPS Blöcke einer unveränderlichen Struktur sind, für eine bestimmte Funktion optimiert sind und keine Programmierwerkzeuge haben (und daher schwierig sind).



Die HPS- und FPGA-Teile des Cyclone V-Chips haben ihre eigenen Pins. Diese Pins werden zwischen dem HPS und dem FPGA nicht frei geteilt. Die HPS-Kontakte werden von der auf dem HPS ausgeführten Software konfiguriert. Die FPGA-Pins werden mithilfe eines FPGA-Konfigurationsabbilds über das HPS oder eine andere unterstützte externe Quelle programmiert.



Um die Interaktion der programmierbaren Logik des Cyclone V-Chips mit diesen Ports zu organisieren, muss ein spezieller Linux-Bootloader erstellt werden, der auf dem HPS ausgeführt wird, und es muss ein Programm entwickelt werden, das Signale von den Controllern der verfügbaren USB-Ports an die freien Kontakte des FPGA übertragen kann.



Nach dem derzeitigen Kenntnisstand erwies sich diese Frage als überwältigend, weshalb beschlossen wurde, einen anderen Weg zu finden. Für Menschen, die mit einem ähnlichen Problem konfrontiert sind und sich entschlossen haben, es herauszufinden, kann es jedoch hilfreich sein, einen Artikel über eine mögliche Lösung zu lesen .



Es gibt einen Ausgang!



Nachdem das Internet gründlich durchsucht worden war, wurde beschlossen, einen externen UART-Controller zu verwenden.



Der externe UART-Controller ist eine kleine Karte, die auf dem FT232RL-Chip basiert. Die Karte verfügt über Mini-USB-B-Anschlüsse für die Kommunikation mit einem Computer und einen 6-poligen Anschluss für die Kommunikation mit Mikrocontrollern und Geräten.

Der Controller ist über die USB-Schnittstelle mit dem PC und über die GPIO-Kontaktbasis mit dem DE10-Nano verbunden.





Der Controller selbst von Waveshare (im Projekt verwendet)



Durch die Verwendung einer UART-Schnittstelle über USB zum Übertragen von Daten von einem PC entfällt praktisch die Notwendigkeit, sich mit dem komplexen und mehrschichtigen USB-Protokollgerät zu befassen. Von nun an ist die Interaktion über die USB-Schnittstelle nicht mehr unser Anliegen, da diese Aufgabe den im System vorinstallierten oder vom Benutzer unabhängig installierten Treibern zugewiesen wird.



Neben Strom- und Erdungsleitungen sowie Datenübertragungs- und -empfangsleitungen befinden sich auf der Platine Pins, die als RTS und CTS signiert sind. Diese Kontakte werden für die sogenannte Flusskontrolle verwendet - ein Mechanismus, der die Bereitschaft signalisiert, je nach Zustand der Leitungen Daten vom Master- oder Slave-Gerät zu empfangen. Die Verwendung dieser Leitungen ist nicht erforderlich. Um den Mechanismus zu deaktivieren, muss in den Einstellungen des Computertreibers angegeben werden, dass die Flusssteuerung nicht verwendet wird (dies ist normalerweise die Standardkonfiguration).



Bei Verbindung mit einem Windows-PC wird der UART-Controller als virtuelle serielle Schnittstelle erkannt. Daher besteht die Entwicklung eines Schemas für die Interaktion mit einem PC darin, Software mit der Funktionalität der Interaktion mit einem seriellen virtuellen Port zu erstellen und ein Projekt für ein FPGA zu entwickeln, das das Empfangen / Senden von Daten über die UART-Schnittstelle implementiert.



Der externe UART-Controller ist zwar ein absolutes Analogon des Controllers, der bereits auf dem DE10-Nano installiert ist, aber sein einziger Vorteil ist die Möglichkeit, eine direkte Verbindung zu den freien Pins des FPGA herzustellen. Die Kosten für ein solches Gerät liegen zwischen 5 und 10 US-Dollar.



Software-Entwicklung



allgemeine Informationen



Wie bereits erwähnt, reduziert sich die Softwareentwicklung für einen PC auf die Erstellung eines Programms, das den Informationsaustausch mit einer virtuellen seriellen Schnittstelle unterstützt. Bei der Analyse der verfügbaren Softwaretools für die Softwareentwicklung fiel die Wahl auf die Programmiersprache Java 8th Edition unter Verwendung der RTXT-Bibliothek.



Java ist eine stark typisierte objektorientierte Programmiersprache mit einer Reihe von Hauptmerkmalen. Insbesondere in der Programmiersprache Java geschriebene Programme werden in einen speziellen Bytecode übersetzt, der es ihnen ermöglicht, auf jeder Computerarchitektur ausgeführt zu werden, für die eine virtuelle Java-Maschine implementiert ist.



Die Java-Standardbibliotheken können nicht mit der virtuellen seriellen Schnittstelle interagieren. Dafür wurde die RTXT-Bibliothek verwendet. RTXT wird unter einer freien Softwarelizenz vertrieben. Die Bibliothek verwendet die Systemimplementierung der Interaktion mit Schnittstellen und bietet Klassen zum Parsen, Verbinden, Lesen und Schreiben über die serielle Schnittstelle. Mehr zu dieser Bibliothek finden Sie hier .



Die alte, aber zuverlässige integrierte Swing-Bibliothek wird als Werkzeug für die Entwicklung der Benutzeroberfläche verwendet. Aufgrund der Möglichkeit, Themen zu ändern, sieht eine einfache Benutzeroberfläche in Swing möglicherweise nicht mehr oder weniger modern hässlich aus .



Das Programm selbst ist spartanisch einfach und nutzt hauptsächlich die dokumentierten Funktionen der RTXT-Bibliothek.



Die Hauptfunktionalität des Programms



So werden die verfügbaren Ports ermittelt:



    public String[] getPorts() {
        ports = CommPortIdentifier.getPortIdentifiers();
        while (ports.hasMoreElements()) {
            CommPortIdentifier curPort = (CommPortIdentifier) ports.nextElement();

            if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                portMap.put(curPort.getName(), curPort);
            }
        }
        return portMap.keySet().toArray(new String[0]);
    }


Verbindung zum ausgewählten Port herstellen:



    public void connect() {
        String selectedPort = (String)gui.ports.getSelectedItem();
        selectedPortIdentifier = portMap.get(selectedPort);
        CommPort commPort;
        try{
            commPort = selectedPortIdentifier.open("UART controller", TIMEOUT);
            serialPort = (SerialPort)commPort;
            serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            gui.writeLog(selectedPort + " opened successfully.");
        }catch (PortInUseException e){
            gui.writeLogWithWarning(selectedPort + " is in use. (" + e.toString() + ")");
        }catch (Exception e){
            gui.writeLogWithWarning("Failed to open " + selectedPort + " (" + e.toString() + ")");
        }
    }


Datenübertragungsprozess:



    public boolean writeData(byte[] bytes){
        boolean successfull = false;
        try {
            gui.writeLog("WRITING: " + HexBinUtil.stringFromByteArray(bytes));
            output.write(bytes);
            output.flush();
            successfull = true;
        }
        catch (Exception e) {
            gui.writeLogWithWarning("Failed to write data. (" + e.toString() + ")");
        }
        return successfull;
    }


Daten empfangen:



    public void serialEvent(SerialPortEvent serialPortEvent) {
        if (serialPortEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {
                byte singleData = (byte)input.read();
                gui.writeLog("READING: " + HexBinUtil.stringFromByteArray(singleData));
            }
            catch (Exception e) {
                gui.writeLogWithWarning("Failed to read data. (" + e.toString() + ")");
            }
        }
    }


Wie bereits erwähnt, wird der DAC / ADC durch Senden eines Befehls zum Schreiben eines gültigen 8-Bit-Werts an eine bestimmte in der Dokumentation beschriebene Registeradresse gesteuert. Um den aktuellen Status des Registers zu ermitteln, müssen Sie den Lesebefehl senden und die Adresse des angeforderten Registers angeben. Vollständige Beschreibung wie immer in der Dokumentation .



UART-Datenübertragung



Während des Studiums des AD9993-EBZ wurde festgestellt, dass im verfügbaren 12-Bit-Registeradressraum nur 8 Datenbits verwendet werden. Auch der übertragene Wert des Registerzustands wird durch 8 Bits beschrieben. Um die Art der Datenübertragung (Schreiben / Lesen) zu bestimmen, muss 1 Datenbit übertragen werden.



Da die derzeitige Begrenzung der maximalen Größe einer Nachricht auf der UART-Schnittstelle 8 Datenbits beträgt, wurde beschlossen, 3 aufeinanderfolgende 8-Bit-Nachrichten während des Schreibvorgangs und 2 Nachrichten während des Lesevorgangs zu übertragen.



Das erste Paket enthält die Art der Datenübertragung, die für die gesamte Paketgröße dupliziert wird. Daher kann es nur zwei mögliche Werte geben: 00000000 zum Lesen bzw. 11111111 zum Schreiben. Die Verwendung eines ganzzahligen Bursts für die Übertragung eines Datenbits wurde durchgeführt, um die weitere Verarbeitung der empfangenen Signale zu vereinfachen.

Als nächstes werden die Adresse des angeforderten Registers und der übertragene Wert des Registerzustands während des Aufzeichnungsprozesses übertragen.





Oszillogramm des entwickelten UART-Pakets



Benutzeroberfläche







Die Hauptelemente der Software-Benutzeroberfläche sind Schaltflächen zum Verbinden / Trennen von verfügbaren seriellen Schnittstellen (Elemente 3,4), Felder zur Eingabe der Adress- und Registerwerte (Elemente 7,8), ein Protokollfenster (Element 6). Die Software ist für die Interaktion mit ihr in zwei Zuständen ausgelegt: "Mit dem Port verbunden" und "Vom Port getrennt". Zustände bestimmen die Aktivität einiger Elemente auf der Programmschnittstelle und beschränken auch die Ausführung bestimmter Methoden, um die Wahrscheinlichkeit von Fehlern und falscher Softwareverwendung zu verringern. Wenn aktiviert, befindet sich das Programm im Status "Vom Port getrennt". Um die Arbeit mit dem Programm zu erleichtern (was eines der Hauptziele des Projekts war), wurde die Funktionalität zum Verbinden von Dateien mit bereits gespeicherten Befehlen im JSON-Format hinzugefügt (Element 10).



Befehlsladevorgang:





Dateiauswahl Befehlsschnittstelle





Mit dieser



Funktion können Sie die geladenen Befehle in Abschnitte sortieren (Element 12), den Prozess der Arbeit mit verbundenen Befehlen anpassen (ob Sie einen Befehl sofort an die serielle Schnittstelle senden, wenn Sie ihn drücken, oder die Adress- und Wertefelder gemäß dem ausgewählten Befehl ausfüllen). ...



Entwicklung eines Projekts für FPGA



allgemeine Informationen



Bevor Sie mit der Entwicklung eines Projekts für ein FPGA beginnen, müssen Sie sich für die Aufgabe entscheiden, die er lösen muss.



Es klingt wie folgen aus : das Projekt für das FPGA muss folgende Datenumwandlung unterstützen:





Datenkonvertierungsschema



Der DE10-Nano - Eingang empfängt Signale von der TX - Leitung der UART - Schnittstelle (oberes Signal). Als nächstes muss das FPGA die empfangenen Daten aus drei Nachrichten mit jeweils 8 Bit korrekt ermitteln und in das der Dokumentation entsprechende SPI-Nachrichtenformat konvertieren (in 4 Zeilen dargestellt).



Die zur Implementierung dieser Konvertierung erforderlichen Hauptmodule sind ein UART-Controller-Modul und ein SPI-Controller-Modul. Ihnen wird der Rest des Kapitels zugewiesen.



Bei der Entwicklung von Projekten für FPGAs wurde die 17. Version der IDE Qartus Prime Lite Edition verwendet.

Wenn Sie keine Erfahrung mit Quartus haben oder FPGAs überhaupt nicht programmiert haben, wird empfohlen, mit einem klaren (meiner Meinung nach) Beispiel für das erste Projekt auf Quartus zu beginnen.



Ich möchte darauf hinweisen, dass alle unten beschriebenen Auszüge aus dem Verilog-Code eine Zusammenstellung von Lösungen aus dem Internet sind, die keine Originalität vorgeben. Auch hier ist das Hauptziel dieses Projekts die Lösung eines bestimmten Problems.



UART-Controller



Beschreibung



Der UART-Controller besteht aus drei Modulen:



  • Impulsgeber;
  • Aufnahmemodul;
  • Lesemodul.


Es wird empfohlen, diesen Artikel zu lesen , aus dem die meisten Informationen stammen. Von nun an werde ich mich nur noch auf die wichtigsten (meiner Meinung nach) Implementierungsdetails konzentrieren.



Impulsgeber



Da die UART-Schnittstelle asynchron ist, muss der Empfänger sein eigenes Referenzsignal erzeugen, um das übertragene Signal korrekt zu empfangen, wodurch er den Beginn eines neuen Informationsbits korrekt bestimmen kann.



Es gibt einen allgemein akzeptierten Bereich von Standard-UART-Baudraten: 300; 600; 1200; 2400; 4800; 9600; 19200; 38400; 57600; 115200; 230400; 460800; 921600 Baud In unserem Fall erfolgt die Datenübertragung mit 9600 Baud. Als nächstes brauchen wir einen Generator mit einer Frequenz, die das 16-fache der Symbolrate beträgt. Dies ist notwendig, um den Pegel des übertragenen Signals korrekt zu erfassen.



Zur Erzeugung von Impulsen wird ein 50-MHz-Generator auf dem Chip verwendet. Um die gewünschte Frequenz zu erhalten, muss jeder 325. Impuls des Generators berücksichtigt werden.

So wird es in Verilog aussehen:



input           Clk;                   //   50
input           Rst_n;               //    
input [15:0]    BaudRate;      //   ,  325
output          Tick;                //  
reg [15:0]      baudRateReg; // 

always @(posedge Clk or negedge Rst_n)
    if (!Rst_n) baudRateReg <= 16'b1;
    else if (Tick) baudRateReg <= 16'b1;
         else baudRateReg <= baudRateReg + 1'b1;
assign Tick = (baudRateReg == BaudRate);
endmodule


Lesemodul



Der Leser wandelt das Eingangssignal von der Empfangsleitung in ein 8-Bit-Ausgangsdatenarray um.



Direktes Lesen und Übertragen der gelesenen Daten an die Ausgabe:



input Clk, Rx,Tick;  //   50,  Rx,   
input [3:0]NBits;                  //     ,  8
output RxDone;	         //     
output [7:0]RxData;                         //  

reg  read_enable = 1'b0;                   //   
reg  RxDone = 1'b0;                         //   
reg [3:0] counter = 4'b0000;            //   
reg  start_bit = 1'b1;	                      //     
reg [4:0]Bit = 5'b00000;                  //    
reg [7:0] RxData;                            //    
reg [7:0] Read_data= 8'b00000000; //    


always @ (posedge Tick)  //        
	begin
	if (read_enable)
	begin
	RxDone <= 1'b0;			//   
	counter <= counter+1'b1;		// 
	

	if ((counter == 4'b1000) & (start_bit))	//   
	begin
	start_bit <= 1'b0;
	counter <= 4'b0000;
	end

	if ((counter == 4'b1111) & (!start_bit) & (Bit < NBits)) //  
	begin
	Bit <= Bit+1'b1;
	Read_data <= {Rx,Read_data[7:1]};
	counter <= 4'b0000;
	end
	
	if ((counter == 4'b1111) & (Bit == NBits)  & (Rx))  //  
	begin
	Bit <= 4'b0000;
	RxDone <= 1'b1;          //      
	counter <= 4'b0000;          //  
	start_bit <= 1'b1;		//   
	end
	end
	
end


always @ (posedge Clk)
begin

if (NBits == 4'b1000)            //  8  ,    
begin
RxData[7:0] <= Read_data[7:0];	
end

end


Übertragungsmodul





Das Übertragungsmodul wandelt das 8-Bit-Eingangssignal in ein serielles UART-Datenpaket um.



Direkte Datenübertragung:



input Clk, Rst_n, TxEn;  // 50,  ,   
input Tick;                    //  
input [3:0]NBits;          //   
input [7:0]TxData;	

output Tx;
output TxDone;

reg  Tx;	
reg  TxDone = 1'b0;	
reg write_enable = 1'b0;
reg start_bit = 1'b1;	
reg stop_bit = 1'b0;	
reg [4:0] Bit = 5'b00000;	
reg [3:0] counter = 4'b0000;
reg [7:0] in_data=8'b00000000;

always @ (posedge Tick)  //        
begin

	if (!write_enable)	
	begin
	TxDone = 1'b0;
	start_bit <=1'b1;
	stop_bit <= 1'b0;
	end

	if (write_enable)
	begin
	counter <= counter+1'b1;	// 
	
	if(start_bit & !stop_bit)//        
	begin
	Tx <=1'b0;					
	in_data <= TxData;	

	if ((counter == 4'b1111) & (start_bit) )    //   
	begin		
	start_bit <= 1'b0;
	in_data <= {1'b0,in_data[7:1]};
	Tx <= in_data[0];
	end

	if ((counter == 4'b1111) & (!start_bit) &  (Bit < NBits-1))	//  
	begin		
	in_data <= {1'b0,in_data[7:1]};
	Bit<=Bit+1'b1;
	Tx <= in_data[0];
	start_bit <= 1'b0;
	counter <= 4'b0000;
	end	

	if ((counter == 4'b1111) & (Bit == NBits-1) & (!stop_bit))	//  
	begin
	Tx <= 1'b1;	
	counter <= 4'b0000;	
	stop_bit<=1'b1;
	end

	if ((counter == 4'b1111) & (Bit == NBits-1) & (stop_bit) )	// 
	begin
	Bit <= 4'b0000;
	TxDone <= 1'b1;
	counter <= 4'b0000;
	//start_bit <=1'b1;
	end
	
	end
		
end


SPI-Controller



Wichtiger Exkurs



Da der auf Basis eines FPGA implementierte SPI-Controller eine komplexere logische Struktur aufweist als der UART-Controller, ist die weitere Erläuterung der Betriebslogik am Schaltungsmodell des Controllers einfacher durchzuführen.



Allgemeines Schema der Steuerung







Das entwickelte Modell kann in 3 Hauptmodule unterteilt werden:



  • sequentielles Schreibmodul;
  • Bitzählermodul;
  • Fehleranalysemodul.


Die Aufteilung in Module ist eher willkürlich, da die Schaltung eine hohe Konnektivität zwischen den verwendeten Elementen aufweist. Die Unterteilung basiert auf den Aufgaben einzelner Elementgruppen, die im allgemeinen Diagramm dargestellt sind.



Die Taktung der Schaltung erfolgt durch ein 12,5-MHz-Signal, das über die Leitung CLK_125 geliefert wird.



Der Beginn der Arbeit der Steuerung an der Bildung einer Steuermeldung erfolgt über das Signal "START". Durch dieses Signal werden alle Module der Schaltung in ihren Ausgangszustand versetzt und der Beginn des Zyklus der Erzeugung der erforderlichen Signale auf den Ausgangsleitungen CLK, SS, MOSI der SPI-Schnittstelle wird initialisiert



Sequentielles Schreibmodul







Das serielle Schreibmodul führt die Hauptaufgabe des SPI-Controllers aus, nämlich die Ausgabe paralleler Bitdaten an die serielle MOSI-Leitung. Dies ist auf das Element RG_24_PI_SO zurückzuführen, das nach dem Prinzip eines Schieberegisters arbeitet, das auf D-Flip-Flops basiert.



Das Element RG_24_PI_SO verfügt über 24 Dateneingänge, die der AD9993-EBZ-Dokumentation zum SPI-Sendeformat entsprechen. Sie beinhalten:



  • Befehlsdaten (DATA_0 - DATA_7);
  • Adressdaten registrieren (ADR_0 - ADR_12);
  • Schreib- / Lesemodus-Bit W / R.


Die dargestellten Signale werden am Eingang LoadP_ShiftN parallel mit einem Logikpegel "1" geschrieben. Ferner reproduziert das Element auf dem Logikpegel "0" am Eingang LoadP_ShiftN bei jedem Taktzyklus am Eingang CLK abwechselnd die aufgezeichneten Daten auf der seriellen Leitung des MOSI-Ausgangs.



Bitzählermodul







Das Bitzählermodul wird benötigt, um die Dauer des Datenschreibfreigabesignals auf der SS-Leitung der SPI-Schnittstelle zu bestimmen. Da gemäß der AD9993-EBZ-Dokumentation die Dauer des Freigabesignals gleich der Gesamtdauer der übertragenen Daten sein muss, müssen ab Beginn der Datenübertragung 24 Synchronisationsimpulse gezählt werden, um die erforderliche Dauer des Freigabesignals zu bestimmen. Die Zählfunktion wird vom ST_32-Element ausgeführt, das beim Erfassen des 24. Taktsignals ein Signal wiedergibt, das zum Zurücksetzen des Zählers sowie zum Beenden des übertragenen Freigabesignals verwendet wird.



Zusätzlich zur Hauptfunktionalität ist das Bitzählermodul auch für die Initialisierung des Fehleranalyseprozesses verantwortlich, dessen anfängliche Aktion darin besteht, den Befehl zum Lesen des Werts an die Adresse des zuletzt aufgezeichneten Registers zu senden. Da der Fehleranalyseprozess nach einem Zeitintervall gestartet werden muss, das der Dauer von 23 Synchronisationsimpulsen ab dem Zeitpunkt der Übertragung des letzten übertragenen Datenbits entspricht (experimentell eingerichtet), wechselt der Bitzähler nach dem Rücksetzsignal in den Zählmodus für 23 Synchronisationsimpulse, wodurch der Betrieb des Fehleranalyseprozesses sichergestellt wird.



Fehleranalysemodul







Wie in der Erläuterung des vorherigen Moduls erwähnt, wurde zur Bereitstellung der Funktionalität der Fehleranalyse ein Verfahren entwickelt, das auf dem Lesen des Werts des auf dem IC gespeicherten Befehls an der im Datenaufzeichnungsprozess verwendeten Registeradresse basiert. Der Lesevorgang ist erforderlich, um den geschriebenen Wert mit den gelesenen Daten zu vergleichen, um Inkonsistenzen zu identifizieren und damit den aufgetretenen Fehler zu bestimmen. Das Fehleranalysemodul basiert auf dem Element RG_8_SI_PO, das nach dem Prinzip eines Schieberegisters arbeitet. Das Element wandelt die über die serielle MISO-Schnittstelle empfangenen Signale in einen parallelen 8-Bit-Ausgang um. Dann werden die Daten mit dem Wert des Befehls verglichen, der während des Datenaufzeichnungsprozesses verwendet wird. Die Vergleichsfunktionalität wird vom CMP_8-Element basierend auf der Exklusiv- oder Logik ausgeführt. Wenn eine Diskrepanz gefunden wird,Das Modul sendet ein Signal an den LED-Ausgang, der sich bis zum nächsten Datenaufzeichnungsprozess im Zustand einer logischen Einheit befindet. Es wird davon ausgegangen, dass der LED-Ausgang mit einer der LEDs verbunden ist, von denen eine Gruppe auf der DE10 Nano-Entwicklungsplatine vorhanden ist, die visuell einen aufgetretenen Fehler signalisiert.



Fazit



Als Ergebnis der Lösung dieses Problems wurde ein Interaktionsschema zwischen einem PC und einem DAC / ADC-Gerät mit einer Reihe von Hauptvorteilen entworfen und physikalisch implementiert. Während der Implementierung wurde das Problem mit der Verbindung von FPGA und PC gelöst. Die Lösung hierfür war die Verwendung eines externen UART-Moduls. Die Software für den PC wurde in der Java-Sprache geschrieben. Die Software verfügt über eine Schnittstelle mit grundlegenden Funktionen zum Senden und Empfangen von Daten im entwickelten UART-Sendeformat. Außerdem kann sie gespeicherte Befehle laden. FPGA-basierte UART- und SPI-Controller wurden entwickelt.



Die im Rahmen dieses Projekts berücksichtigten Probleme ermöglichen:



  • Bewertung der Interaktionsmöglichkeiten von integrierten Schaltkreisen mit externen Geräten;
  • Bewertung der Verwendung von FPGAs als Matching-Gerät, eines Puffers für den Datenaustausch;
  • Erforschen Sie einen der effektivsten Ansätze zur Entwicklung von Software für den praktischen Gebrauch.


PS Ich freue mich über Ergänzungen, Bemerkungen und Hinweise auf Fehler.



All Articles