Verilog使用组合逻辑求最小值

任务需求:用组合逻辑一拍求出最小值

req_flag:标志系统正在执行的任务数,
time_win:标志每一个任务所用时间值
time_flag:标志各个任务中使用时间最短的任务
在这里插入图片描述

设计思想:

①求最小值,从二进制数的高位到低位依次比较;
②标志位起到屏蔽作用;
例如比较8个四位二进制数:
1000;
1010;
0101;
1100;
0100;
0001;
0000;
1000;
假设有效位标志数req_flag=11110000,即前四个数位有效数据(正在运行的,参与最小值比较),后四位数据无效(不参与最小值比较);
首先,需要用标志位req_flag来屏蔽掉,后四个数;
然后,选出time1(11010000)前四个数最高位中为0的数;
~(~req_flag | time1)=00100000
由于前四个数只判断最高位就可以选出最小值,因此不需要再算。
其次,正常情况下需要从最高位到最低位依次判断选出最终最小值。
最后,如果有两个数相等都是最小值,那么选后面的位最小值。

代码:

`timescale 1ns/1ps
module min(
    input   clk,
    input   rst_n,
    input   [7:0]           req_flag,
    input   [7:0]           time_win1,
    input   [7:0]           time_win2,
    input   [7:0]           time_win3,
    input   [7:0]           time_win4,
    input   [7:0]           time_win5,
    input   [7:0]           time_win6,
    input   [7:0]           time_win7,
    input   [7:0]           time_win8,
    output  [7:0]           time_flag
    );
    
    wire    [7:0]           value_flag1;
    wire    [7:0]           value_flag2;
    wire    [7:0]           value_flag3;
    wire    [7:0]           value_flag4;
    wire    [7:0]           value_flag5;
    wire    [7:0]           value_flag6;
    wire    [7:0]           value_flag7;
    wire    [7:0]           value_flag8;
    wire    [7:0]           win1;
    wire    [7:0]           win2;
    wire    [7:0]           win3;
    wire    [7:0]           win4;
    wire    [7:0]           win5;
    wire    [7:0]           win6;
    wire    [7:0]           win7;
    wire    [7:0]           win8;
    
    assign  win1 = {time_win1[7],time_win2[7],time_win3[7],time_win4[7],time_win5[7],time_win6[7],time_win7[7],time_win8[7]};
    assign  win2 = {time_win1[6],time_win2[6],time_win3[6],time_win4[6],time_win5[6],time_win6[6],time_win7[6],time_win8[6]};
    assign  win3 = {time_win1[5],time_win2[5],time_win3[5],time_win4[5],time_win5[5],time_win6[5],time_win7[5],time_win8[5]};
    assign  win4 = {time_win1[4],time_win2[4],time_win3[4],time_win4[4],time_win5[4],time_win6[4],time_win7[4],time_win8[4]};
    assign  win5 = {time_win1[3],time_win2[3],time_win3[3],time_win4[3],time_win5[3],time_win6[3],time_win7[3],time_win8[3]};
    assign  win6 = {time_win1[2],time_win2[2],time_win3[2],time_win4[2],time_win5[2],time_win6[2],time_win7[2],time_win8[2]};
    assign  win7 = {time_win1[1],time_win2[1],time_win3[1],time_win4[1],time_win5[1],time_win6[1],time_win7[1],time_win8[1]};
    assign  win8 = {time_win1[0],time_win2[0],time_win3[0],time_win4[0],time_win5[0],time_win6[0],time_win7[0],time_win8[0]};
    
    assign  value_flag1 = (((~req_flag   )|win1) == 8'b1111_1111)? seq_flag    : ~((~seq_flag   )|win1);
    assign  value_flag2 = (((~value_flag1)|win2) == 8'b1111_1111)? value_flag1 : ~((~value_flag1)|win2);
    assign  value_flag3 = (((~value_flag2)|win3) == 8'b1111_1111)? value_flag2 : ~((~value_flag2)|win3);
    assign  value_flag4 = (((~value_flag3)|win4) == 8'b1111_1111)? value_flag3 : ~((~value_flag3)|win4);
    assign  value_flag5 = (((~value_flag4)|win5) == 8'b1111_1111)? value_flag4 : ~((~value_flag4)|win5);
    assign  value_flag6 = (((~value_flag5)|win6) == 8'b1111_1111)? value_flag5 : ~((~value_flag5)|win6);
    assign  value_flag7 = (((~value_flag6)|win7) == 8'b1111_1111)? value_flag6 : ~((~value_flag6)|win7);
    assign  value_flag8 = (((~value_flag7)|win8) == 8'b1111_1111)? value_flag7 : ~((~value_flag7)|win8);
    
    generate
    genvar  i;
        for(i=1;i<8;i=i+1)
            begin:min_
            assign time_flag[i] = value_flag8[i]&(~(|value_flag8[i-1:0]));
            end
    endgenerate
    
    assign  time_flag[0] = value_flag8[0];

    
    endmodule

改进后的代码,进行了参数化和generate + for循环

`timescale 1ns/1ps
module min_v2#(
    parameter DATA_NUM    = 8,
    parameter DATA_WIDTH  = 4
    )(
    input   clk,
    input   rst_n,
    input   [DATA_NUM-1:0]              req_flag,
    input   [DATA_NUM*DATA_WIDTH-1:0]   time_win,
    output  [DATA_NUM-1:0]              time_flag
    );
    
    wire    [DATA_WIDTH-1:0]           time_wini [DATA_NUM-1  :0];
    wire    [DATA_NUM-1  :0]           digit     [DATA_WIDTH-1:0];
    wire    [DATA_NUM-1  :0]           value_flag[DATA_WIDTH-1:0];
    
    //将输入时间数值写入数组
    generate
        genvar i;
        for(i=0;i<DATA_NUM;i=i+1)
            begin:time_
                assign time_wini[i] = time_win[DATA_WIDTH*(i+1)-1:DATA_WIDTH*i];
            end
    endgenerate
    //将DATA_NUM个数,按位提取
    generate
        genvar di,ti;
        for(di=0;di<DATA_WIDTH;di=di+1)
            begin:data_i
            for(ti=0;ti<DATA_NUM;ti=ti+1)
                begin:time_i
                    assign digit[di][ti] = time_wini[ti][di];
                end
            end
    endgenerate
    
    //比较有效位
    assign  value_flag[DATA_WIDTH-1] = (((~req_flag )|digit[DATA_WIDTH-1]) == {DATA_NUM{1'b1}})? req_flag:~((~req_flag)|digit[DATA_WIDTH-1]);

    generate
        genvar fi;
        for(fi=0;fi<DATA_WIDTH-1;fi=fi+1)
            begin:flag_i
                assign value_flag[fi] = (((~value_flag[fi+1])|digit[fi])=={DATA_NUM{1'b1}})?value_flag[fi+1]:~((~value_flag[fi+1])|digit[fi]);
            end
    endgenerate
    //如果由两个数都是最小值,那么选后面的
    generate
    genvar  j;
        for(j=1;j<DATA_NUM;j=j+1)
            begin:min_j
            assign time_flag[j] = value_flag[0][j]&(~(|value_flag[0][j-1:0]));
            end
    endgenerate
    
    assign  time_flag[0] = value_flag[0][0];
    
endmodule

分享出来希望对各位同学有帮助,整理不易,点个赞再走呗。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值