|
4 | 4 | //--------------------------------------------------------------------------------
|
5 | 5 |
|
6 | 6 | // INFO --------------------------------------------------------------------------------
|
7 |
| -// Dynamic delay for arbitrary signal |
| 7 | +// Dynamic delay for arbitrary signal. |
8 | 8 | //
|
9 |
| -// CAUTION: The module intentionally does NOT implement error handling when |
10 |
| -// LENGTH is not a multiple of 2. Please handle "out of range" |
11 |
| -// checks externally. |
| 9 | +// Incoming data elements have WIDTH bits each. Module does serialization of |
| 10 | +// input data and outputs flattened bits, based on provided selector value. |
| 11 | +// You can perform delays bit-wize, not just element-wize. |
| 12 | +// |
| 13 | +// CAUTION: Be careful selecting last, most-delayed "WIDTH" number of bits. |
| 14 | +// The module intentionally does NOT implement "out of range" |
| 15 | +// checks. Please handle them externally. |
| 16 | + |
12 | 17 |
|
13 | 18 |
|
14 | 19 | /* --- INSTANTIATION TEMPLATE BEGIN ---
|
15 | 20 |
|
16 | 21 | dynamic_delay #(
|
17 |
| - .LENGTH( 8 ) |
18 |
| - //.SEL_W( 3 ) |
19 |
| -) DD1 ( |
| 22 | + .LENGTH( 3 ), |
| 23 | + .WIDTH( 4 ) |
| 24 | +) M ( |
20 | 25 | .clk( clk ),
|
21 |
| - .nrst( 1'b1 ), |
| 26 | + .nrst( nrst ), |
22 | 27 | .ena( 1'b1 ),
|
23 |
| - .in( ), |
24 |
| - .sel( ), |
25 |
| - .out( ) |
| 28 | + .in( in_data[3:0] ), |
| 29 | + .sel( sel[3:0] ), |
| 30 | + .out( out_data[3:0] ) |
26 | 31 | );
|
27 | 32 |
|
28 | 33 | --- INSTANTIATION TEMPLATE END ---*/
|
29 | 34 |
|
30 | 35 |
|
31 | 36 | module dynamic_delay #( parameter
|
32 |
| - LENGTH = 8, // maximum delay chain width |
33 |
| - SEL_W = $clog2(LENGTH) // output selector width |
| 37 | + LENGTH = 63, // maximum delay chain length |
| 38 | + WIDTH = 4, // data width |
| 39 | + |
| 40 | + SEL_W = $clog2( (LENGTH+1)*WIDTH ) // output selector width |
| 41 | + // plus one is for zero delay element |
34 | 42 | )(
|
35 | 43 | input clk,
|
36 | 44 | input nrst,
|
37 | 45 | input ena,
|
38 |
| - input in, |
39 |
| - input [SEL_W-1:0] sel, // output selector |
40 |
| - output logic out |
| 46 | + input [WIDTH-1:0] in, // input data |
| 47 | + // bit in[0] is the "oldest" one |
| 48 | + // bit in[WIDTH] is considered the most recent |
| 49 | + input [SEL_W-1:0] sel, // output selector |
| 50 | + output logic [WIDTH-1:0] out // output data |
41 | 51 | );
|
42 | 52 |
|
43 |
| -logic [(LENGTH-1):0] data = 0; |
| 53 | + |
| 54 | + |
| 55 | +logic [(LENGTH+1)-1:0][WIDTH-1:0] data = '0; |
| 56 | + |
| 57 | +// packed vector includes extra bits |
| 58 | +logic [(LENGTH+1)*WIDTH-1:0] pack_data; |
| 59 | +assign pack_data[(LENGTH+1)*WIDTH-1:0] = data; |
44 | 60 |
|
45 | 61 | integer i;
|
46 | 62 | always_ff @(posedge clk) begin
|
47 |
| - if (~nrst) begin |
48 |
| - data[(LENGTH-1):0] <= 0; |
49 |
| - out <= 0; |
| 63 | + if( ~nrst ) begin |
| 64 | + // reset all data except zero element |
| 65 | + for( i=1; i<(LENGTH+1); i=i+1 ) begin |
| 66 | + data[i][WIDTH-1:0] <= '0; |
| 67 | + end |
50 | 68 | end else if (ena) begin
|
51 |
| - data[0] <= in; |
52 |
| - for (i=1; i<LENGTH; i=i+1) begin |
53 |
| - data[i] <= data[i-1]; |
| 69 | + for( i=1; i<(LENGTH+1); i=i+1 ) begin |
| 70 | + data[i][WIDTH-1:0] <= data[i-1][WIDTH-1:0]; |
54 | 71 | end
|
55 |
| - out <= data[sel[SEL_W-1:0]]; |
| 72 | + end |
| 73 | +end |
| 74 | + |
| 75 | +integer j; |
| 76 | +always_comb begin |
| 77 | + // zero element assignment |
| 78 | + data[0][WIDTH-1:0] <= in[WIDTH-1:0]; |
| 79 | + |
| 80 | + // output selector, sel==0 gives non-delayed output |
| 81 | + for( j=0; j<WIDTH; j=j+1 ) begin |
| 82 | + out[j] <= pack_data[sel[SEL_W-1:0]+j]; |
56 | 83 | end
|
57 | 84 | end
|
58 | 85 |
|
|
0 commit comments