6 votos

Mi aplicación de verilog del receptor serial no actúa como se esperaba

Yo he programado mi propia implementación de una serie de receptor. Va a trabajar para la entrada de datos a una tasa de 115200 baudios.

Aquí está mi código:

module my_serial_receiver(
    input clk,
    input reset_n,
    input Rx,
    output reg [7:0] received_byte,
    output reg byte_ready
);

parameter IDLE = 4'd0, BIT_0 = 4'd1, BIT_1 = 4'd2,
                BIT_2 = 4'd3, BIT_3 = 4'd4, BIT_4 = 4'd5, BIT_5 = 4'd6, 
                BIT_6 = 4'd7, BIT_7 = 4'd8, BYTE_READY = 4'd9;

reg [3:0] state = 0;
reg [7:0] baud_rate_clock = 0;

always @(posedge clk) begin
  if (baud_rate_clock == 8'd216) begin
    baud_rate_clock <= 0;
  end
  else begin
    baud_rate_clock <= baud_rate_clock + 8'd1;
  end
end

assign baud_tick = ~|baud_rate_clock;

always @(posedge baud_tick or negedge reset_n) begin
    if (~reset_n) begin
        state <= 0;
        byte_ready <= 0;
    end
    case(state)
        IDLE: begin
             byte_ready <= 0;
             if (Rx == 0) state <= BIT_0;
        end
        BIT_0: begin
           received_byte[0] <= Rx;
           state <= BIT_1;
        end
        BIT_1: begin
             received_byte[1] <= Rx;
             state <= BIT_2;
        end
        BIT_2: begin
             received_byte[2] <= Rx;
             state <= BIT_3;
        end
        BIT_3: begin
             received_byte[3] <= Rx;
             state <= BIT_4;
        end
        BIT_4: begin
             received_byte[4] <= Rx;
             state <= BIT_5;
        end
        BIT_5: begin
             received_byte[5] <= Rx;
             state <= BIT_6;
        end
        BIT_6: begin
             received_byte[6] <= Rx;
             state <= BIT_7;
        end
        BIT_7: begin
             received_byte[7] <= Rx;
             state <= BYTE_READY;
        end
        BYTE_READY: begin
             byte_ready <= 1;
             state <= IDLE;
        end
        default: state <= IDLE;
    endcase
end      


endmodule

Aquí están mis resultados de la simulación:

Simulation results

Así que, básicamente, la simulación está reaccionando exactamente como quiero.

He enviado 0x55, 0x74, y 0x40, y que es cuando byte_ready se afirma, así que sé que es correcto.

Además, mi baud_tick de señal está correctamente afirmó 115200 veces en un segundo.

Por encima de todo, mi simulación parece ser perfecto.

Cuando en realidad el programa de la FPGA y conectar la línea Rx, no pasa nada (como en, no hay ningún Led intermitente). Yo he programado que el 8 LEDs tomar los valores de los 8 bits del byte. He probado este método antes con alguien de implementación y funcionó perfectamente para probar el módulo.

Yo he utilizado la SignalTap analizador lógico y confirmó la entrantes Rx de datos es correcta, y la tasa de baudios es correcta con + o - 0.5% de error.

No tengo idea de qué hacer desde aquí. Alguna sugerencia?

8voto

MarkU Puntos 3743

Código FPGA trabaja en la simulación de conducta, pero no en el hardware

Esto sucede a veces. Así que tal vez algo está mal con el hardware, y tal vez la simulación no modelar con precisión lo que sucede en la realidad. Tienen que revisar ambos.

Supongo que usted es un estudiante, ya que no es gratis, preparado código que ya implementa de serie UARTs, así que mi respuesta es acerca de cómo acercarse a la depuración de este tipo de problema.

1. Hizo la síntesis de realmente tener éxito?

Al generar el proyecto, ¿hay algún diagnóstico o mensajes de advertencia? ¿El sintetizados código sentido?

Examinar la post-traducción/post-síntesis de código que es generado por las diversas herramientas de síntesis.

Como está escrito, el código que has publicado es de comportamiento (always @posedge), no estructurales (instancias y cables). Que hace que sea muy sencillo para simular, pero la herramienta de síntesis tiene que tratar de reconocer lo que estás pidiendo por la comparación con las plantillas. Si su always declaración no coincide con una de las plantillas, la herramienta de síntesis no sabes cómo ponerlo en práctica. Que debe generar un mensaje de diagnóstico en algún lugar.

La primera traducción de la fase genera código RTL (Register Transfer Lógica) que es genérico de la lógica combinacional además de flip-flops. En este ejemplo, usted debe esperar para ver algunos de los flip-flops para la velocidad en baudios del contador y el estado de la máquina, y algunos de lógica combinacional para determinar el estado siguiente. Después de la síntesis de las fases de averiguar cómo configurar la FPGA para implementar RTL código. Estos asignación y el lugar y la ruta de las fases de elegir qué rebanada (Xilinx) o bloque de lógica configurable (Altera) será que el flip-flop, que pin para el uso para el que toplevel puertos de entrada/salida, y cómo conectar todo junto.

Después de la traducción/asignación/lugar-y-ruta, puedes volver a ejecutar post-asignación o post-lugar-y-la simulación de la ruta. Esto simula el RTL código de la herramienta de síntesis generado, no el código de comportamiento con el que comenzó. Esta simulación sabe donde cada flip-flop se encuentra y cómo muchos de los picosegundos de retardo de cada ruta, así que usted puede ver una visión más realista de simulación de la temporización de los bordes. (Debido a que el reloj es sólo 25MHz espero que no debe haber un montón de tiempo de margen.)

La simulación y la síntesis son muy diferentes. Un always bloque que funciona bien en la simulación inesperadamente puede ser omitido después de la síntesis. (Yo una vez perdida la mitad de un muy complejo sistema debido a un "incompleto de inicialización ignorado la advertencia:" en un bajo nivel de módulo, lo que causó Xilinx ISE 14.7 para reemplazar un módulo completo con una temperatura constante de 0. Y todos los de nivel superior de los módulos que dependía de la señal, tengo optimizado lejos para nada, ya que sus salidas se convirtió en una constante. Ya no había ninguna lógica interna a la unidad de mi salida SPI, el pin de salida no se encaminan. Ahora he desarrollado el hábito de revisar el RTL después de la síntesis para asegurarse de que no hay piezas que faltan.)

Yo vengo de una programación en C de fondo, por lo que constantemente me han desafiarme a mí mismo al escribir Verilog: ¿qué hardware no quiero sintetizar, a continuación, asegúrese de que estoy describiendo de una forma en la que la herramienta de síntesis puede entender.

2. ¿Qué es el hardware haciendo en realidad?

Desde la FPGA está haciendo nada de lo que se puede observar directamente, es difícil de diagnosticar si la FPGA está encendido, configurado con el código, y el funcionamiento de su máquina de estado. Modificar su nivel superior para llevar a cabo algunos diagnositc salidas:

  • Traiga state[3:0] a cuatro de los LEDs

  • Traiga baud_tick de señal a un LED

  • Agregar un "latido" de LED luz intermitente a su nivel superior (sólo de alternar un D flip-flop en la mitad de la clk tasa), para ayudar a confirmar que la FPGA firmware está configurado. Este diagnositc es la pena renunciar a uno de los LEDs, al menos por ahora.

  • Traiga received_byte[0] (el primer y el bit menos significativo) a un LED

  • Traiga received_byte[7] (el último y el bit más significativo) a un LED

Esto significa que el uso de los ocho LEDs en su consejo de administración para el diagnóstico de las señales, en lugar de la received_byte[7:0] de datos en paralelo. Pero estas las señales de bajo nivel dará la información más útil para ver lo que está pasando en el interior del módulo. Se puede cambiar de nuevo después de obtener los errores corregidos.

Puedo asumir que sus FPGA de la junta tiene algunos rebotada interruptores. Ahora es el momento de ponerlos a trabajar:

  • El uso de un rebotada, deslice el interruptor a la unidad reset

  • El uso de un rebotada, deslice el interruptor a la unidad Rx

  • El uso de un rebotada, deslice el interruptor a la unidad clk

Cambiar temporalmente la tasa de baudios del parámetro de modo de obtener baud_tick cada 7 ciclos de reloj, de modo que usted puede manualmente clk-alternar a través de todos los estados, sin perder la noción del tiempo.

El paso a través del estado de la máquina poco a poco, en el hardware real.

  • Compruebe que el latido del corazón LED está parpadeando (alternando 1/2 clk frecuencia)

  • Compruebe que baud_tick le da un impulso a la tasa esperada (SUGERENCIA: creo que aquí es donde vas a encontrar el problema. Lo que si iniciales baud_rate_clock valor es al azar?)

  • Compruebe que el estado de la máquina va para el correcto estado de reset.

  • Compruebe que su estado de la máquina permanece en estado de reposo cuando Rx está inactivo.

  • Compruebe que su estado de la máquina detecta el bit de inicio.

  • Compruebe que su estado de ciclos de la máquina a través de los estados correctamente y vuelve al estado de reposo.

  • Compruebe que el received_byte[0] y received_byte[7] valores son lo que usted espera.

Un osciloscopio es un verdadero lifeline si usted tiene uno disponible, esto le permitiría ver el hardware que se ejecuta a toda velocidad, sin necesidad de alternar con rebotada interruptores. Para una más complicado el diseño esta sería una herramienta esencial.

3. ¿Por qué no la simulación de la realidad?

Totalmente de pruebas de un diseño es realmente un problema difícil. Especialmente cuando se trata de su propio código. En este ejemplo, el código tiene entradas clk, reset, y Rx. Ya estás conduciendo clk.

  • ¿Qué sucede si la Rx es en el "mal" del estado al salir de reset? El estado de la máquina que se recupere?

  • ¿Qué pasa si el transmisor es el uso de una velocidad de transmisión diferente (+5%, -5%, +10%, -10%, x2, x0.5)

  • ¿Qué pasa si el estado de la máquina se pone en marcha en un estado aleatorio, se recupera o se atascan?

  • ¿Qué pasa si la Rx de marco tiene la mala bit de parada valor?

  • ¿Qué pasa si la Rx es de marca cuando usted está esperando espacio?

  • ¿Qué pasa si la Rx es invertida? (Este es un error muy común en RS232 UART de los sistemas, debido a que la lógica de nivel RS232 nivel de traductor normalmente invierte.)

Usted consigue la idea. Viene con todas las condiciones de la prueba es tan difícil como cualquier otro tipo de trabajo de diseño. Siempre habrá lagunas en la cobertura, por lo que planea volver atrás y añadir más pruebas basadas en lo que se encuentra en la comprobación del hardware.

Una de las cosas más difíciles, tanto en la programación y en el diseño HDL, es la prueba de sus propios diseños. Cuando escribo un banco de prueba para mi propio código, siempre me preocupe que no he cubierto lo suficiente posibles casos de prueba. Y en cualquier caso de prueba que se me ocurre, probablemente he afrontado en mi código, es una de las pruebas que no pensaba que causan deficiencias en la cobertura de las pruebas. Por ejemplo, ¿qué pasa si la señal de entrada no está sincronizado con el dispositivo bajo prueba? Eso es muy común en el hardware real, pero puede ser difícil de establecer en una simulación de conducta.

Espero que esto sea suficiente para conseguir que en su camino. Buena suerte!

1voto

MegaMind Puntos 116

El código no es sintetizable por un allí debe ser una else antes de case . Habría cogido en simulación probando el reset_n pin.

  • Cambios necesarios están en negrita
  • Recomendar mejoras son cursiva negrita
always @(posedge baud_tick or negedge reset_n) begin
    if (~reset_n) begin
        state <= 

Esta falta IDLE; error debe estar en su registro/informe de síntesis.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X