mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
Added performance variant of encoder and tb
This commit is contained in:
parent
76674549c3
commit
a1608c2326
113
round_robin_performance_enc.sv
Executable file
113
round_robin_performance_enc.sv
Executable file
@ -0,0 +1,113 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// round_robin_performance_enc.sv
|
||||
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// 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 = $clog2(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
|
||||
|
||||
endmodule
|
121
round_robin_performance_enc_tb.sv
Executable file
121
round_robin_performance_enc_tb.sv
Executable file
@ -0,0 +1,121 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// round_robin_performance_enc_tb.sv
|
||||
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// INFO ------------------------------------------------------------------------
|
||||
// testbench for round_robin_performance_enc.sv module
|
||||
//
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module round_robin_performance_enc_tb();
|
||||
|
||||
logic clk200;
|
||||
initial begin
|
||||
#0 clk200 = 1'b0;
|
||||
forever
|
||||
#2.5 clk200 = ~clk200;
|
||||
end
|
||||
|
||||
// external device "asynchronous" clock
|
||||
logic clk33a;
|
||||
initial begin
|
||||
#0 clk33a = 1'b0;
|
||||
forever
|
||||
#7 clk33a = ~clk33a;
|
||||
end
|
||||
|
||||
logic clk33;
|
||||
//assign clk33 = clk33a;
|
||||
always @(*) begin
|
||||
clk33 = #($urandom_range(0, 2000)*10ps) clk33a;
|
||||
end
|
||||
|
||||
logic rst;
|
||||
initial begin
|
||||
#0 rst = 1'b0;
|
||||
#10.2 rst = 1'b1;
|
||||
#5 rst = 1'b0;
|
||||
//#10000;
|
||||
forever begin
|
||||
#9985 rst = ~rst;
|
||||
#5 rst = ~rst;
|
||||
end
|
||||
end
|
||||
|
||||
logic nrst;
|
||||
assign nrst = ~rst;
|
||||
|
||||
logic rst_once;
|
||||
initial begin
|
||||
#0 rst_once = 1'b0;
|
||||
#10.2 rst_once = 1'b1;
|
||||
#5 rst_once = 1'b0;
|
||||
end
|
||||
|
||||
logic nrst_once;
|
||||
assign nrst_once = ~rst_once;
|
||||
|
||||
logic [31:0] DerivedClocks;
|
||||
clk_divider #(
|
||||
.WIDTH( 32 )
|
||||
) cd1 (
|
||||
.clk( clk200 ),
|
||||
.nrst( nrst_once ),
|
||||
.ena( 1'b1 ),
|
||||
.out( DerivedClocks[31:0] )
|
||||
);
|
||||
|
||||
logic [31:0] E_DerivedClocks;
|
||||
edge_detect ed1[31:0] (
|
||||
.clk( {32{clk200}} ),
|
||||
.nrst( {32{nrst_once}} ),
|
||||
.in( DerivedClocks[31:0] ),
|
||||
.rising( E_DerivedClocks[31:0] ),
|
||||
.falling( ),
|
||||
.both( )
|
||||
);
|
||||
|
||||
logic [15:0] RandomNumber1;
|
||||
c_rand rng1 (
|
||||
.clk(clk200),
|
||||
.rst(rst_once),
|
||||
.reseed(1'b0),
|
||||
.seed_val(DerivedClocks[31:0]),
|
||||
.out( RandomNumber1[15:0] )
|
||||
);
|
||||
|
||||
logic start;
|
||||
initial begin
|
||||
#0 start = 1'b0;
|
||||
#100 start = 1'b1;
|
||||
#20 start = 1'b0;
|
||||
end
|
||||
|
||||
// Module under test ==========================================================
|
||||
|
||||
`define WIDTH_W 3
|
||||
`define WIDTH (2**`WIDTH_W)
|
||||
|
||||
logic [`WIDTH-1:0] pos;
|
||||
bin2pos #(
|
||||
.BIN_WIDTH( `WIDTH_W )
|
||||
) BP1 (
|
||||
.bin( RandomNumber1[`WIDTH_W-1:0] ),
|
||||
.pos( pos[`WIDTH-1:0] )
|
||||
);
|
||||
|
||||
round_robin_performance_enc #(
|
||||
.WIDTH( `WIDTH )
|
||||
) RE1 (
|
||||
.clk( clk200 ),
|
||||
.nrst( nrst_once ),
|
||||
.id( RandomNumber1[`WIDTH-1:0] ), //pos[`WIDTH-1:0] ),
|
||||
.od_valid( ),
|
||||
.od_filt( ),
|
||||
.od_bin( )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user