Skip to content

Commit b57c3a9

Browse files
committed
Updated delay module. Added block RAM implementation
1 parent d2f436d commit b57c3a9

File tree

2 files changed

+216
-26
lines changed

2 files changed

+216
-26
lines changed

delay.sv

+96-26
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//------------------------------------------------------------------------------
55

66
// INFO -------------------------------------------------------------------------
7-
// Static Delay for arbitrary signal
7+
// Static Delay for arbitrary signal, v2
88
// Another equivalent names for this module:
99
// conveyor.sv
1010
// synchronizer.sv
@@ -14,21 +14,26 @@
1414
//
1515
//
1616
// 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
2119
//
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
2224

2325

2426
/* --- INSTANTIATION TEMPLATE BEGIN ---
2527
2628
delay #(
27-
.LENGTH( 2 )
29+
.LENGTH( 2 ),
30+
.WIDTH( 1 ),
31+
.TYPE( "CELLS" )
2832
) S1 (
2933
.clk( clk ),
3034
.nrst( 1'b1 ),
3135
.ena( 1'b1 ),
36+
3237
.in( ),
3338
.out( )
3439
);
@@ -37,45 +42,110 @@ delay #(
3742

3843

3944
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)
4251
)(
4352
input clk,
4453
input nrst,
4554
input ena,
46-
input in,
47-
output out
55+
56+
input [WIDTH-1:0] in,
57+
output [WIDTH-1:0] out
4858
);
4959

5060
generate
5161

5262
if ( LENGTH == 0 ) begin
53-
assign out = in;
63+
64+
assign out[WIDTH-1:0] = in[WIDTH-1:0];
65+
5466
end else if( LENGTH == 1 ) begin
5567

56-
logic data = 0;
68+
logic [WIDTH-1:0] data = '0;
5769
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];
6274
end
6375
end
64-
assign out = data;
76+
assign out[WIDTH-1:0] = data[WIDTH-1:0];
6577

6678
end else begin
79+
if( TYPE=="ALTERA_BLOCK_RAM" && LENGTH>=4 ) begin
6780

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
7494
end
75-
end
76-
assign out = data[LENGTH];
7795

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
79149

80150
endgenerate
81151

delay_tb.sv

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//------------------------------------------------------------------------------
2+
// delay_tb.sv
3+
// Konstantin Pavlov, [email protected]
4+
//------------------------------------------------------------------------------
5+
6+
// INFO ------------------------------------------------------------------------
7+
// testbench for delay_tb.sv module
8+
9+
`timescale 1ns / 1ps
10+
11+
module delay_tb();
12+
13+
logic clk200;
14+
initial begin
15+
#0 clk200 = 1'b1;
16+
forever
17+
#2.5 clk200 = ~clk200;
18+
end
19+
20+
logic clk400;
21+
initial begin
22+
#0 clk400 = 1'b1;
23+
forever
24+
#1.25 clk400 = ~clk400;
25+
end
26+
27+
logic clk33;
28+
initial begin
29+
#0 clk33 = 1'b1;
30+
forever
31+
#15.151 clk33 = ~clk33;
32+
end
33+
34+
logic rst;
35+
initial begin
36+
#0 rst = 1'b0;
37+
#10.2 rst = 1'b1;
38+
#5 rst = 1'b0;
39+
end
40+
41+
logic nrst;
42+
assign nrst = ~rst;
43+
44+
logic rst_once;
45+
initial begin
46+
#0 rst_once = 1'b0;
47+
#10.2 rst_once = 1'b1;
48+
#5 rst_once = 1'b0;
49+
end
50+
51+
logic nrst_once;
52+
assign nrst_once = ~rst_once;
53+
54+
logic [31:0] DerivedClocks;
55+
clk_divider #(
56+
.WIDTH( 32 )
57+
) cd1 (
58+
.clk( clk200 ),
59+
.nrst( nrst_once ),
60+
.ena( 1'b1 ),
61+
.out( DerivedClocks[31:0] )
62+
);
63+
64+
logic [31:0] E_DerivedClocks;
65+
edge_detect ed1[31:0] (
66+
.clk( {32{clk200}} ),
67+
.nrst( {32{nrst_once}} ),
68+
.in( DerivedClocks[31:0] ),
69+
.rising( E_DerivedClocks[31:0] ),
70+
.falling( ),
71+
.both( )
72+
);
73+
74+
logic [31:0] RandomNumber1;
75+
c_rand rng1 (
76+
.clk( clk200 ),
77+
.rst( 1'b0 ),
78+
.reseed( rst_once ),
79+
.seed_val( DerivedClocks[31:0] ^ (DerivedClocks[31:0] << 1) ),
80+
.out( RandomNumber1[15:0] )
81+
);
82+
83+
c_rand rng2 (
84+
.clk( clk200 ),
85+
.rst( 1'b0 ),
86+
.reseed( rst_once ),
87+
.seed_val( DerivedClocks[31:0] ^ (DerivedClocks[31:0] << 2) ),
88+
.out( RandomNumber1[31:16] )
89+
);
90+
91+
// Module under test ==========================================================
92+
93+
delay #(
94+
.LENGTH( 10 ),
95+
.WIDTH( 8 )
96+
//.TYPE( "CELLS" )
97+
) d1 (
98+
.clk( clk200 ),
99+
.nrst( ~E_DerivedClocks[8] ),
100+
.ena( 1'b1 ),
101+
102+
.in( RandomNumber1[7:0] ),
103+
.out( )
104+
);
105+
106+
delay #(
107+
.LENGTH( 10 ),
108+
.WIDTH( 8 ),
109+
.TYPE( "ALTERA_BLOCK_RAM" )
110+
) d2 (
111+
.clk( clk200 ),
112+
.nrst( ~E_DerivedClocks[8] ),
113+
.ena( 1'b1 ),
114+
115+
.in( RandomNumber1[7:0] ),
116+
.out( )
117+
);
118+
119+
120+
endmodule

0 commit comments

Comments
 (0)