// Copyright © 2019-2023 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. `include "VX_platform.vh" `TRACING_OFF module VX_popcount63( input wire [5:0] data_in, output wire [2:0] data_out ); reg [2:0] sum; always @(*) begin case (data_in) 6'd0: sum=3'd0; 6'd1: sum=3'd1; 6'd2: sum=3'd1; 6'd3: sum=3'd2; 6'd4: sum=3'd1; 6'd5: sum=3'd2; 6'd6: sum=3'd2; 6'd7: sum=3'd3; 6'd8: sum=3'd1; 6'd9: sum=3'd2; 6'd10: sum=3'd2; 6'd11: sum=3'd3; 6'd12: sum=3'd2; 6'd13: sum=3'd3; 6'd14: sum=3'd3; 6'd15: sum=3'd4; 6'd16: sum=3'd1; 6'd17: sum=3'd2; 6'd18: sum=3'd2; 6'd19: sum=3'd3; 6'd20: sum=3'd2; 6'd21: sum=3'd3; 6'd22: sum=3'd3; 6'd23: sum=3'd4; 6'd24: sum=3'd2; 6'd25: sum=3'd3; 6'd26: sum=3'd3; 6'd27: sum=3'd4; 6'd28: sum=3'd3; 6'd29: sum=3'd4; 6'd30: sum=3'd4; 6'd31: sum=3'd5; 6'd32: sum=3'd1; 6'd33: sum=3'd2; 6'd34: sum=3'd2; 6'd35: sum=3'd3; 6'd36: sum=3'd2; 6'd37: sum=3'd3; 6'd38: sum=3'd3; 6'd39: sum=3'd4; 6'd40: sum=3'd2; 6'd41: sum=3'd3; 6'd42: sum=3'd3; 6'd43: sum=3'd4; 6'd44: sum=3'd3; 6'd45: sum=3'd4; 6'd46: sum=3'd4; 6'd47: sum=3'd5; 6'd48: sum=3'd2; 6'd49: sum=3'd3; 6'd50: sum=3'd3; 6'd51: sum=3'd4; 6'd52: sum=3'd3; 6'd53: sum=3'd4; 6'd54: sum=3'd4; 6'd55: sum=3'd5; 6'd56: sum=3'd3; 6'd57: sum=3'd4; 6'd58: sum=3'd4; 6'd59: sum=3'd5; 6'd60: sum=3'd4; 6'd61: sum=3'd5; 6'd62: sum=3'd5; 6'd63: sum=3'd6; endcase end assign data_out = sum; endmodule module VX_popcount32( input wire [2:0] data_in, output wire [1:0] data_out ); reg [1:0] sum; always @(*) begin case (data_in) 3'd0: sum=2'd0; 3'd1: sum=2'd1; 3'd2: sum=2'd1; 3'd3: sum=2'd2; 3'd4: sum=2'd1; 3'd5: sum=2'd2; 3'd6: sum=2'd2; 3'd7: sum=2'd3; endcase end assign data_out = sum; endmodule module VX_sum33( input wire [2:0] data_in1, input wire [2:0] data_in2, output wire [3:0] data_out ); reg [3:0] sum; always @(*) begin case ({data_in1, data_in2}) 6'd0: sum=4'd0; 6'd1: sum=4'd1; 6'd2: sum=4'd2; 6'd3: sum=4'd3; 6'd4: sum=4'd4; 6'd5: sum=4'd5; 6'd6: sum=4'd6; 6'd7: sum=4'd7; 6'd8: sum=4'd1; 6'd9: sum=4'd2; 6'd10: sum=4'd3; 6'd11: sum=4'd4; 6'd12: sum=4'd5; 6'd13: sum=4'd6; 6'd14: sum=4'd7; 6'd15: sum=4'd8; 6'd16: sum=4'd2; 6'd17: sum=4'd3; 6'd18: sum=4'd4; 6'd19: sum=4'd5; 6'd20: sum=4'd6; 6'd21: sum=4'd7; 6'd22: sum=4'd8; 6'd23: sum=4'd9; 6'd24: sum=4'd3; 6'd25: sum=4'd4; 6'd26: sum=4'd5; 6'd27: sum=4'd6; 6'd28: sum=4'd7; 6'd29: sum=4'd8; 6'd30: sum=4'd9; 6'd31: sum=4'd10; 6'd32: sum=4'd4; 6'd33: sum=4'd5; 6'd34: sum=4'd6; 6'd35: sum=4'd7; 6'd36: sum=4'd8; 6'd37: sum=4'd9; 6'd38: sum=4'd10; 6'd39: sum=4'd11; 6'd40: sum=4'd5; 6'd41: sum=4'd6; 6'd42: sum=4'd7; 6'd43: sum=4'd8; 6'd44: sum=4'd9; 6'd45: sum=4'd10; 6'd46: sum=4'd11; 6'd47: sum=4'd12; 6'd48: sum=4'd6; 6'd49: sum=4'd7; 6'd50: sum=4'd8; 6'd51: sum=4'd9; 6'd52: sum=4'd10; 6'd53: sum=4'd11; 6'd54: sum=4'd12; 6'd55: sum=4'd13; 6'd56: sum=4'd7; 6'd57: sum=4'd8; 6'd58: sum=4'd9; 6'd59: sum=4'd10; 6'd60: sum=4'd11; 6'd61: sum=4'd12; 6'd62: sum=4'd13; 6'd63: sum=4'd14; endcase end assign data_out = sum; endmodule module VX_popcount #( parameter MODEL = 1, parameter N = 1, parameter M = `CLOG2(N+1) ) ( input wire [N-1:0] data_in, output wire [M-1:0] data_out ); `UNUSED_PARAM (MODEL) `ifndef SYNTHESIS assign data_out = $countones(data_in); `elsif QUARTUS assign data_out = $countones(data_in); `else if (N == 1) begin assign data_out = data_in; end else if (N <= 3) begin reg [2:0] t_in; wire [1:0] t_out; always @(*) begin t_in = '0; t_in[N-1:0] = data_in; end VX_popcount32 pc32(t_in, t_out); assign data_out = t_out[M-1:0]; end else if (N <= 6) begin reg [5:0] t_in; wire [2:0] t_out; always @(*) begin t_in = '0; t_in[N-1:0] = data_in; end VX_popcount63 pc63(t_in, t_out); assign data_out = t_out[M-1:0]; end else if (N <= 9) begin reg [8:0] t_in; wire [4:0] t1_out; wire [3:0] t2_out; always @(*) begin t_in = '0; t_in[N-1:0] = data_in; end VX_popcount63 pc63(t_in[5:0], t1_out[2:0]); VX_popcount32 pc32(t_in[8:6], t1_out[4:3]); VX_sum33 sum33(t1_out[2:0], {1'b0, t1_out[4:3]}, t2_out); assign data_out = t2_out[M-1:0]; end else if (N <= 12) begin reg [11:0] t_in; wire [5:0] t1_out; wire [3:0] t2_out; always @(*) begin t_in = '0; t_in[N-1:0] = data_in; end VX_popcount63 pc63a(t_in[5:0], t1_out[2:0]); VX_popcount63 pc63b(t_in[11:6], t1_out[5:3]); VX_sum33 sum33(t1_out[2:0], t1_out[5:3], t2_out); assign data_out = t2_out[M-1:0]; end else if (N <= 18) begin reg [17:0] t_in; wire [8:0] t1_out; wire [5:0] t2_out; always @(*) begin t_in = '0; t_in[N-1:0] = data_in; end VX_popcount63 pc63a(t_in[5:0], t1_out[2:0]); VX_popcount63 pc63b(t_in[11:6], t1_out[5:3]); VX_popcount63 pc63c(t_in[17:12], t1_out[8:6]); VX_popcount32 pc32a({t1_out[0], t1_out[3], t1_out[6]}, t2_out[1:0]); VX_popcount32 pc32b({t1_out[1], t1_out[4], t1_out[7]}, t2_out[3:2]); VX_popcount32 pc32c({t1_out[2], t1_out[5], t1_out[8]}, t2_out[5:4]); assign data_out = {2'b0,t2_out[1:0]} + {1'b0,t2_out[3:2],1'b0} + {t2_out[5:4],2'b0}; end else if (MODEL == 1) begin localparam PN = 1 << `CLOG2(N); localparam LOGPN = `CLOG2(PN); `IGNORE_UNOPTFLAT_BEGIN wire [M-1:0] tmp [LOGPN-1:0][PN-1:0]; `IGNORE_UNOPTFLAT_END for (genvar j = 0; j < LOGPN; ++j) begin localparam D = j + 1; localparam Q = (D < LOGPN) ? (D + 1) : M; for (genvar i = 0; i < (1 << (LOGPN-j-1)); ++i) begin localparam l = i * 2; localparam r = i * 2 + 1; wire [Q-1:0] res; if (j == 0) begin if (r < N) begin assign res = data_in[l] + data_in[r]; end else if (l < N) begin assign res = 2'(data_in[l]); end else begin assign res = 2'b0; end end else begin assign res = D'(tmp[j-1][l]) + D'(tmp[j-1][r]); end assign tmp[j][i] = M'(res); end end assign data_out = tmp[LOGPN-1][0]; end else begin reg [M-1:0] cnt_r; always @(*) begin cnt_r = '0; for (integer i = 0; i < N; ++i) begin cnt_r = cnt_r + M'(data_in[i]); end end assign data_out = cnt_r; end `endif endmodule `TRACING_ON