¿Cómo tener una señal de reinicio activada por un borde en un circuito verilog secuencial?

1

Me pregunto cómo es posible construir un circuito verilog secuencial con un disparador de reinicio. El problema que tengo es que necesito un bloque siempre específico para cuando se activa el restablecimiento. He creado este ejemplo de un contador para demostrar lo que quiero decir:

'timescale 1ns / 1ps

module Counter(input CLK, reset, output reg[2:0] val);
    always@(posedge CLK)
        val = val+1;

    always@(negedge reset)
        val = 0;

endmodule

El error que obtengo al sintetizar esto es

"ERROR:Xst:528 - Multi-source in Unit <Counter> on signal <Mcount_val_cy<0>>; this signal is connected to multiple drivers.
Drivers are: 
   Output signal of FD instance <val_0>
   Signal <val<0>> in Unit <Counter> is assigned to GND"  

Esto se debe a que val se actualiza en 2 declaraciones siempre.

¿Cómo puedo solucionar esto y tener un circuito secuencial con un activador de reinicio?

    
pregunta Tyler H

2 respuestas

1

Una forma de hacer esto es combinar los bloques siempre, como este:

module Counter(input CLK, reset, output reg[2:0] val);
    always@(posedge CLK or negedge reset) begin
        if (!reset) begin
            val <= 0;
        end else begin
            val <= val+1;
        end
    end
endmodule

Esto reiniciará el contador siempre que el reinicio sea bajo.

Sin embargo, esta puede o no ser la funcionalidad que está buscando. En general, los reinicios asíncronos en los FPGA no son una gran idea. Una alternativa es usar un detector de bordes, como este:

module Counter(input CLK, reset, output reg[2:0] val);
    reg reset_reg = 0;
    reg last_reset_reg = 0;
    always@(posedge CLK) begin
        reset_reg <= reset;
        last_reset <= reset_reg;
        if (!reset_reg && last_reset_reg) begin
            val <= 0;
        end else begin
            val <= val+1;
        end
    end
endmodule
    
respondido por el alex.forencich
2

La forma más sencilla de hacerlo sería sincronizar la señal reset en el dominio del reloj del contador y luego hacer la detección de bordes en él. Aquí hay un fragmento real de un proyecto en el que estoy trabajando actualmente. Estoy usando un reloj local fijo para medir el período de una señal de datos entrante.

  /* This logic is in the "fast local clock" domain.
   * The local clock is assumed to be faster than the RF signal itself, by
   * a factor of at least two. We resynchronize bit_pulse to the FLC domain
   * and count the number of cycles between the rising edges of those pulses.
   *
   * The bit_period is stable by the time the logic in the rf_in domain
   * looks at it based on a delayed version of the original bit_pulse.
   */
  always @(posedge clock) begin
    flc_pulse_a <= bit_pulse;
    flc_pulse_b <= flc_pulse_a;
    flc_pulse_c <= flc_pulse_b;
    if (sim_reset || (flc_pulse_b && !flc_pulse_c)) begin
      bit_period <= bit_count;
      bit_count <= 0;
    end else begin
      bit_count <= bit_count + 1;
    end
  end

Tenga en cuenta que ES posible hacer lo que quiera con una máquina de estado asíncrona compleja, pero los FPGA generalmente no tienen los recursos para implementar estas cosas de manera eficiente, y las herramientas no están configuradas para admitir dichos diseños.

Además, debe pensar en casos de límites: si los dos eventos ( posedge clock y negedge reset_l ) son verdaderamente asíncronos, eso significa que pueden ocurrir arbitrariamente juntos. ¿Qué comportamiento esperas cuando eso sucede?

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas