Organizamos la interacción entre PC y DAC / ADC usando FPGA

En el mundo digital moderno, la necesidad de DAC / ADC ( convertidores de digital a analógico / convertidores de analógico a digital ) no está en duda: se utilizan para procesar señales de varios sensores, en equipos de sonido, sintonizadores de TV, tarjetas de entrada de video, cámaras de video, etc.



Sin embargo, usar o depurar un DAC / ADC puede ser difícil debido a las limitaciones establecidas por el fabricante del hardware, por ejemplo, en el software utilizado o en cómo se puede controlar el dispositivo. Esto sugiere diseñar su propio modelo de interacción.



En este artículo consideraremos la posibilidad de organizar la interacción entre una PC y un DAC / ADC utilizando FPGA.









Prefacio



El objetivo principal de este artículo es describir la solución a un problema específico, así como la familiaridad con las interfaces de interacción de circuitos integrados (CI). El propósito principal del DAC / ADC no se considera aquí.



Este artículo requiere algunos conocimientos de programación y circuitos orientados a objetos, por lo que si no está familiarizado con estos conceptos, se recomienda comenzar con ellos.



Espero que la experiencia de una persona que se encuentra por primera vez con el problema de la comunicación de los dispositivos electrónicos le sea útil.



¡Buena suerte y nuevos logros para todos!



Un pequeño programa educativo sobre interfaces



Descargo de responsabilidad



Si está familiarizado con la estructura de las interfaces principales utilizadas para la comunicación IC, puede omitir este punto de manera segura.



programa educativo



, .



, (, .) . , .



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



, .





( ), :



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


«-» — , . , — .







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







( «») . , , , - . .









:



  • ;
  • ;
  • -.


, . . . , .







, . , , .







(-/)





:



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


. .







, .

: , «» .







. .









:



  • ;
  • .


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







, , .







?



() 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





¿Qué es este DAC?





No parece esto.



Para empezar, definamos el DAC / ADC utilizado: La



placa de depuración AD9993-EBZ de Analog Devices es un dispositivo que combina cuatro ADC de 14 bits y dos DAC de 14 bits.



Los modos de funcionamiento de este IC se controlan cambiando el estado de sus registros internos. El AD9993 utiliza 66 registros con un tamaño de palabra almacenada (procesada) de 8 bits, cuyas direcciones se describen mediante valores hexadecimales de tres dígitos (12 bits de datos). Se admiten dos tipos de comandos: comando de lectura y comando de escritura. En otras palabras, para corregir el funcionamiento del IC, es necesario enviar un comando para escribir algún valor válido de 8 bits en una dirección de registro específica. El acceso a los registros de este IC se realiza a través de la interfaz de periféricos en serie (SPI), cuya conexión en la placa de depuración se realiza mediante el conector FIFO_0 de 40 pines o mediante un grupo de contactos adicionalmente instalado.





Como este (FIFO_0 - conector gris superior)



Requisitos básicos para los parámetros de límite de SPI:



  • Frecuencia máxima de transmisión de datos: 25 MHz;
  • La duración de los niveles superior e inferior en la línea de generación de la señal de sincronización es de 10 ns;
  • Tiempo de ajuste de nivel en líneas de transmisión de datos y líneas de resolución - 2 ns;
  • Nivel de tiempo de retención en las líneas de transmisión de datos y en la línea de resolución - 2 ns;
  • El tiempo de validez garantizado de un bit de datos en la línea de transmisión del dispositivo esclavo es de 2 ns.


Se puede encontrar una descripción completa de las características del dispositivo en su documentación .



¿Qué dice el fabricante?



Esquema de control recomendado



Según la documentación de AD9993-EBZ, la forma recomendada de controlar el IC es utilizar la placa de depuración HSC-ADC-EVALC de Analog Devices conectada al IC a través de un puerto de 40 pines y a una PC a través de la interfaz USB.



SPIController se utiliza como software de control. Dispositivos analógicos





recomendados





Circuito HSC-ADC-EVALC (basado en Xilinx Virtex-4 FPGA)



contras:



  • Precio alto. La placa de depuración HSC-ADC-EVALC en el sitio web oficial de Analog Devices se ofrece por $ 698.28.
  • Interfaz de usuario incómoda. El software SPIController, además de la función principal de escribir y leer registros, no proporciona la capacidad de guardar o programar el inicio de los comandos.
  • . SPI SPIController, . Analog Devices, SPI.




SPIController



:



  • .


HSC-ADC-EVALC



