如何在SystemVerilog中用移位运算符实现部分选择?含替代方案
一、使用移位运算符实现
1. 先计算关键参数
首先确定目标位段的宽度:
int width = abs(i - j) + 1; // 位段的总位数
2. 分场景处理
场景1:i ≥ j(正向选择,左到右高位到低位)
此时memword[i:j]取索引i到j的连续位(i在左,位权更高),用右移+掩码实现:
mem2 = (memword >> j) & ((1 << width) - 1);
原理:
memword >> j:将memword逻辑右移j位,把目标位段的最低位(memword[j])对齐到结果的第0位;((1 << width) - 1):生成width位的全1掩码,与移位结果做与运算,截断出目标width位的位段,完全等价于memword[i:j]的数值。
场景2:i < j(反向选择,左到右低位到高位)
此时memword[i:j]取索引i到j的连续位(i在左,j在右,位权逐渐降低),需先反转位序再处理:
logic [8:0] memword_rev; logic [width-1:0] temp; memword_rev = {<<{memword}}; // 反转memword位序,变为[8:0](原memword[0]对应新索引8) temp = (memword_rev >> (8 - j)) & ((1 << width) - 1); mem2 = {<<{temp}}; // 反转temp还原原位序
原理:
- 反转后,原
memword[i:j]对应反转向量的memword_rev[8-j : 8-i],此时满足8-j ≤8-i,可复用场景1的移位逻辑; - 最后反转temp,还原原
memword[i:j]的位序和数值。
二、更通用的替代实现(适合编译器优化)
如果移位实现过于繁琐,推荐逐位循环赋值,逻辑直观且支持所有索引组合,编译器可直接展开优化:
logic [width-1:0] mem2; int k; always_comb begin for(k = 0; k < width; k++) begin if(i >= j) begin mem2[k] = memword[i - k]; // 正向选择:从i到j依次赋值给mem2高位到低位 end else begin mem2[k] = memword[i + k]; // 反向选择:从i到j依次赋值给mem2高位到低位 end end end
三、替换示例代码
将原示例中的部分选择语句替换后,完整代码如下:
logic [0:8] memword; logic [width-1:0] mem2; int width, i, j; always @(posedge clk) begin width = abs(i - j) + 1; // 生成等价于memword[i:j]的临时值 logic [width-1:0] temp_val; int k; for(k=0; k<width; k++) begin if(i >=j) temp_val[k] = memword[i -k]; else temp_val[k] = memword[i +k]; end if(temp_val) begin mem2 = temp_val; end end
内容的提问来源于stack exchange,提问作者Subramanya Krishna
相关产品推荐
相关产品推荐

