4
4
// ------------------------------------------------------------------------------
5
5
6
6
// INFO -------------------------------------------------------------------------
7
- // Static Delay for arbitrary signal
7
+ // Static Delay for arbitrary signal, v2
8
8
// Another equivalent names for this module:
9
9
// conveyor.sv
10
10
// synchronizer.sv
14
14
//
15
15
//
16
16
// CAUTION: delay module is widely used for synchronizing signals across clock
17
- // domains. To automatically exclude input data paths from timing analisys
18
- // set_false_path SDC constraint is integrated into this module. Applicable
19
- // only to Intel/Altera Quartus IDE. Xilinx users still should write the
20
- // constraints manually
17
+ // domains. When synchronizing, please exclude input data paths from timing
18
+ // analisys manually by writing appropriate set_false_path SDC constraint
21
19
//
20
+ // Version 2 introduces "ALTERA_BLOCK_RAM" option to implement delays using
21
+ // block RAM. Quartus can make shifters on block RAM aautomatically
22
+ // using 'altshift_taps' internal module when "Auto Shift Register
23
+ // Replacement" option is ON
22
24
23
25
24
26
/* --- INSTANTIATION TEMPLATE BEGIN ---
25
27
26
28
delay #(
27
- .LENGTH( 2 )
29
+ .LENGTH( 2 ),
30
+ .WIDTH( 1 ),
31
+ .TYPE( "CELLS" )
28
32
) S1 (
29
33
.clk( clk ),
30
34
.nrst( 1'b1 ),
31
35
.ena( 1'b1 ),
36
+
32
37
.in( ),
33
38
.out( )
34
39
);
@@ -37,45 +42,110 @@ delay #(
37
42
38
43
39
44
module delay # ( parameter
40
- LENGTH = 2 // delay/synchronizer chain length
41
- // default length for synchronizer chain is 2
45
+ LENGTH = 2 , // delay/synchronizer chain length
46
+ WIDTH = 1 , // signal width
47
+ TYPE = " CELLS" , // "ALTERA_BLOCK_RAM" infers block ram fifo
48
+ // all other values infer registers
49
+
50
+ CNTR_W = $clog2(LENGTH )
42
51
)(
43
52
input clk,
44
53
input nrst,
45
54
input ena,
46
- input in,
47
- output out
55
+
56
+ input [WIDTH - 1 : 0 ] in,
57
+ output [WIDTH - 1 : 0 ] out
48
58
);
49
59
50
60
generate
51
61
52
62
if ( LENGTH == 0 ) begin
53
- assign out = in;
63
+
64
+ assign out[WIDTH - 1 : 0 ] = in[WIDTH - 1 : 0 ];
65
+
54
66
end else if ( LENGTH == 1 ) begin
55
67
56
- logic data = 0 ;
68
+ logic [ WIDTH - 1 : 0 ] data = ' 0 ;
57
69
always_ff @ (posedge clk) begin
58
- if ( ~ nrst) begin
59
- data <= 0 ;
60
- end else if ( ena) begin
61
- data <= in;
70
+ if ( ~ nrst ) begin
71
+ data[ WIDTH - 1 : 0 ] <= ' 0 ;
72
+ end else if ( ena ) begin
73
+ data[ WIDTH - 1 : 0 ] <= in[ WIDTH - 1 : 0 ] ;
62
74
end
63
75
end
64
- assign out = data;
76
+ assign out[ WIDTH - 1 : 0 ] = data[ WIDTH - 1 : 0 ] ;
65
77
66
78
end else begin
79
+ if ( TYPE == " ALTERA_BLOCK_RAM" && LENGTH >= 4 ) begin
67
80
68
- logic [LENGTH : 1 ] data = 0 ;
69
- always_ff @ (posedge clk) begin
70
- if (~ nrst) begin
71
- data[LENGTH : 1 ] <= 0 ;
72
- end else if (ena) begin
73
- data[LENGTH : 1 ] <= { data[LENGTH - 1 : 1 ],in} ;
81
+ logic [CNTR_W - 1 : 0 ] delay_cntr = '0 ;
82
+
83
+ logic fifo_output_ena;
84
+ assign fifo_output_ena = (delay_cntr[CNTR_W - 1 : 0 ] == LENGTH );
85
+
86
+ always_ff @ (posedge clk) begin
87
+ if ( ~ nrst ) begin
88
+ delay_cntr[CNTR_W - 1 : 0 ] <= '0 ;
89
+ end else begin
90
+ if ( ena && ~ fifo_output_ena) begin
91
+ delay_cntr[CNTR_W - 1 : 0 ] <= delay_cntr[CNTR_W - 1 : 0 ] + 1'b1 ;
92
+ end
93
+ end
74
94
end
75
- end
76
- assign out = data[LENGTH ];
77
95
78
- end // if
96
+ logic [WIDTH - 1 : 0 ] fifo_out;
97
+ scfifo # (
98
+ .LPM_WIDTH ( WIDTH ),
99
+ .LPM_NUMWORDS ( LENGTH ), // must be at least 4
100
+ .LPM_WIDTHU ( CNTR_W ),
101
+ .LPM_SHOWAHEAD ( " ON" ),
102
+ .UNDERFLOW_CHECKING ( " ON" ),
103
+ .OVERFLOW_CHECKING ( " ON" ),
104
+ .ALMOST_FULL_VALUE ( 0 ),
105
+ .ALMOST_EMPTY_VALUE ( 0 ),
106
+ .ENABLE_ECC ( " FALSE" ),
107
+ .ALLOW_RWCYCLE_WHEN_FULL ( " ON" ),
108
+ .USE_EAB ( " ON" ),
109
+ .MAXIMIZE_SPEED ( 5 ),
110
+ .DEVICE_FAMILY ( " Cyclone V" )
111
+ ) internal_fifo (
112
+ .clock ( clk ),
113
+ .aclr ( 1'b0 ),
114
+ .sclr ( ~ nrst ),
115
+
116
+ .data ( in[WIDTH - 1 : 0 ] ),
117
+ .wrreq ( ena ),
118
+ .rdreq ( ena && fifo_output_ena ),
119
+
120
+ .q ( fifo_out[WIDTH - 1 : 0 ] ),
121
+ .empty ( ),
122
+ .full ( ),
123
+ .almost_full ( ),
124
+ .almost_empty ( ),
125
+ .usedw ( ),
126
+ .eccstatus ( )
127
+ );
128
+
129
+ assign out[WIDTH - 1 : 0 ] = (fifo_output_ena)? (fifo_out[WIDTH - 1 : 0 ]): ('0 );
130
+
131
+ end else begin
132
+
133
+ logic [LENGTH : 1 ][WIDTH - 1 : 0 ] data = '0 ;
134
+ always_ff @ (posedge clk) begin
135
+ integer i;
136
+ if ( ~ nrst ) begin
137
+ data <= '0 ;
138
+ end else if ( ena ) begin
139
+ for (i= LENGTH - 1 ; i> 0 ; i-- ) begin
140
+ data[i+ 1 ][WIDTH - 1 : 0 ] <= data[i][WIDTH - 1 : 0 ];
141
+ end
142
+ data[1 ][WIDTH - 1 : 0 ] <= in[WIDTH - 1 : 0 ];
143
+ end
144
+ end
145
+ assign out[WIDTH - 1 : 0 ] = data[LENGTH ][WIDTH - 1 : 0 ];
146
+
147
+ end // if TYPE
148
+ end // if LENGTH
79
149
80
150
endgenerate
81
151
0 commit comments