Cabe señalar que el uso de la placa HSC-ADC-EVALC de Analog Devices como dispositivo de control DAC / ADC no es su propósito principal.



El HSC-ADC-EVALC se utiliza principalmente como una tarjeta de memoria intermedia para el ADC, sin embargo, también tiene la funcionalidad de configurar tarjetas de depuración mediante SPI si las tarjetas conectadas lo admiten.



Modelo de interacción propio



Razón para usar un dispositivo intermedio



Es obvio que la interacción del DAC / ADC y el PC no se puede organizar directamente, ya que el SPI, con el que se programa el AD9993-EBZ, no es una interfaz típica de un PC moderno.



Para resolver este problema, fue necesario utilizar un dispositivo intermediario que convertiría los datos de la interfaz USB enviados desde la computadora al formato de interfaz SPI compatible con el IC.



En el proceso de elaboración de las opciones, la elección recayó en el uso de la placa de desarrollo Terasic DE10-Nano, basada en la FPGA Cyclone V.





Modelo de interacción propio



¿Por qué FPGA es tan genial?



Las principales ventajas de utilizar FPGA:



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




...



Durante el diseño del modelo de interacción, se decidió implementar la interfaz SPI basada en GPIO (pines de propósito general), cuya base de contacto está disponible en el DE10-Nano. La implementación del controlador SPI basado en FPGA no debería haber creado ningún problema especial debido a la gran cantidad de materiales sobre un tema similar.



Sin embargo, la implementación de conectar la FPGA a la computadora a través de la interfaz USB causó dificultades.



DE10-Nano tiene los siguientes puertos USB:



  • USB mini-B alimentado por chip FT232R, realizando conexión UART a USB.
  • USB mini-B controlado por el chip SMSC USB3300, que implementa la capa física de la interfaz USB, así como también se utiliza para programar FPGA.


El uso de estos puertos se complica por el hecho de que el DE10-Nano se comunica con estos puertos a través del llamado HPS ( sistema de procesador duro ), una parte del chip Cylone V, que contiene un módulo de microprocesador, un procesador ARM Cortex, controladores de memoria flash y mucho más. La principal diferencia entre HPS y FPGA es que HPS son bloques de estructura invariable, optimizados para una función específica y no tienen sus herramientas de programación (y por lo tanto son duros).



Las partes HPS y FPGA del chip Cyclone V tienen sus propios pines. Estos pines no se comparten libremente entre el HPS y el FPGA. Los contactos del HPS se configuran mediante software que se ejecuta en el HPS. Los pines FPGA se programan utilizando una imagen de configuración FPGA a través del HPS o cualquier otra fuente externa compatible.



Para organizar la interacción de la lógica programable del chip Cyclone V con estos puertos, es necesario crear un gestor de arranque especial de Linux que se ejecute en el HPS, y también es necesario desarrollar un programa que sea capaz de transferir señales desde los controladores de los puertos USB disponibles a los contactos libres de la FPGA.



En la etapa actual de conocimiento, esta pregunta resultó abrumadora, por lo que se decidió buscar otro camino. Sin embargo, para las personas que se enfrentan a un problema similar y deciden resolverlo, puede ser útil leer un artículo sobre una posible solución.



¡Hay una salida!



Después de haber examinado a fondo Internet, se decidió utilizar un controlador UART externo.



El controlador UART externo es una placa pequeña basada en el chip FT232RL. La placa tiene conectores miniUSB-B para comunicación con una computadora y un conector de 6 pines para comunicación con microcontroladores y dispositivos.

El controlador se conecta a través de la interfaz USB a la PC y a través de la base de contacto GPIO al DE10-Nano.





El propio controlador de Waveshare (utilizado en el proyecto)



El uso de una interfaz UART a través de USB para transferir datos desde una PC prácticamente elimina la necesidad de lidiar con el dispositivo de protocolo USB complejo y de múltiples capas. A partir de ahora, la interacción a través de la interfaz USB ya no es de nuestra incumbencia, ya que esta tarea se asigna a los controladores preinstalados en el sistema o instalados de forma independiente por el usuario.



Además de las líneas eléctricas y de tierra, así como las líneas de transmisión y recepción de datos, hay pines en la placa, firmados como RTS y CTS. Estos contactos se utilizan para el llamado control de flujo, un mecanismo diseñado para señalar la disponibilidad para recibir datos del dispositivo maestro o esclavo, según el estado de las líneas. El uso de estas líneas no es necesario, por lo tanto, para deshabilitar el mecanismo, es necesario indicar en la configuración del controlador de la computadora que no se usa el control de flujo (esta suele ser la configuración predeterminada).



Cuando se conecta a una PC con Windows, el controlador UART se identifica como un puerto serie virtual. Por lo tanto, el desarrollo de un esquema para interactuar con una PC se reduce a crear un software con la funcionalidad de interactuar con un puerto virtual serie, así como a desarrollar un proyecto para una FPGA que implemente la recepción / transmisión de datos a través de la interfaz UART.



El controlador UART externo es de hecho un análogo absoluto del controlador que ya está en el DE10-Nano, pero su única ventaja es la capacidad de conectarse directamente a los pines libres de la FPGA. El costo de dicho dispositivo varía entre $ 5 y $ 10.



Desarrollo de software



Información general



Como ya se mencionó, el desarrollo de software para PC se reduce a la creación de un programa que admita el intercambio de información con un puerto serie virtual. Durante el análisis de las herramientas de software disponibles para el desarrollo de software, la elección recayó en el lenguaje de programación Java octava edición utilizando la biblioteca RTXT.



Java es un lenguaje de programación orientado a objetos fuertemente tipado con una serie de características clave. En particular, los programas escritos en el lenguaje de programación Java se traducen a un código de bytes especial, que les permite ejecutarse en cualquier arquitectura de computadora para la cual existe una implementación de una máquina virtual Java.



Las bibliotecas estándar de Java no tienen la capacidad de interactuar con el puerto serie virtual. Para esto se utilizó la biblioteca RTXT. RTXT se distribuye bajo una licencia de software libre. La biblioteca utiliza la implementación del sistema de interacción con interfaces y proporciona clases para analizar, conectar, leer y escribir operaciones utilizando el puerto serie. Puede encontrar más información sobre esta biblioteca aquí .



La antigua pero confiable biblioteca integrada Swing se utiliza como herramienta para desarrollar la interfaz de usuario. Debido a la capacidad de cambiar temas, una interfaz de usuario simple en Swing puede no verse más o menos fea y moderna.



El programa en sí es espartanamente simple y utiliza principalmente las capacidades documentadas de la biblioteca RTXT.



La principal funcionalidad del programa.



Así es como se determinan los puertos disponibles:



    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]);
    }


Conectando al puerto seleccionado:



    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() + ")");
        }
    }


Proceso de transferencia de datos:



    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;
    }


Recibiendo información:



    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() + ")");
            }
        }
    }


Como ya se mencionó, el DAC / ADC se controla transmitiendo el comando de escritura de algún valor válido de 8 bits a una dirección de registro específica descrita en la documentación. Para determinar el estado actual del registro, debe enviar el comando de lectura y especificar la dirección del registro solicitado. Descripción completa como siempre en la documentación .



Transmisión de datos UART



En el curso del estudio del AD9993-EBZ, se encontró que solo se utilizan 8 bits de datos en el espacio de direcciones de registro de 12 bits disponible. Además, el valor transmitido del estado del registro se describe mediante 8 bits. Para determinar el tipo de transferencia de datos (escritura / lectura), se requiere transferir 1 bit de datos.



Dado que la limitación actual sobre el tamaño máximo de un mensaje a través de la interfaz UART es de 8 bits de datos, se decidió transmitir 3 mensajes consecutivos de 8 bits durante el proceso de escritura y 2 mensajes durante el proceso de lectura.



El primer paquete contendrá el tipo de transmisión de datos, duplicado para todo el tamaño del paquete. Por lo tanto, solo puede haber dos valores posibles: 00000000 para lectura y 11111111 para escritura, respectivamente. El uso de una ráfaga de números enteros para la transmisión de un bit de datos se realizó para simplificar el procesamiento adicional de las señales recibidas.

A continuación, se transmiten la dirección del registro solicitado y el valor transmitido del estado del registro durante el proceso de grabación.





Oscilograma del paquete UART desarrollado



Interfaz de usuario







Los elementos principales de la interfaz de usuario del software son los botones para conectarse / desconectarse de los puertos serie disponibles (elementos 3, 4), campos para ingresar la dirección y registrar valores (elementos 7, 8), una ventana de registro (elemento 6). El software está diseñado para interactuar con él en dos estados: "conectado al puerto" y "desconectado del puerto". Los estados determinan la actividad de algunos elementos en la interfaz del programa y también restringen la capacidad de ejecutar ciertos métodos para reducir la probabilidad de errores y el uso incorrecto del software. Cuando está habilitado, el programa está en el estado "desconectado del puerto". Además, para facilitar el trabajo con el programa (que era uno de los principales objetivos del proyecto), se agregó la funcionalidad de conectar archivos con comandos ya guardados en formato JSON (elemento 10).



