【数字IC】基于全并行排序的32个8位无符号数的排序逻辑

基于全并行排序的32个8位无符号数的排序逻辑

1.设计功能与要求

在这里插入图片描述

2.算法原理

本设计采用 全并行排序 算法,其基本思想是将输入序列中一个数据与其他所有数据进行比较并统计得分,得分累积越高代表该数据的数值越大。

得分规则

输入序列中的一个数据A与其他所有数据进行比较,在某一次与数据B的比较中,当:

  • 数据A > 数据B,则数据A得1分
  • 数据A < 数据B,则数据A得0分
  • 数据A == 数据B
    • 若数据A的索引小于数据B,则数据A得1分
    • 若数据A的索引大于数据B,则数据A得0分

以8个数据序列{98, 23, 34, 53, 23, 64, 26, 78}的排序为例,根据上述得分规则可以得到列表如下,其中每行为要与其他数值比较的数值,每列代表被比较的数值:
在这里插入图片描述

全并行排序算法的第一步为将所有数据与其他数据进行比较并得到得分列表,第二步将所有得分累积获得总得分,第三步以总得分为索引得到输出序列。

综上所述,我们明确了全并行排序算法的原理与步骤,下面将进行RTL实现。

3.RTL实现

根据第2小节中的描述,将全并行排序电路逻辑也分为统计比较得分、得分累加、输出排序三个流水阶段。

3.1 第一阶段:统计比较得分

根据题目要求,输入32个8位无符号数是从32个8位输入端口输入的,但是为了方便在generate块中使用for循环,使用din来存放din_31到din_0。

    wire [7:0] din [31:0]; // 存放输入数据
    // input data assign
    assign {din[31],din[30],din[29],din[28],din[27],din[26],din[25],din[24],
            din[23],din[22],din[21],din[20],din[19],din[18],din[17],din[16],
            din[15],din[14],din[13],din[12],din[11],din[10],din[9],din[8],
            din[7],din[6],din[5],din[4],din[3],din[2],din[1],din[0]
        } = {din_31,din_30,din_29,din_28,din_27,din_26,din_25,din_24,
            din_23,din_22,din_21,din_20,din_19,din_18,din_17,din_16,
            din_15,din_14,din_13,din_12,din_11,din_10,din_9,din_8,
            din_7,din_6,din_5,din_4,din_3,din_2,din_1,din_0};

