barrel_shift

Posted yuandonghua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了barrel_shift相关的知识,希望对你有一定的参考价值。

barrel_shift的目的就是在一个bus中根据idx动态选择一部分数据输出如:

input    din  [256*dw-1:0];
input    idx  [8-1:0];// 0~132
output   dout [124*dw-1:0];

上面就要求从256的数据单元中选择124个数据单元输出,输出的起始位置为idx(取值只能爱0~132,如果取值超过132,比如是140,那么140~255不够124个数据,输出中会出现重复的数据)

数据选择其实就是mux,不过这里是要选择出多个数据(124个),需要按段进行选择;通过根据idx的译码选择出124+2^n-1个数据(必须保证选择出的数据包含了需要的124个数据,2^n-1是在找选择数据段的起始)

定义一些中间连线:

reg   [dw-1:0]s0[124];// widht = 124 + 2^0 - 1
reg   [dw-1:0]s1[125];// widht = 124 + 2^1 - 1
reg   [dw-1:0]s2[127];// widht = 124 + 2^2 - 1
reg   [dw-1:0]s3[131];// widht = 124 + 2^3 - 1
reg   [dw-1:0]s4[139];// widht = 124 + 2^4 - 1
reg   [dw-1:0]s5[155];// widht = 124 + 2^5 - 1
reg   [dw-1:0]s6[187];// widht = 124 + 2^6 - 1
reg   [dw-1:0]s7[251];// widht = 124 + 2^7 - 1
reg   [dw-1:0]s8[256];//input width

首先需要对输入的数据进行分块,以dw位宽为一个块,用二位数组缓存起来。

generate
for(i=0;i<256;i=i+1)begin:REFORM_INPUT
    always@(*)begin
         s8[i][0+:dw] = din[i*dw +: dw];
    end
end
endgenerate

先开始进行idx的最高位进行译码,将din的数据分为两部分,输出的数据的起点就会在这两部分数据中,假设起点在前一部分,即起点为din[0*dw],din[1*dw]....din[127*dw],如果起点是din[127*dw]那么输出数据会是din[127*dw:(127+124-1)*dw],这部分数据包括了后半部分是数据。考虑完备,根据idx[7]的选择,需要输出128+124-1个数据(使用的2分法译码)

generate
for(i=0;i<251;i=i+1)begin:SEL7
    if(i<128)begin
        always@(*)begin
            if(idx[7]==1b0)begin
                s7[i] = s8[i];
            end else begin
                s7[i] = s8[i+128];
end
end end else begin always@(*)begin s7[i] = s8[i];//只有在idx[7]==1‘b0的时候才有意义,idx[7]==1‘b1的时候会出现一部分重复数据。 end end end endgenerate

根据判断idx[7]从256中选择出251个数据,接下来要判断idx[6]选择出124 + 2^6 -1 = 187个数据

generate
for(i=0;i<187;i=i+1)begin:SEL6
    always@(*)begin
        if(idx[6]==1b0)begin
            s6[i] = s7[i];
        end else begin
            s6[i] = s7[i+64];
        end
    end
end
endgenerate

接下来的每判断idx[k]就可以去除2^k个数据,最后只剩下124个数据

generate
for(i=0;i<155;i=i+1)begin:SEL5
    always@(*)begin
        if(idx[5]==1b0)begin
            s5[i] = s6[i];
        end else begin
            s5[i] = s6[i+32];
        end
    end
end
endgenerate

generate
for(i=0;i<139;i=i+1)begin:SEL4
    always@(*)begin
        if(idx[4]==1b0)begin
            s4[i] = s5[i];
        end else begin
            s4[i] = s5[i+16];
        end
    end
end
endgenerate

generate
for(i=0;i<131;i=i+1)begin:SEL3
    always@(*)begin
        if(idx[3]==1b0)begin
            s3[i] = s4[i];
        end else begin
            s3[i] = s4[i+8];
        end
    end
end
endgenerate

generate
for(i=0;i<127;i=i+1)begin:SEL2
    always@(*)begin
        if(idx[2]==1b0)begin
            s2[i] = s3[i];
        end else begin
            s2[i] = s3[i+4];
        end
    end
end
endgenerate

generate
for(i=0;i<125;i=i+1)begin:SEL1
    always@(*)begin
        if(idx[1]==1b0)begin
            s1[i] = s2[i];
        end else begin
            s1[i] = s2[i+2];
        end
    end
end
endgenerate

generate
for(i=0;i<124;i=i+1)begin:SEL0
    always@(*)begin
        if(idx[0]==1b0)begin
            s0[i] = s1[i];
        end else begin
            s0[i] = s1[i+1];
        end
    end
end
endgenerate

最后将s0数组中的数据转成输出数据的格式:

generate
for(i=0;i<124;i=i+1)begin:GET_OUT
    always@(*)begin
        dout[i*dw +: dw] = s0[i];
    end
end
endgenerate

 

berral shift使用场景,比如两个128的数据中选择124个数据输出就可以将两个128的数据拼起来,然后根据idx输出124个数据。


以上是关于barrel_shift的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器

VSCode自定义代码片段——声明函数