¿Por qué dentro del bloque siempre con la condición de posición, ve la señal como cero?

0

Estoy experimentando con FPGA (estoy usando la placa Mojo pero no creo que sea esencial), y escribí un código para agregar un contador cada vez que se presiona un botón (el contador está asignado a Los 8 leds en el tablero)

El código está debajo ( button_conditioner es simplemente un debouncer y no debería importar, por cierto, el código de este proyecto es aquí )

module mojo_top(
    // 50MHz clock input
    input clk,
    // Input from reset button (active low)
    input rst_n,
    // cclk input from AVR, high when AVR is ready
    input cclk,
    // Outputs to the 8 onboard LEDs
    output[7:0]led,
    // AVR SPI connections
    output spi_miso,
    input spi_ss,
    input spi_mosi,
    input spi_sck,
    // AVR ADC channel select
    output [3:0] spi_channel,
    // Serial connections
    input avr_tx, // AVR Tx => FPGA Rx
    output avr_rx, // AVR Rx => FPGA Tx
    input avr_rx_busy, // AVR Rx buffer full
    input button
);


wire rst = ~rst_n; // make reset active high

// these signals should be high-z when not used
assign spi_miso = 1'bz;
assign avr_rx = 1'bz;
assign spi_channel = 4'bzzzz;

wire btn_out;
reg [7:0] led_r;

assign led = led_r;

button_conditioner btn(
  .clk(clk),
  .btn(button),
  .out(btn_out)
);

always @(posedge rst or posedge btn_out) begin
  if (rst)
    led_r <= 0;
  else if (btn_out == 1'b0) // <=== THIS IS THE WTF LINE
    led_r <= led_r + 1;  
end

Lo que me desconcierta es que el contador solo aumenta si se comprueba el señal igual a cero pero la condición está en posedge es decir, una transición de 0 a 1: así que esperaría un cheque con 1'b1 , ¿qué me falta?

    
pregunta gipi

3 respuestas

1

Pensando en esto en términos de hardware, ¿qué valor hay en la entrada del led_r inferido D-flip-flop en el momento en que hay un borde ascendente que lo bloquea? Básicamente no lo sabes porque su entrada es una señal de flanco ascendente ( btn_out ). Estará en algún lugar entre 0 y 1 , aunque probablemente seguirá siendo 0 una vez que tenga en cuenta los retrasos en la propagación.

Es un código muy mal escrito (usando la lógica como un reloj, probablemente causando metastabilidad, etc.), y no estoy seguro de lo que se supone que debe hacer. Dicho esto, si tuviera que hacer una suposición, diría que debería ser simplemente else , no else if() . No necesita comprobarlo con nada porque sabe que es una ventaja ascendente en virtud del hecho de que será cronometrado por la ventaja ascendente que está buscando.

    
respondido por el Tom Carpenter
0

Su button_conditioner puede ser el problema. Está utilizando su salida como reloj, y los relojes deben estar libres de fallos. No puedo ver si ese es el caso de su diseño.

Los relojes necesitan un tratamiento especial: nunca los conecte con lógica, siempre conecte esa lógica a clock enable . En un buen diseño, todos tus bloques leen always @(posedge rst or posedge clk) . Todos los clics (es posible que tenga más de uno) deben provenir de entradas de reloj designadas o PLL internos, por lo que el software de diseño las enruta en las redes de reloj designadas y minimiza (y analiza) el sesgo.

  

En un diseño síncrono, las señales son estables y están bien definidas en el límite del reloj (ascendente). En el medio, todo tipo de cosas pueden pasar. Las señales pueden cambiar varias veces si sus entradas tienen diferentes retardos de propagación ("fallas"). Eso no hace daño siempre que todo se haya arreglado cuando llegue el reloj.

     

El reloj no debe tener bordes ascendentes adicionales durante ese tiempo de liquidación, ya que eso activará los registros para registrar un estado sin definir (indefinido). Los flancos ascendentes no deseados se introducen fácilmente combinando o sincronizando el reloj con otras señales lógicas.

Para su diseño, debe introducir un nuevo registro btn_out_delayed y hacer btn_out_delayed <= btn_out en cada ciclo de reloj. Luego puede hacer if (btn_out & ~btn_out_delayed) { led_r <= led_r + 1 } para obtener solo un aumento por cada pulsación. Esto normalmente se deducirá para habilitar el reloj.

Su software también debe incluir algún visor para verificar el resultado de la síntesis. Siempre es una buena idea ver que para cada módulo pequeño, se pueden detectar muchos errores allí (caso típico: el módulo completo se optimiza y se reemplaza con un controlador constante).

    
respondido por el Andreas
0

Estoy seguro de que si lees la especificación del lenguaje verilog esto está bien definido (pero no pude encontrarlo). Si tuviera un diseño más complejo en el que varias señales cambiaran a la vez y se usaran en un proceso cronometrado, ciertamente desearía actuar en los estados de señal existentes antes del borde del reloj para elegir sus acciones. . Esto es similar a preguntar por qué necesitas usar asignaciones no bloqueantes cuando inferes un flop.

When the clock transitions es una declaración ambigua en inglés. Puede leerse como cuando el reloj está en cero y necesita ir alto, o como una vez que el reloj está alto después de ser cambiado.

Su lógica no se modifica si elimina el if (btn_out) . Por definición, esta señal es baja a menos que se haya confirmado el restablecimiento. Para hacerlo más obvio, considere si escribió if (led_r == 8'h00) y necesita ver el primer ciclo en su evaluación.

    
respondido por el Sean Houlihane

Lea otras preguntas en las etiquetas