在第一级中使用din_pipe1寄存din信号用于第二级的再次寄存从而保证第三级输出重排。使用flag_pipe1用于存放比较之后的得分,用于第二级得分累加。使用valid_pipe1、valid_sum1_pipe1和valid_sum_pipe1的组合来判断第一级是否比较完毕。

    reg [7:0] din_pipe1 [31:0]; // 寄存输入数据
    reg [5:0] flag_pipe1 [31:0][31:0]; // 2D表格,统计比较分值
    reg valid_pipe1 [31:0][31:0]; // 和后续valid_sum1_pipe1、valid_sum_pipe1判断第一阶段是否完成
    wire valid_sum1_pipe1 [31:0];
    wire valid_sum_pipe1;
    genvar i,j;

    // compare parallel
    generate
        for (j = 0; j<32; j=j+1) begin
            assign valid_sum1_pipe1[j] = &{valid_pipe1[j][0],valid_pipe1[j][1],valid_pipe1[j][2],valid_pipe1[j][3],valid_pipe1[j][4],valid_pipe1[j][5],valid_pipe1[j][6],valid_pipe1[j][7],
                                           valid_pipe1[j][8],valid_pipe1[j][9],valid_pipe1[j][10],valid_pipe1[j][11],valid_pipe1[j][12],valid_pipe1[j][13],valid_pipe1[j][14],valid_pipe1[j][15],
                                           valid_pipe1[j][16],valid_pipe1[j][17],valid_pipe1[j][18],valid_pipe1[j][19],valid_pipe1[j][20],valid_pipe1[j][21],valid_pipe1[j][22],valid_pipe1[j][23],
                                           valid_pipe1[j][24],valid_pipe1[j][25],valid_pipe1[j][26],valid_pipe1[j][27],valid_pipe1[j][28],valid_pipe1[j][29],valid_pipe1[j][30],valid_pipe1[j][31]};
        end
    endgenerate

    assign valid_sum_pipe1 = &{valid_sum1_pipe1[0],valid_sum1_pipe1[1],valid_sum1_pipe1[2],valid_sum1_pipe1[3],valid_sum1_pipe1[4],valid_sum1_pipe1[5],valid_sum1_pipe1[6],valid_sum1_pipe1[7],
                               valid_sum1_pipe1[8],valid_sum1_pipe1[9],valid_sum1_pipe1[10],valid_sum1_pipe1[11],valid_sum1_pipe1[12],valid_sum1_pipe1[13],valid_sum1_pipe1[14],valid_sum1_pipe1[15],
                               valid_sum1_pipe1[16],valid_sum1_pipe1[17],valid_sum1_pipe1[18],valid_sum1_pipe1[19],valid_sum1_pipe1[20],valid_sum1_pipe1[21],valid_sum1_pipe1[22],valid_sum1_pipe1[23],
                               valid_sum1_pipe1[24],valid_sum1_pipe1[25],valid_sum1_pipe1[26],valid_sum1_pipe1[27],valid_sum1_pipe1[28],valid_sum1_pipe1[29],valid_sum1_pipe1[30],valid_sum1_pipe1[31]};

    generate
        for (j = 0; j<32; j=j+1) begin:loop_j
            for(i = 0; i<32; i=i+1) begin:loop_i
                always@(posedge	clk or negedge rst_n) begin
                    if(!rst_n) begin
                        valid_pipe1[j][i] <= 0;
                        flag_pipe1[j][i]  <= 0;	
                    end
                    else if(vld_in) begin
                        if(din[j] < din[i]) begin
                            flag_pipe1[j][i] <= 0;
                        end
                        else if(din[j] == din[i]) begin
                            if(j >= i) begin
                                flag_pipe1[j][i] <= 0;
                            end
                            else begin
                                flag_pipe1[j][i] <= 1;
                            end
                        end
                        else begin
                            flag_pipe1[j][i] <= 1;
                        end
                        valid_pipe1[j][i] <= vld_in;
                    end
                    else begin
                        flag_pipe1[j][i] <= 0;
                        valid_pipe1[j][i] <= 0;
                    end
                end
            end

            always @(posedge clk or negedge rst_n) begin
                if (!rst_n) begin
                    din_pipe1[j] <= 0;
                end
                else if (vld_in) begin
                    din_pipe1[j] <= din[j];
                end
                else begin
                    din_pipe1[j] <= 0;
                end
            end
        end
    endgenerate

3.2 第二阶段:得分累加

