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: