1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
//
// Copyright 2019 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: sim_clock_gen
//
// Description: This module generates a clock and reset signal for the purposes
// of simulation. Both clock and reset are configurable at run time for
// software-based simulation control.
//
module sim_clock_gen #(
parameter realtime PERIOD = 10.0, // Period in ns
parameter real DUTY_CYCLE = 0.5, // Duty cycle, in the range (0.0, 1.0)
parameter bit AUTOSTART = 1, // Start clock automatically at time 0
parameter realtime PHASE = 0.0 // Phase offset
) (
output bit clk,
output bit rst
);
timeunit 1ns;
timeprecision 1ps;
realtime period = PERIOD;
real duty = DUTY_CYCLE;
realtime low_time = PERIOD * (1.0 - DUTY_CYCLE);
realtime high_time = PERIOD * DUTY_CYCLE;
bit toggle = AUTOSTART;
bit alive = 1;
//-----------------------
// Clock and Reset Tasks
//-----------------------
// Set the period and duty cycle for the clock
function void set_clock(real new_period, real new_duty);
low_time = new_period * (1.0 - new_duty);
high_time = new_period * new_duty;
endfunction
// Set the period, only, for the clock
function void set_period(real new_period);
set_clock(new_period, duty);
endfunction
// Set the duty cycle, only, for the clock
function void set_duty(real new_duty);
set_clock(period, new_duty);
endfunction
// Start toggling the clock
function void start();
toggle = 1;
endfunction
// Stop toggling the clock
function void stop();
toggle = 0;
endfunction
// Stop running the clock loop (no new simulation events will be created)
function void kill();
alive = 0;
endfunction
// Start running the clock loop (new simulation events will be created)
function void revive();
alive = 1;
endfunction
// Asynchronously assert the reset signal and synchronously deassert it after
// "length" clock cycles.
task reset(int length = 8);
fork
begin
rst <= 1;
repeat (length) @(posedge clk);
rst <= 0;
end
join_none
// Make sure rst asserts before we return
wait(rst);
endtask : reset
// Assert reset
task set_reset();
rst <= 1'b1;
endtask : set_reset
// Deassert reset
task clr_reset();
rst <= 1'b0;
endtask : clr_reset
// Wait for num rising edges of the clock
task clk_wait_r(int num = 1);
repeat(num) @(posedge clk);
endtask
// Wait for num falling edges of the clock
task clk_wait_f(int num = 1);
repeat(num) @(negedge clk);
endtask
//--------------------------
// Clock Generation Process
//--------------------------
initial begin : clock_block
if (PHASE != 0.0) #(PHASE);
// Toggle the clock in a loop
forever begin : clock_loop
#(low_time);
if (toggle) clk = 0;
#(high_time);
if (toggle) clk = 1;
wait (alive);
end
end
endmodule : sim_clock_gen
|