使用flag_sum_pipe2累积第一级得到的flag_pipe1,从而得到每一个输入数据的得分之和。使用valid_pipe2和valid_sum_pipe2的组合来判断第二级是否完成。

    reg [4:0] flag_sum_pipe2  [31:0]; // 累积得分和
    reg valid_pipe2 [31:0]; // 和后续valid_sum_pipe2判断第二阶段是否完成
    wire valid_sum_pipe2;
    assign valid_sum_pipe2 = &{&valid_pipe2[0 ],&valid_pipe2[1 ],&valid_pipe2[2 ],&valid_pipe2[3 ],&valid_pipe2[4 ],&valid_pipe2[5 ],&valid_pipe2[6 ],&valid_pipe2[7 ],
                               &valid_pipe2[8 ],&valid_pipe2[9 ],&valid_pipe2[10],&valid_pipe2[11],&valid_pipe2[12],&valid_pipe2[13],&valid_pipe2[14],&valid_pipe2[15],
                               &valid_pipe2[16],&valid_pipe2[17],&valid_pipe2[18],&valid_pipe2[19],&valid_pipe2[20],&valid_pipe2[21],&valid_pipe2[22],&valid_pipe2[23],
                               &valid_pipe2[24],&valid_pipe2[25],&valid_pipe2[26],&valid_pipe2[27],&valid_pipe2[28],&valid_pipe2[29],&valid_pipe2[30],&valid_pipe2[31]} == 1'b1;
    
    generate
        for (j = 0; j<32; j=j+1) begin
            always @(posedge clk or negedge rst_n) begin
                if (!rst_n) begin
                    valid_pipe2[j] <= 0;
                    flag_sum_pipe2[j] <= 0;
                    din_pipe2[j] <= 0;
                end
                else if (valid_sum_pipe1) begin
                    valid_pipe2[j] <= valid_sum_pipe1;
                    flag_sum_pipe2[j] <= flag_pipe1[j][0 ] + flag_pipe1[j][1 ] + flag_pipe1[j][2 ] + flag_pipe1[j][3 ] + flag_pipe1[j][4 ] + flag_pipe1[j][5 ] + flag_pipe1[j][6 ] + flag_pipe1[j][7 ] + 
                                         flag_pipe1[j][8 ] + flag_pipe1[j][9 ] + flag_pipe1[j][10] + flag_pipe1[j][11] + flag_pipe1[j][12] + flag_pipe1[j][13] + flag_pipe1[j][14] + flag_pipe1[j][15] + 
                                         flag_pipe1[j][16] + flag_pipe1[j][17] + flag_pipe1[j][18] + flag_pipe1[j][19] + flag_pipe1[j][20] + flag_pipe1[j][21] + flag_pipe1[j][22] + flag_pipe1[j][23] + 
                                         flag_pipe1[j][24] + flag_pipe1[j][25] + flag_pipe1[j][26] + flag_pipe1[j][27] + flag_pipe1[j][28] + flag_pipe1[j][29] + flag_pipe1[j][30] + flag_pipe1[j][31] ;
                    din_pipe2[j] <= din_pipe1[j];
                end 
                else begin
                    valid_pipe2[j] <= 0;
                    flag_sum_pipe2[j] <= 0;
                    din_pipe2[j] <= 0;
                end
            end
        end
    endgenerate

3.3 第三阶段:输出排序

