diff --git a/sim_clk_gen.sv b/sim_clk_gen.sv new file mode 100644 index 0000000..4433768 --- /dev/null +++ b/sim_clk_gen.sv @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// sim_clk_gen.sv +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// Testbench clock generator written in System Verilog +// + +`timescale 1ns / 1ps + +module sim_clk_gen #( parameter + FREQ = 200_000_000, // in Hz + PHASE = 0, // in degrees + DUTY = 50, // in percentage + DISTORT = 200 // in picoseconds +)( + input ena, + output logic clk, // ideal clock + output logic clkd // distorted clock +); + + real clk_pd = 1.0 / FREQ * 1e9; // convert to ns + real clk_on = DUTY / 100.0 * clk_pd; + real clk_off = (100.0 - DUTY) / 100.0 * clk_pd; + real start_dly = clk_pd / 4 * PHASE / 90; + + logic do_clk; + + initial begin + $display("FREQ = %0d Hz", FREQ); + $display("PHASE = %0d deg", PHASE); + $display("DUTY = %0d %%", DUTY); + $display("DISTORT = %0d ps", DISTORT); + + $display("PERIOD = %0.3f ns", clk_pd); + $display("CLK_ON = %0.3f ns", clk_on); + $display("CLK_OFF = %0.3f ns", clk_off); + $display("START_DLY = %0.3f ns", start_dly); + end + + initial begin + clk <= 0; + do_clk <= 1; + end + + always @ (posedge ena or negedge ena) begin + if (ena) begin + #(start_dly) do_clk = 1; + end else begin + #(start_dly) do_clk = 0; + end + end + + always @(posedge do_clk) begin + if( do_clk ) begin + clk = 1; + while ( do_clk ) begin + #(clk_on) clk = 0; + #(clk_off) clk = 1; + end + clk = 0; + end + end + + always @(*) begin + clkd = #($urandom_range(0, DISTORT)*1ps) clk; + end + +endmodule +