¿Cómo implementar de manera eficiente un solo impulso de salida desde una entrada larga en Altera?

4

Tengo un reloj rápido y un interruptor llamado "listo". Cuando se gira el interruptor (listo va ALTO), me gustaría que la salida pcEn produzca un pulso que dura solo un ciclo de reloj. pcEn solo emitirá otro pulso la próxima vez que esté listo HIGH otra vez.

El siguiente código simula correctamente, pero desafortunadamente no es sintetizable. Tenga en cuenta que el espacio es una consideración importante, por lo que me preguntaba si es posible implementarlo sin usar una máquina de estados (que utiliza muchos elementos lógicos).

module control
(
    output logic pcEn,
    input clock, ready
);

always_ff @(negedge clock)
    pcEn <= 1'b0;

always_ff @(posedge ready)
    pcEn <= 1'b1;

endmodule
    
pregunta geft

3 respuestas

4

Mi técnica habitual es implementar un sincronizador de 2 etapas para llevar la entrada asíncrona al dominio de tiempo del reloj, y luego usar un flip-flop más como detector de bordes. Dependiendo de la lógica que use en la última declaración, puede detectar bordes ascendentes, bordes descendentes o ambos.

module control
(
    output logic pcEn,
    input clock, ready
);
    reg r1, r2, r3;

    always @(posedge clock) begin
        r1 <= ready;    // first stage of 2-stage synchronizer
        r2 <= r1;       // second stage of 2-stage synchronizer
        r3 <= r2;       // edge detector memory
    end

    pcEn <= r2 && !r3;   // pulse on rising edge
endmodule
    
respondido por el Dave Tweed
1

La formación habitual para alternar a pulso está en la línea de

module flip (output logic pcEn, input clock, input ready);
reg state;
always_ff @(posedge clock)
      state <= ready;
assign pcEn = state != ready;
endmodule

Si ready se maneja externamente, vale la pena limpiarlo para alinearlo con el borde del reloj con una sola etapa de registro primero. No hay necesidad de reiniciar. Si va a contar la salida, también debe dirigirse a cambio de rebote.

Para abordar el comentario de Daves: modificado para tener que registrar la salida pcEn y disparar en el flanco ascendente.

module flip (output reg pcEn, input clock, input ready);
reg state;
always_ff @(posedge clock) begin
      state <= ready;
      pcEn  <= state != ready && ready;
end
endmodule

    
respondido por el shuckc
0

Esto es lo que Xilinx parece recomendar, que no está muy lejos de Dave Tweed:

(* ASYNC_REG = "TRUE" *) reg     state;
(* ASYNC_REG = "TRUE" *) reg     statemeta;
reg                              reloadRegmeta  = 1'b0;

# -> for negative edge    assign pcEn = state | (~reloadRegmeta);
assign pcEn = state && (~reloadRegmeta);
always @(posedge S_AXI_ACLK) begin
    statemeta     <= ready;
    state         <= statemeta;
    reloadRegmeta <= state;
end
    
respondido por el Kurt Peters

Lea otras preguntas en las etiquetas