¡Comunicación en serie basada en dos FPGA Cyclone II!
En primer lugar, ambas partes deben acordar la frecuencia del reloj para la comunicación, pero los relojes utilizados por ambas partes deben tener errores y se desconoce la hora de inicio de cada bit. Estos dos puntos son la razón por la que a veces recibes el correcto y otras el incorrecto. Por lo tanto, se requiere un muestreo de reloj de alta potencia, generalmente 8 o 16 veces.
Si es una implementación simple, tome 8 veces como ejemplo. Si otra placa (o PC) envía datos y la frecuencia de reloj para enviar un bit es 115,2 KHz, primero debería generar un reloj interno de 115,2 x8 = 921,6 khz en su propia placa. Utilice este reloj para muestrear los datos en serie recibidos. En teoría, se pueden obtener de 7 a 8 puntos de muestreo para cada bit.
A continuación, el primer paso es encontrar la posición inicial. Si es 0 después de tres (o cuatro) veces, significa que se ha encontrado el bit inicial y es probable que el punto de muestreo actual esté en el medio de este bit. Entonces, de ahora en adelante, cada 8 relojes, puedes elegir la siguiente posición intermedia. Luego, los ocho bits recopilados se combinan en un byte. De esta forma se pueden obtener datos estables y correctos. Finalmente, después de 8 relojes, tómelo nuevamente para asegurarse de que el siguiente bit esté alto, lo que indica el final. Si no, algo anda mal. No importa. Simplemente busque la posición inicial nuevamente.
A continuación, escribí un ejemplo para su referencia.
Biblioteca IEEE
Usar IEEE.STD_logic_1164.all;
Usar IEEE.STD_logic_arith.all;
Usar IEEE.STD_logic_unsigned.all ;
La entidad UART_RX es
puerto (
reset_n: en std_logic;
clk: en std_logic;
rx: en std_logic;
dout:out STD _ logic _ vector (7 hasta 0
dav: salida lógica estándar
);
fin UART_RX
La arquitectura de UART_RX, UART_RX_arch, es
El tipo UART_RX_STATE_TYPE es (WAIT_START, DATA, STOP);
Señal curState: UART _ RX _ STATE _ TYPE;
Bit de señal: std_logic_vector (7 cayó a 0);
Señal smpCnt: rango de enteros 0 a 7
señal bitCnt: rango de enteros de 0 a 15
Inicio
Procesamiento (reset_n, clk)
Inicio
Si reset_n = '0', entonces
curState & lt=wait_start;
bits & lt=(other= & gt' 0');
smpCnt & lt = 0;
bitCnt & lt= 0;
elsif flanco ascendente (clk) entonces
El estado del caso es
Cuando WAIT_START = & gt
Si rx = '0 ', entonces
Si smpCnt = 3, entonces
curState & lt=data;
smpCnt & lt= 0;
Otro
curState & lt=wait_start;
smpCnt & lt= smpCnt+1;
Fin if;
Otro
curState & lt=wait_start;
smpCnt & lt= 0;
Finalizar si;
bits & lt=(other= & gt'0');
bitCnt & lt= 0
Cuando datos = & gt
Si smpCnt = 7, entonces
Si bitCnt = 7, entonces
curState & lt=Stop ;
Otro
curState & lt= data;
End if;
smpCnt & lt= 0;
bits & lt= rx & amp bits (7 hasta 1);
bitCnt & lt= bit CNT+1;
Otros
curState & lt=data;
smpCnt & lt= smpCnt+1;
bits & lt=bits;
bitCnt & lt= bitCnt
Finalizar si;
Cuando STOP = >;
Si smpCnt = 7, entonces
curState & lt=wait_start;
smpCnt & lt= 0;
Otros
<p>curState & lt=stop;
smpCnt & lt= smpCnt+1;
Finalizar si;
bits & lt=bits;
bitCnt & lt= 0;
cuando otros= & gt
curState & lt=wait_start;
bits & lt=(other= & gt '0');
smpCnt & lt= 0;
bitCnt & lt= 0;
Fin de caso;
Fin si ;
Finalizar proceso;
dout & lt=bit;
Proceso (reset_n, clk)
Iniciar
Si reset_n = '0 ', entonces
dav & lt= '0';
elsif flanco ascendente (clk) entonces
si curState = STOP y smpCnt = 7 y rx = '1', entonces
dav & lt= '1';
Otros
dav & lt= '0';
Finalizar si;
Finalizar si;
Finalizar proceso;
Finalizar UART_RX_arch
Aquí no me refiero al reloj. Puede generar un reloj 8x y enviarlo a este módulo según su situación. Al mismo tiempo, si desea que el dav generado sea tan amplio como el ciclo de reloj de su sistema, también debe realizar una detección de retraso.