Código más elegante para el generador síncrono de onda cuadrada en Verilog

0

Estoy estudiando por mi cuenta con el libro de prototipos FPGA de Chu. El ejercicio 4.7.1 solicita un generador de onda cuadrada programable:

  

Un generador de onda cuadrada programable es un circuito que puede generar una onda cuadrada con   variable en intervalos (es decir, lógica 1) y apagado (es decir, lógica 0). Las duraciones de los intervalos son.   especificado por dos señales de control de 4 bits, myn, que se interpretan como enteros sin signo.   Los intervalos de encendido y apagado son m * 100 ns y n * 100 ns, respectivamente. Diseñar un circuito generador de onda cuadrada programable. El circuito debe ser completamente sincrónico.

Tengo una solución de trabajo completamente sincrónica, pero no pude encontrar una buena forma para que sea precisa en el ciclo, en el sentido de que el código que más me gusta usa dos ciclos de reloj más para cambiar el nivel lógico del cuadrado ola. Estoy pegando todo el código al final de mi pregunta, pero lo que no me gusta es la parte que hace if(clk_tick_count == interval_quant_ns - 1) , específicamente tener que restar 1 de la cantidad de intervalos que quiero contar. Llegué a esta solución después de verificar que la solución sin el -1 estaba tomando dos ciclos de reloj más, y la arreglé con el -1. Entiendo que esto se debe a que, dado que la actualización es sincrónica, necesito otro ciclo de reloj completo para que los cambios se reflejen en mi ouput wave.

Simplemente tengo la sensación de que hay una forma más agradable de hacer esto, pero no puedo discutirlo con nadie ni he tenido la suerte de buscar un código mejor en línea.

¡Gracias!

Este es mi código actual:

module sqwaveGen
#( 
parameter interval_quant_ns = 5
)
(
input wire clk,
input wire rst,
output wire wave,
input wire [3:0] on_interval, 
input wire [3:0] off_interval 
);

reg wave_next, wave_reg;
reg [3:0] clk_tick_count, clk_tick_count_next;
reg [3:0] count, count_next;

always @(posedge clk, negedge rst) begin
    if(~rst) begin
        wave_reg <= 0;
        clk_tick_count <= 0;
        count <= 0;
    end else begin
        wave_reg <= wave_next;
        clk_tick_count <= clk_tick_count_next;
        count <= count_next; 
    end
end

always @(*) begin
    wave_next = wave_reg;
    count_next = count;
    clk_tick_count_next = clk_tick_count + 1;

    if(wave_reg == 0 && count == off_interval) begin
        wave_next = 1;
        count_next = 0;
    end

    if(wave_reg == 1 && count == on_interval) begin
        wave_next = 0;
        count_next = 0;
    end                      

    if(clk_tick_count == interval_quant_ns - 1) begin
        count_next = count + 1;
        clk_tick_count_next = 0;
    end

end

assign wave = wave_reg;

endmodule

Onda de salida de una prueba para completar, mostrando que esto funciona:

    
pregunta Peter

3 respuestas

1

Si desea implementar algo que requiera un número de conteo N (4 por ejemplo), puede contar 0, 1, ..., N-1 (ejemplo, 0, 1, 2, 3, 0, 1 ...). O puede contar 1, 2, ..., N (ejemplo, 1, 2, 3, 4, 1, 2 ...). Entonces, si desea finalizar el conteo en el número N, comience el conteo en 1.

A menudo, los estilos de codificación son solo preferencias personales. La compensación por una condición nunca me molesta. Aunque casi siempre uso la cuenta regresiva por hábito porque hay un par de beneficios potenciales: puede sintetizarse para ser más rápido, y solo requiere la entrada del parámetro de cuenta en el reloj de inicio (generalmente no es una característica beneficiosa en un ciclo continuo como aquí). ).

    
respondido por el rioraxe
0

Bueno, para empezar, estás usando dos bloques siempre donde uno estaría bien. Al fusionar todo en un bloque, se eliminan todas esas feas "siguientes" señales.

También podemos hacer que la salida sea un registro eliminando la señal wave_reg.

module sqwaveGen
#( 
parameter interval_quant_ns = 5
)
(
input wire clk,
input wire rst,
output reg wave,
input wire [3:0] on_interval, 
input wire [3:0] off_interval 
);

reg [3:0] clk_tick_count, clk_tick_count;
reg [3:0] count;

always @(posedge clk, negedge rst) begin
    if(~rst) begin
        wave_reg <= 0;
        clk_tick_count <= 0;
        count <= 0;
    end else begin       
        clk_tick_count <= clk_tick_count + 1;

        if(wave == 0 && count == off_interval) begin
            wave <= 1;
            count <= 0;
        end

        if(wave == 1 && count == on_interval) begin
            wave <= 0;
            count <= 0;
        end                      

        if(clk_tick_count == interval_quant_ns - 1) begin
            count <= count + 1;
            clk_tick_count <= 0;
        end

    end
end

endmodule
    
respondido por el Peter Green
0

Podrías quitar el "interval_quant_ns - 1" de tu lógica y esconderlo en la parte superior del archivo donde no estarás mirando a menudo.

Contar el contador de ondas hacia abajo (punta de rioraxe) + una modificación al código de Peter Green le permite recortar algunas líneas también:

module sqwaveGen #(parameter interval_quant_ns = 5)
  (
  input wire clk,
  input wire rst,
  output reg wave,
  input wire [3:0] on_interval, 
  input wire [3:0] off_interval 
  );
  localparam interval_quant_count_to = interval_quant_ns - 1; /* Shh don't tell anyone I'm here */

  reg [3:0] clk_tick_count;
  reg [3:0] count;

  always @(posedge clk, negedge rst) begin
    if(~rst) begin
        wave <= 0;
        clk_tick_count <= 0;
        count <= 0;
    end
    else begin       
        clk_tick_count <= clk_tick_count + 1;

        if(clk_tick_count == interval_quant_count_to) begin
            count <= count - 1;
            clk_tick_count <= 0;
        end

        if(count == 0) begin // now all you need to keep track of is when the counter hits 0; then you toggle the wave and set the counter up for the next interval
            count <= (wave == 1) ? off_interval : on_interval;
            wave <= ~wave;
        end
    end
  end
endmodule
    
respondido por el PistoletPierre

Lea otras preguntas en las etiquetas