-
Notifications
You must be signed in to change notification settings - Fork 380
/
delayed_event.sv
146 lines (117 loc) · 3.86 KB
/
delayed_event.sv
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//------------------------------------------------------------------------------
// delayed_event.sv
// published as part of https://github.com/pConst/basic_verilog
// Konstantin Pavlov, pavlovconst@gmail.com
//------------------------------------------------------------------------------
// INFO ------------------------------------------------------------------------
// Module generates delayed pulse one clock width
//
// - Could be useful for initialization or sequencing some tasks
// - Could be easily daisy-chained by connecting "after_event" outputs
// to the subsequent "ena" inputs
// - Only one event can be triggered after every reset
// - Delay operation could be suspended by setting ena to 0 at any time
// |
// |___,___, ,___,___,___,___,___,___,___,___,___,___,___,
// | , |___| , , , , , , , , , , , nrst
// |
// | <---------- DELAY -------->
// | ___
// |___,___,___,___,___,___,___,___,___,___| |___,___,___, on_event
// |
// | ,___,___,___,___,___,___,___,
// |___,___,___| , , , , , , |___,___,___,___, before_event
// |
// |___,___,___ ___,___,___,___,
// | , , |___,___,___,___,___,___,___| , , , , after_event
// |
//
/* --- INSTANTIATION TEMPLATE BEGIN ---
delayed_event #(
.DELAY( 8 )
) de1 (
.clk( clk ),
.nrst( nrst ),
.ena( ),
.on_event( ), // one clock cycle
.before_event( ),
.after_event( )
);
--- INSTANTIATION TEMPLATE END ---*/
module delayed_event #( parameter
DELAY = 32
)(
input clk, // system clock
input nrst, // negative reset
input ena, // enable
output on_event, // one clock cycle
output before_event, // event outputs
output after_event // event outputs
);
localparam CNTR_W = $clog2(DELAY+1);
generate
//==========================================================================
if ( DELAY == 0 ) begin
logic ena_rise;
edge_detect event_edge (
.clk( clk ),
.anrst( nrst ),
.in( ena ),
.rising( ena_rise )
);
assign on_event = ena_rise;
assign before_event = 1'b0;
assign after_event = 1'b1;
//==========================================================================
end else if ( DELAY == 1 ) begin
logic ena_d1 = 1'b0;
always_ff @(posedge clk) begin
if( ~nrst ) begin
ena_d1 <= 1'b0;
end else begin
ena_d1 <= ena;
end
end
logic ena_rise;
edge_detect event_edge (
.clk( clk ),
.anrst( nrst ),
.in( ena_d1 ),
.rising( ena_rise )
);
logic got_ena = 1'b0;
always_ff @(posedge clk) begin
if( ~nrst ) begin
got_ena <= 1'b0;
end if( on_event ) begin
got_ena <= 1'b1;
end
end
assign on_event = ena_rise;
assign before_event = !got_ena && !ena_rise;
assign after_event = got_ena || ena_rise;
//==========================================================================
end else begin
logic [CNTR_W-1:0] seq_cntr = CNTR_W'(DELAY);
logic seq_cntr_is_0;
assign seq_cntr_is_0 = (seq_cntr[CNTR_W-1:0]=='0);
always_ff @(posedge clk) begin
if( ~nrst) begin
seq_cntr[CNTR_W-1:0] <= CNTR_W'(DELAY);
end else begin
if( ena && ~seq_cntr_is_0 ) begin
seq_cntr[CNTR_W-1:0] <= seq_cntr[CNTR_W-1:0] - 1'b1;
end
end // nrst
end
edge_detect event_edge (
.clk( clk ),
.anrst( 1'b1 ),
.in( seq_cntr_is_0 ),
.rising( on_event )
);
assign before_event = ~seq_cntr_is_0;
assign after_event = seq_cntr_is_0;
end
endgenerate
endmodule