VHDL actualiza diferentes partes del vector grande (datos MIG) de los datos en serie

0

Estoy intentando escribir datos en una instancia del generador de interfaz de memoria Xilinx que recibo de un UART. Estoy usando VHDL en Vivado.

El UART presenta datos de 8 bits a la vez, con bastantes ciclos de reloj entre cada información nueva. La entrada de datos MIG es un vector de 512 bits.

signal s_app_wdf_data : STD_LOGIC_VECTOR(511 downto 0); -- Output to MIG
signal s_uart_data    : STD_LOGIC_VECTOR(7 downto 0); -- input from UART

Deseo rellenar el vector con datos recibidos del UART. Actualizaré cada parte del vector y luego, cuando reciba el último byte de UART, habilitaré las señales de escritura en el MIG.

Creé un contador para realizar un seguimiento de qué posición en el vector era la posición relevante para escribir los datos de UART, por lo que cada vez que hay datos nuevos en el UART, haga algo como esto:

s_app_wdf_data(v_position downto v_position - 7) <= s_uart_data;
v_position := v_position - 8;

Sin embargo, esto tomó aproximadamente una hora para realizar el diseño de la ruta, y dio errores de tiempo (holgura negativa).

Estaba pensando que para que eso funcione, las herramientas tendrían que sintetizar algo que esencialmente permita el acceso aleatorio a cualquier parte del vector, así que tal vez podría ayudar a aclarar las herramientas que solo ciertas partes del vector siempre se ha accedido, ya que la posición solo cambia en decrementos de 8. Escribí

if (v_position = 511) then
    s_app_wdf_data(511 downto 504) <= s_uart_data;
elsif (v_position = 503) then
    s_app_wdf_data(503 downto 496) <= s_uart_data;
elsif (v_position = 495) then
    s_app_wdf_data(495 downto 488) <= s_uart_data;
etc, etc

Fue laborioso teclearlo (un signo claro de que algo está mal), y al final tuvo errores de sincronización aún peores.

Luego traté de evitar el código que accedía a lugares arbitrarios en el vector, intenté usar desplazar y actualizar solo el byte más bajo.

s_app_wdf_data(511 downto 8) <= s_app_wdf_data(503 downto 0);
s_app_wdf_data(7 downto 0) <= s_uart_data;

Este tuvo la peor holgura negativa total del lote.

¿Cuál es el enfoque correcto aquí? ¿O qué técnicas debería estar investigando?

    
pregunta Tim Porter

3 respuestas

0

Aquí tengo un código que hace algo extremadamente similar a lo que estás intentando implementar:

enlace

Este código conecta una interfaz de flujo AXI (que podría estar conectada a un UART, una interfaz de Ethernet, etc.) a un bus de memoria de wishbone para emitir solicitudes de lectura / escritura en el bus.

Este código utiliza el método de selección de parte indexada de verilog para actualizar el registro de datos de esta manera:

data_next[AXIS_DATA_WORD_SIZE*count_reg +: AXIS_DATA_WORD_SIZE] = input_axis_tdata;
count_next = count_reg + 1;

No estoy muy familiarizado con VHDL, pero quizás puedas probar una pequeña modificación de una de las técnicas que ya probaste:

s_app_wdf_data(v_position*8 downto v_position*8 - 7) <= s_uart_data;
v_position := v_position - 1;

Lo que desea es que el sintetizador configure el registro de salida de modo que la palabra de datos de entrada se enrute a cada conjunto posible de 8 bits de salida, y luego genere un byte habilitado por desplazamiento. Si se asegura de que nunca pueda haber superposición alguna, entonces esto termina siendo muy eficiente. En el código que probaste originalmente, parece que tal vez el sintetizador no pudo determinar que no hubo superposiciones y, como resultado, produjo un resultado muy poco óptimo.

    
respondido por el alex.forencich
0

En general, piense en el procesamiento paralelo / concurrente. ¿Hay algo que le impida escribir cada "datos dimensionados en el ancho de su memoria" antes de recibir los 64 bytes? De lo contrario, escriba en la ubicación de la memoria cada vez que reciba cada "datos del tamaño adecuado" de la UART. De esa manera, solo tratará con un único segmento de los 512 bits en un momento dado. Probablemente, está utilizando su memoria como FIFO (?), Por lo que es un simple puntero de escritura y lectura que es su dirección de memoria (relativa o absoluta, de cualquier manera).

Si se detiene y piensa en ello, en términos de HW, ya está "almacenando" todos los 64 bytes antes de escribir la memoria de todos modos ... y, para estar seguro, el "almacenamiento" puede ser un registro o una memoria, como le plazca. ... entonces, creo que si dejas de intentar registrar 512 bits y luego escribes los cortes en la memoria, y en lugar de eso los guardas en la memoria "al vuelo", tu diseño se ajustará al tiempo y se ajustará más fácilmente a tu dispositivo.

    
respondido por el CapnJJ
0

Seré honesto. Me sorprende que lo que describas no funcione, ya que no es un patrón inusual.

Habiendo dicho eso, he aquí un pensamiento: dado que el UART será muy lento en comparación con el reloj de su sistema, ¿puede cambiar los datos de UART un bit a la vez al vector MIG?

for i in range 0 to 7 loop
  s_app_wdf_data(s_app_wdf_data'high downto 1) <= s_app_wdf_data(s_app_wdf_data'high-1 downto 0) & s_uart_data(s_uart_data'high);
  s_uart_data <= s_uart_data(s_uart_data'high-1 downto 0) & '0';
  wait until rising_edge(clk)
end loop;

O algo por el estilo :)

    
respondido por el Martin Thompson

Lea otras preguntas en las etiquetas