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 clkd_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
|