bitcount using bit method

unsigned int v; // count bits set in this (32-bit value)
unsigned int c; // store the total here

c = v - ((v >> 1) & 0x55555555);
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
c = ((c >> 4) + c) & 0x0F0F0F0F;
c = ((c >> 8) + c) & 0x00FF00FF;
c = ((c >> 16) + c) & 0x0000FFFF;

Edit: Admittedly it's a bit optimized which makes it harder to read. It's easier to read as:

c = (v & 0x55555555) + ((v >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = (c & 0x0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F);
c = (c & 0x00FF00FF) + ((c >> 8) & 0x00FF00FF);
c = (c & 0x0000FFFF) + ((c >> 16)& 0x0000FFFF);

Each step of those five, adds neighbouring bits together in groups of 1, then 2, then 4 etc. The method is based in divide and conquer.

In the first step we add together bits 0 and 1 and put the result in the two bit segment 0-1, add bits 2 and 3 and put the result in the two-bit segment 2-3 etc...

In the second step we add the two-bits 0-1 and 2-3 together and put the result in four-bit 0-3, add together two-bits 4-5 and 6-7 and put the result in four-bit 4-7 etc...

Example:

So if I have number 395 in binary 0000000110001011 (0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1)
After the first step I have:      0000000101000110 (0+0 0+0 0+0 0+1 1+0 0+0 1+0 1+1) = 00 00 00 01 01 00 01 10
In the second step I have:        0000000100010011 ( 00+00   00+01   01+00   01+10 ) = 0000 0001 0001 0011
In the fourth step I have:        0000000100000100 (   0000+0001       0001+0011   ) = 00000001 00000100
In the last step I have:          0000000000000101 (       00000001+00000100       )
### SystemVerilog 中 Bitcount 的实现 在 SystemVerilog 中,`bitcount` 是指统计某个信号中 `1` 的数量的操作。这种操作通常用于硬件设计中的数据处理场景,比如错误检测、编码解码等领域。 以下是几种常见的 `bitcount` 实现方式: #### 方法一:使用循环结构 通过 `for` 循环逐一检查每一位是否为 `1` 并累加计数器的值[^2]。 ```systemverilog function integer count_ones(input logic [WIDTH-1:0] data); integer i; integer cnt; cnt = 0; // 初始化计数器 for(i = 0; i < WIDTH; i = i + 1) begin if(data[i]) begin cnt = cnt + 1; // 如果当前位为1,则增加计数器 end end return cnt; // 返回最终的结果 endfunction ``` 此方法适用于仿真环境下的函数调用,在综合工具上可能不被支持。 --- #### 方法二:基于组合逻辑的并行计算 为了提高性能,可以采用纯组合逻辑的方式实现 `bitcount` 功能。这种方法适合 FPGA 或 ASIC 设计[^3]。 以下是一个简单的例子,假设输入宽度为 8 位: ```systemverilog module bit_count #(parameter WIDTH=8)( input logic [WIDTH-1:0] data, output logic [$clog2(WIDTH):0] ones_count ); logic [WIDTH/2-1:0][1:0] pairs_sum; logic [WIDTH/4-1:0][2:0] quads_sum; logic [WIDTH/8-1:0][3:0] eights_sum; // Step 1: Add adjacent bits to form sums of two-bit groups. genvar i; generate for(i = 0; i < WIDTH / 2; i++) begin : pair_adder assign pairs_sum[i] = {data[2*i], data[2*i+1]}; end endgenerate // Step 2: Sum the results from step 1 into four-bit groups. generate for(i = 0; i < WIDTH / 4; i++) begin : quad_adder assign quads_sum[i] = pairs_sum[2*i] + pairs_sum[2*i+1]; end endgenerate // Step 3: Continue summing until we get a single result. assign ones_count = $sum(quads_sum); // 使用自定义宏或者进一步展开树形求和 endmodule ``` 上述模块展示了如何利用分层加法器来减少延迟时间,并且能够扩展到任意宽度的数据路径。 --- #### 方法三:借助内置函数 `$onehot` 和 `$onehot0` 某些情况下可以直接利用 SystemVerilog 提供的标准库函数来进行简化判断[^4]。 例如: - `$onehot(x)` 判断是否有且仅有一个位置上的比特为高电平; - `$onehot0(x)` 验证所有比特均为低电平时返回真;否则假。 虽然这些不是严格意义上的 “bitcount”,但在特定条件下非常有用。 --- #### 性能对比分析 | **特性** | **循环方法** | **组合逻辑方法** | |------------------|---------------------------------|-------------------------------| | 综合可行性 | 不推荐 | 推荐 | | 延迟 | 较大 | 小 | | 资源消耗 | 取决于目标平台 | 显著高于顺序版本 | 因此,在实际项目开发过程中需权衡两者优劣再做决定。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值