Tienes dos requisitos aquí:
- Debe asegurarse de muestrear esos datos en el momento correcto de acuerdo con las necesidades del bus.
- Debe sincronizar estos datos en el dominio del reloj de su sistema.
Hay un par de maneras de satisfacer estas necesidades.
Primero, si el reloj del bus es lo suficientemente lento por debajo del reloj de tu sistema, entonces puedes sincronizar el reloj del bus con el dominio de tu reloj con un doble flop. Luego use un detector de bordes simple para determinar cuándo es el borde ascendente. Esto se utiliza para muestrear con seguridad la línea de datos del bus. Tenga en cuenta que esto logra # 2 automáticamente. Además, como se señaló aquí , esta es la forma preferida de hacer esto en un FPGA.
Este método tiene el inconveniente de que los datos se muestrean entre dos y tres relojes del sistema más tarde que el borde del reloj del bus "en el pin". Si esto es demasiado largo (debido a que el reloj de tu sistema no es lo suficientemente rápido en comparación), tienes que ir por un camino alternativo.
En este método, muestrea antes de sincronizar con el dominio del reloj del sistema. El motivo es asegurarse de que esté tomando muestras en el momento adecuado de acuerdo con el bus.
always @(posedge bclk) begin // positive edge of bus clock
sampled_data <= data;
end
En este punto, ha muestreado datos que son una señal en el dominio bclk. Debe sincronizarlo con el dominio del reloj de su sistema. Para hacer esto, debes usar handshaking o FIFO.
Una forma que funciona es hacer el registro de desplazamiento en el dominio del reloj de bus para obtener datos paralelos. Luego, páselo a través de un FIFO de doble reloj al otro dominio. Los FPGA tienen primitivas solo para este uso.
// Latch the data in the bclk domain
always @(posedge bclk) begin
fifo_d <= {fifo_d[30:0], data};
data_count <= data_count + 1;
if (data_count == 31)
fifo_wr <= 1'b1; // This will latch fifo_d to the dual clock fifo input
else
fifo_wr <= 1'b0;
end
// Read the data out of the FIFO in the system clock domain.
always @(posedge clk) begin
if (fifo_ready)
synchronized_data <= fifo_q; // Now the data is in your domain.
end
Otras notas:
Al igual que con cualquier E / S en el borde del FPGA, así como entre dominios de reloj, deberá definir correctamente las restricciones de tiempo. Describir los detalles es un poco demasiado general para este foro, pero como lo recomiendan los comentarios de Greg, este documento es una buena fuente para comprender las necesidades del cruce del dominio del reloj. Los proveedores de FPGA tienden a tener también anotaciones decentes para el retardo de entrada y las definiciones de retardo de salida.