一、原理
参考博客:<Verilog> 语法技巧:数据位操作_verilog移位操作-CSDN博客
下图是从作者的博客cv过来的一张图,讲的非常的清晰。实现了动态的选择选择数据的位宽,只需要动态的改变base_expr就可以。
二、在s2p的运用
2.1 部分代码
always@(posedge clk or negedge resetn)begin// 以parallel_num是8路为例,此时计数器是 7 8,9,10 , 11,12,13,14 if( (cnt >= parallel_num - 1) && (cnt <= double_parallel_num -2) )beginfor (j = 0; j < parallel_num; j = j + 1) begin// 用循环拼接,把从0到7的寄存器数组的值都放到s2p里面,有个问题就是,第一个fft部件的输入被放到了高位,// 后续给值的时候,需要注意把高位给到第一个fft的输入// 另外,通过计数器的增加,可以从左到右边的读取完 前8个寄存器数组地址的[ 63 : 0] ,[127 : 96] ,[191 : 160].....// s2p_output = {s2p_output, short_fft_buf[j][( (cnt_num - parallel_num) +1)*data_length*2 - 1 : (cnt_num - parallel_num)*data_length*2]};// 这里用(cnt + 1)的原因是计数器从7开始,不 +1 就会出现负数s2p_output = {s2p_output, short_fft_buf[j][( (cnt + 1) - parallel_num)*data_length*2 +: data_length*2]};endend
2.2 报错代码
如果使用下图的方式会显示范围不能是动态的,范围必须是常量,因为引入的计数器是一个变量。
[VRFC 10-1775] range must be bounded by constant expressions
2.3 正确表达
s2p_output = {s2p_output, short_fft_buf[j][( (cnt + 1) - parallel_num)*data_length*2 +: data_length*2]};
上面的代码中,线选部分如下,(cnt+ 1) - parallel_num)*data_length*2 可以根据计算器的变化变化,然后向上选择(+:) 64位。
[( (cnt + 1) - parallel_num)*data_length*2 +: data_length*2]
好处:
1、表达更加简练,不容易出错,例如选择[63: 0],[127 : 64]....,就只需要计算0,64怎么表达出来,不用再计算 63和 127的表达式了。
2、使用情况更广,不会出现上面的报错。