Proceso de carga de comandos:





Selección de archivos





Interfaz de comandos La



funcionalidad le permite clasificar los comandos cargados en secciones (elemento 12), personalizar el proceso de trabajo con comandos conectados (ya sea para enviar un comando al puerto serie inmediatamente cuando se presiona, o completar los campos de dirección y valor de acuerdo con el comando seleccionado) ...



Desarrollo de un proyecto para FPGA



Información general



Antes de comenzar a desarrollar un proyecto para una FPGA, debe decidir la tarea que debe resolver.



Suena algo así: el proyecto para la FPGA debe admitir la siguiente conversión de datos:





Diagrama de conversión de datos



El DE10-Nano recibe señales de la línea Tx de la interfaz UART (señal superior). A continuación, la FPGA necesita determinar correctamente los datos recibidos de tres mensajes de 8 bits cada uno y convertirlos al formato de mensaje SPI correspondiente a la documentación (presentado en 4 líneas).



Los módulos principales necesarios para implementar esta conversión son un módulo controlador UART y un módulo controlador SPI. A ellos se les asigna el resto del capítulo.



Al desarrollar proyectos para FPGA, se utilizó la versión 17 de IDE Qartus Prime Lite Edition.

Si no tiene experiencia en el uso de Quartus o no ha programado FPGA en absoluto, se recomienda comenzar con un ejemplo claro (en mi opinión) del primer proyecto en Quartus.



Me gustaría señalar que todos los extractos del código Verilog que se describen a continuación son una compilación de soluciones que se encuentran en Internet, que no pretenden ser originales. Nuevamente, el objetivo principal de este proyecto es resolver un problema específico.



Controlador UART



Descripción



El controlador UART consta de tres módulos:



  • generador de pulso;
  • módulo de grabación;
  • módulo de lectura.


Se recomienda mirar este artículo , del cual se tomó la mayor parte de la información. De ahora en adelante, me centraré solo en los detalles de implementación más importantes (en mi opinión).



Generador de pulso



Dado que la interfaz UART es asíncrona, el receptor necesita generar su propia señal de referencia para recibir correctamente la señal transmitida, lo que le permite determinar correctamente el comienzo de un nuevo bit de información.



Existe un rango generalmente aceptado de velocidades de transmisión UART estándar: 300; 600; 1200; 2400; 4800; 9600; 19200; 38400; 57600; 115200; 230400; 460800; 921600 baudios En nuestro caso, la transferencia de datos se produce a 9600 baudios. A continuación, necesitamos un generador con una frecuencia 16 veces la tasa de símbolos. Esto es necesario para detectar correctamente el nivel de la señal transmitida.



Para generar pulsos, se utiliza un generador de 50 MHz en el chip. Para obtener la frecuencia deseada, es necesario tener en cuenta cada 325 pulso del generador.

Así es como se verá en Verilog:



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


Módulo lector



El lector convierte la señal de entrada de la línea RX en una matriz de datos de salida de 8 bits.



Leer y transferir directamente los datos leídos a la salida:



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


Módulo de transmisión





El módulo de transmisión convierte la señal de entrada de 8 bits en un paquete de datos en serie UART.



Transferencia directa de datos:



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


Controlador SPI



Digresión importante



Dado que el controlador SPI, implementado sobre la base de un FPGA, es una estructura lógica más compleja que el controlador UART, la explicación adicional de la lógica de operación es más fácil de realizar en el modelo de circuito del controlador.



Esquema general del responsable del tratamiento







El modelo desarrollado se puede dividir en 3 módulos principales:



  • módulo de escritura secuencial;
  • módulo contador de bits;
  • módulo analizador de errores.


La división en módulos es bastante arbitraria, ya que el circuito tiene una alta conectividad entre los elementos utilizados. La división se basa en las tareas realizadas por grupos individuales de elementos, presentados en el diagrama general.



El reloj del circuito lo proporciona una señal de 12,5 MHz suministrada a través de la línea CLK_125.



El inicio del trabajo del controlador en la formación de un mensaje de control se realiza mediante la señal "INICIO". Mediante esta señal, todos los módulos del circuito se establecen en su estado inicial y se inicializa el comienzo del ciclo de generación de las señales requeridas en las líneas de salida CLK, SS, MOSI de la interfaz SPI