使用din_pipe3存放使用flag_sum_pipe2进行索引重排后的输出数据。

    reg [7:0] din_pipe3 [31:0]; // 重排后的输出数据

    generate
        always @(posedge clk or negedge rst_n) begin
            if (!rst_n) begin
                vld_out <= 0;
                {din_pipe3[0 ],din_pipe3[1 ],din_pipe3[2 ],din_pipe3[3 ],din_pipe3[4 ],din_pipe3[5 ],din_pipe3[6 ],din_pipe3[7 ],
                 din_pipe3[8 ],din_pipe3[9 ],din_pipe3[10],din_pipe3[11],din_pipe3[12],din_pipe3[13],din_pipe3[14],din_pipe3[15],
                 din_pipe3[16],din_pipe3[17],din_pipe3[18],din_pipe3[19],din_pipe3[20],din_pipe3[21],din_pipe3[22],din_pipe3[23],
                 din_pipe3[24],din_pipe3[25],din_pipe3[26],din_pipe3[27],din_pipe3[28],din_pipe3[29],din_pipe3[30],din_pipe3[31]} <= 0;
            end
            else if (valid_sum_pipe2) begin
                vld_out <= 1;
                {din_pipe3[flag_sum_pipe2[0 ]],din_pipe3[flag_sum_pipe2[1 ]],din_pipe3[flag_sum_pipe2[2 ]],din_pipe3[flag_sum_pipe2[3 ]],din_pipe3[flag_sum_pipe2[4 ]],din_pipe3[flag_sum_pipe2[5 ]],din_pipe3[flag_sum_pipe2[6 ]],din_pipe3[flag_sum_pipe2[7 ]],
                 din_pipe3[flag_sum_pipe2[8 ]],din_pipe3[flag_sum_pipe2[9 ]],din_pipe3[flag_sum_pipe2[10]],din_pipe3[flag_sum_pipe2[11]],din_pipe3[flag_sum_pipe2[12]],din_pipe3[flag_sum_pipe2[13]],din_pipe3[flag_sum_pipe2[14]],din_pipe3[flag_sum_pipe2[15]],
                 din_pipe3[flag_sum_pipe2[16]],din_pipe3[flag_sum_pipe2[17]],din_pipe3[flag_sum_pipe2[18]],din_pipe3[flag_sum_pipe2[19]],din_pipe3[flag_sum_pipe2[20]],din_pipe3[flag_sum_pipe2[21]],din_pipe3[flag_sum_pipe2[22]],din_pipe3[flag_sum_pipe2[23]],
                 din_pipe3[flag_sum_pipe2[24]],din_pipe3[flag_sum_pipe2[25]],din_pipe3[flag_sum_pipe2[26]],din_pipe3[flag_sum_pipe2[27]],din_pipe3[flag_sum_pipe2[28]],din_pipe3[flag_sum_pipe2[29]],din_pipe3[flag_sum_pipe2[30]],din_pipe3[flag_sum_pipe2[31]]
                } <= {din_pipe2[0 ],din_pipe2[1 ],din_pipe2[2 ],din_pipe2[3 ],din_pipe2[4 ],din_pipe2[5 ],din_pipe2[6 ],din_pipe2[7 ],
                      din_pipe2[8 ],din_pipe2[9 ],din_pipe2[10],din_pipe2[11],din_pipe2[12],din_pipe2[13],din_pipe2[14],din_pipe2[15],
                      din_pipe2[16],din_pipe2[17],din_pipe2[18],din_pipe2[19],din_pipe2[20],din_pipe2[21],din_pipe2[22],din_pipe2[23],
                      din_pipe2[24],din_pipe2[25],din_pipe2[26],din_pipe2[27],din_pipe2[28],din_pipe2[29],din_pipe2[30],din_pipe2[31]};
            end
            else begin
                vld_out <= 0;
                {din_pipe3[0 ],din_pipe3[1 ],din_pipe3[2 ],din_pipe3[3 ],din_pipe3[4 ],din_pipe3[5 ],din_pipe3[6 ],din_pipe3[7 ],
                 din_pipe3[8 ],din_pipe3[9 ],din_pipe3[10],din_pipe3[11],din_pipe3[12],din_pipe3[13],din_pipe3[14],din_pipe3[15],
                 din_pipe3[16],din_pipe3[17],din_pipe3[18],din_pipe3[19],din_pipe3[20],din_pipe3[21],din_pipe3[22],din_pipe3[23],
                 din_pipe3[24],din_pipe3[25],din_pipe3[26],din_pipe3[27],din_pipe3[28],din_pipe3[29],din_pipe3[30],din_pipe3[31]} <= 0;
            end
        end
    endgenerate

最后将din_pipe3的数值分别赋值给dout_0-dout_31满足输出端口要求。

Vivado RTL analysis结果如下图所示,可见32个8bit数据对比消耗逻辑资源较多,但符合设计预期。
在这里插入图片描述

4.RTL仿真结果

测试用例1:输入32个数据依次为:31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 2, 2, 4, 4, 4, 4, 8, 16, 8, 16, 32, 32, 0, 10, 20, 30;输出32个数据依次为:0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 7, 8, 8, 9, 10, 11, 13, 15, 16, 16, 17, 19, 20, 21, 23, 25, 27, 29, 30, 31, 32, 32。随后又通过$random系统函数生成随机测试向量。
输入数据仿真波形如下:
在这里插入图片描述

输出数据仿真波形如下:
在这里插入图片描述

从波形可以看出本设计功能正确。

参考与致谢

数据排序(含verilog源码)

写在最后

2025年1月上旬总算结束了研一上学期繁忙的课程,总算有时间整理总结UCAS《高等数字集成电路分析与设计》课程中老师所布置的作业题,作为老师上课来不及仔细讲解内容的补充,也作为以后自己复习的参考。笔者作为初学者难免出现错误,请读者多多批评指正,也希望看到本博客的学弟学妹多多思考、不要盲目抄袭。

源码

verilog源码开源在:lionelZhaowy/Digital-IC-Analysis-and-Design

作者:LionelZhao 欢迎转载,主动输出、与人分享是进步的源泉!!!

转载请保留原文地址:https://blog.csdn.net/LionelZhao/article/details/145285614?spm=1001.2014.3001.5501

创作不易,如果觉得本文对您有帮助欢迎读者客官多多打赏!!!
在这里插入图片描述

工程文件请在海鲜市场购买。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值