forked from pConst/basic_verilog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathround_robin_performance_enc.sv
executable file
·116 lines (95 loc) · 2.98 KB
/
round_robin_performance_enc.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
//------------------------------------------------------------------------------
// round_robin_performance_enc.sv
// Konstantin Pavlov, [email protected]
//------------------------------------------------------------------------------
// INFO -------------------------------------------------------------------------
// VErsion of round robin combinational encoder to select only one bit from
// the input bus. Feature of this particular version is a performance boost
// motivated by skipping inactive inputs while performing round_robin.
//
// In contrast to priority encoder, every input bit (on average) has equal
// chance to get to the output when all inputs are equally probable
//
// See also round_robin_enc.sv
// See also priority_enc.sv
//
/* --- INSTANTIATION TEMPLATE BEGIN ---
round_robin_performance_enc #(
.WIDTH( 32 )
) RE1 (
.clk( clk ),
.nrst( nrst ),
.id( ),
.od_valid( ),
.od_filt( ),
.od_bin( )
);
--- INSTANTIATION TEMPLATE END ---*/
module round_robin_performance_enc #( parameter
WIDTH = 32,
WIDTH_W = $clogb2(WIDTH)
)(
input clk, // clock
input nrst, // inversed reset, synchronous
input [WIDTH-1:0] id, // input data bus
output od_valid, // output valid (some bits are active)
output logic [WIDTH-1:0] od_filt, // filtered data (only one priority bit active)
output logic [WIDTH_W-1:0] od_bin // priority bit binary index
);
// current bit selector
logic [WIDTH_W-1:0] priority_bit = '0;
// prepare double width buffer with LSB bits masked out
logic [2*WIDTH-1:0] mask;
logic [2*WIDTH-1:0] id_buf;
always_comb begin
integer i;
for ( i=0; i<2*WIDTH; i++ ) begin
if( i>priority_bit[WIDTH_W-1:0] ) begin
mask[i] = 1'b1;
end else begin
mask[i] = 1'b0;
end
end
id_buf[2*WIDTH-1:0] = {2{id[WIDTH-1:0]}} & mask[2*WIDTH-1:0];
end
logic [2*WIDTH-1:0] id_buf_filt;
leave_one_hot #(
.WIDTH( 2*WIDTH )
) one_hot_b (
.in( id_buf[2*WIDTH-1:0] ),
.out( id_buf_filt[2*WIDTH-1:0] )
);
logic [(WIDTH_W+1)-1:0] id_buf_bin; // one more bit to decode double width input
logic err_no_hot;
assign od_valid = ~err_no_hot;
pos2bin #(
.BIN_WIDTH( (WIDTH_W+1) )
) pos2bin_b (
.pos( id_buf_filt[2*WIDTH-1:0] ),
.bin( id_buf_bin[(WIDTH_W+1)-1:0] ),
.err_no_hot( err_no_hot ),
.err_multi_hot( )
);
always_comb begin
if( od_valid ) begin
od_bin[WIDTH_W-1:0] = id_buf_bin[(WIDTH_W+1)-1:0] % WIDTH;
od_filt[WIDTH-1:0] = 1'b1 << od_bin[WIDTH_W-1:0];
end else begin
od_bin[WIDTH_W-1:0] = '0;
od_filt[WIDTH-1:0] = '0;
end
end
// latching current
always_ff @(posedge clk) begin
if( ~nrst ) begin
priority_bit[WIDTH_W-1:0] <= '0;
end else begin
if( od_valid ) begin
priority_bit[WIDTH_W-1:0] <= od_bin[WIDTH_W-1:0];
end else begin
// nop,
end // if
end // if nrst
end
`include "clogb2.svh"
endmodule