Módulo de escritura secuencial







El módulo de escritura en serie realizará la tarea principal del controlador SPI, es decir, la salida de datos de bits paralelos a la línea MOSI en serie. Esto se debe al elemento RG_24_PI_SO, que opera según el principio de un registro de desplazamiento basado en D-flip-flops.



El elemento RG_24_PI_SO tiene 24 entradas de datos correspondientes a la documentación AD9993-EBZ sobre el formato de envío SPI. Incluyen:



  • Datos de comando (DATA_0 - DATA_7);
  • Registrar datos de dirección (ADR_0 - ADR_12);
  • Bit de modo de escritura / lectura W / R.


Las señales presentadas se escriben en paralelo a un nivel lógico "1" en la entrada LoadP_ShiftN. Además, en el nivel lógico "0" en la entrada LoadP_ShiftN, en cada ciclo de reloj en la entrada CLK, el elemento reproduce alternativamente los datos registrados en la línea serial de la salida MOSI.



Módulo contador de bits







El módulo contador de bits es necesario para determinar la duración de la señal de habilitación de escritura de datos en la línea SS de la interfaz SPI. Dado que, de acuerdo con la documentación AD9993-EBZ, la duración de la señal de habilitación debe ser igual a la duración total de los datos transmitidos, es necesario contar 24 pulsos de sincronización desde el comienzo de la transmisión de datos para determinar la duración requerida de la señal de habilitación. La función de conteo la realiza el elemento ST_32, el cual, cuando se detecta la señal del reloj 24, reproduce una señal que se utiliza para reiniciar el contador, así como para finalizar la señal de habilitación transmitida.



Además de la funcionalidad principal, el módulo contador de bits también es responsable de inicializar el proceso de análisis de errores, cuya acción inicial es enviar el comando de valor leído a la dirección del último registro registrado. Dado que el proceso de análisis de errores debe iniciarse después de un intervalo de tiempo equivalente a la duración de 23 pulsos de sincronización desde el momento en que se transmitió el último bit de datos transmitido (establecido experimentalmente), el contador de bits después de la señal de reinicio cambia al modo de conteo de 23 pulsos de sincronización, lo que garantiza el funcionamiento del proceso de análisis de errores.



Módulo de análisis de errores







Como se mencionó en la explicación del módulo anterior, para brindar la funcionalidad del análisis de errores, se desarrolló un método basado en leer el valor del comando almacenado en el IC en la dirección de registro utilizada en el proceso de registro de datos. El proceso de lectura es necesario para comparar el valor escrito con los datos leídos para identificar inconsistencias y, por lo tanto, determinar el error que se ha producido. El módulo de análisis de errores se basa en el elemento RG_8_SI_PO, que opera según el principio de un registro de desplazamiento. El elemento convierte las señales recibidas a través del puerto serie MISO en una salida paralela de 8 bits. Luego, los datos se comparan con el valor del comando utilizado durante el proceso de registro de datos. La funcionalidad de comparación la realiza el elemento CMP_8 basándose en la lógica o exclusiva. Si se encuentra una discrepancia,el módulo transmite una señal a la salida LED, que estará en estado de unidad lógica hasta el próximo proceso de registro de datos. Se supone que la salida del LED se asociará con uno de los LED, un grupo de los cuales está presente en la placa de desarrollo DE10 Nano, que señalará visualmente un error que se ha producido.



Conclusión



Como resultado de la solución de este problema, se diseñó e implementó físicamente un esquema de interacción entre una PC y un dispositivo DAC / ADC con una serie de ventajas clave. En el proceso de implementación, se solucionó el problema con la conexión de FPGA y PC. La solución a esto fue utilizar un módulo UART externo. El software para PC se escribió en lenguaje Java. El software tiene una interfaz con capacidades básicas para transmitir y recibir datos en el formato de envío UART desarrollado, además, tiene la función de cargar comandos guardados. Se desarrollaron controladores UART y SPI basados ​​en FPGA.



Los temas considerados en el marco de este proyecto permiten:



  • evaluar las formas de interacción de los circuitos integrados con dispositivos externos;
  • evaluar formas de utilizar FPGA como un dispositivo de emparejamiento, un búfer para el intercambio de datos;
  • Explore uno de los enfoques más efectivos para desarrollar software para uso práctico.


PD: Estaré encantado de recibir adiciones, comentarios e indicaciones de errores.



All Articles