• systemverilog学习 --- 数组操作(二)


    array reduction method

    systemverilog提供的这些方法可以作用于unpacked数组,将整个数组减小到一个值。内建的方法如下:

    sum()返回数组里所有元素的和
    product()返回数组里所有元素的乘积
    and()返回数组元素的与
    or()返回数组中所有元素的或
    xor()返回数组中所有元素的异或
    module fixedsize_array;
    
        //declaration of array's
        int array_1[4];
        int t_sum;
        int t_product;
    
        initial begin
            //array initialization
            array_1 = '{1,2,3,4};
    
            t_sum = array_1.sum();          //t_sum = 1+2+3+4
            $display("Sum of array_a is \t %0d", t_sum);
    
            t_product = array_1.product();  //t_product = 1*2*3*4
            $display("product of array_1 is \t%0d", t_product);
        end
    
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    上面的例子展示了sum()和product的方法,sum是对所有元素求和,而product是对所有的元素求积。
    在这里插入图片描述
    而and,or,和xor方法,都是位操作,将所有的元素值进行按位与,按位或或者按位异或。
    我们也可以使用with操作符,对数组里面的某个元素进行必要的操作。

    module fixedsize_array;
    
        //declaration of array's
        int array_1[4];
        int t_sum;
        int t_product;
    
        initial begin
            //array initialization 
            array_1 = '{1,2,3,4};
            
            t_sum = array_1.sum with (item * 2);
            //t_sum = (1*2) + (2*2) + (3*2) + (4*2)
            $display("Sum of array_1 is \t %0d", t_sum);
    
            t_product = array_1.product with (item+2);
            //t_product = (1+2)*(2+2)*(3+2)*(4+2) = 3*4*5*6
            $display("product of array_1 is \t %0d", t_product);
        end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在上面例子中对数组里面的元素分别进行了乘2和加2的操作。执行结果如下:
    在这里插入图片描述

    array locator method

    数组定位方法对于找到一个数组元素的索引是很有帮助的。这类的方法可以操作unpacked类型的数组和队列。这些方法的返回类型是一个队列。通过一个表达式可以找到数组对应的元素或者相应的索引。因此根据找索引还是找元素,可以分类为element finder和index finder。
    element finder

    find()找到所有符合表达式的元素
    find_first()找到第一个满足表达式的元素
    find_last()找到最后一个满足表达式的元素
    min()找到数组里面最小的元素
    max()找到数组里面最大的元素
    unique()找到数组里面具有唯一值的元素

    ** index_finder**

    find_index找到所有满足表达式元素的索引
    find_first_index()返回满足给定表达式的第一个元素的索引
    find_last_index返回满足给定表达式的最后一个元素的索引
    unique_index()返回具有唯一值的元素的索引
    class packet;
    
        int a;
        int b;
    
        function void display();
            $display("\tValue of a = %0d", a);
            $display("\tValue of b = %0d", b);
        endfunction
    
    endclass
    
    module assoc_array;
    //declaration of array
    packet  assoc_array[*]  ;
    packet  pkt             ;
    int     count           ;
    int     qu[$]           ;
    int     tmp_var         ;
    
    initial begin
        
        pkt = new();
        pkt.a = 8;
        pkt.b = 3;
        assoc_array[2] = pkt;
    
        pkt = new();
        pkt.a = 0;
        pkt.b = 6;
        assoc_array[5] = pkt;
    
        pkt = new();
        pkt.a = 2;
        pkt.b = 6;
        assoc_array[6] = pkt;
    
        pkt = new();
        pkt.a = 1;
        pkt.b = 6;
        assoc_array[9] = pkt;
        //==========================================================================
        //========== Find Index Method ===========
        //==========================================================================
    
        //type-1:returning one matching index
        qu = assoc_array.find_index with (item.a == 'h2);
        count = qu.size();
    
        for(int i=0; i<count; i++)begin
            tmp_var = qu.pop_front();
            $display("Index of Asoc Array for a == 2 is %0d", tmp_var);
        end
    
        //type-2:returning multiple matching index
        qu = assoc_array.find_index with (item.b == 6);
        count = qu.size();
    
        for(int i = 0; i < count; i++)begin
            tmp_var = qu.pop_front();
            $display("Index of Asoc Array for b==6 is %0d", tmp_var);
        end
    
        //type-3:with multiple conditions
        qu = assoc_array.find_index with (item.a == 2 && item.b == 6);
        count = qu.size();
        for(int i = 0; i < count; i++)begin
            tmp_var = qu.pop_front();
            $display("Index of Asoc Array for a == 2,b==6 is %0d", tmp_var);
        end
    
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    在上面的代码中,类packet有两个int类型的变量,以及一个display方法打印成员的变量值。在模块assoc_array内,定义了packet类型的关联数组。声明了packet类句柄,以及int类型的count,tmp_var以及队列qu。
    然后创建了3个类packet的实例,并将其赋值给关联数组元素。最后调用数组的查找方法,这个方法会返回一个队列。然后再使用队列的pop_front()方法取出队列里面的元素,打印出来。执行结果如下:
    在这里插入图片描述

    array iterator

    我们可以查找一个数组中的元素或者索引,但是只能实现分别查找。使用iterator迭代器我们可以同时处理数组中的元素或索引。迭代器的简单理解可以认为是with中的item。

    array_1.find with (item == item.index)
    
    • 1

    返回一个数组元素,它的值就是它的索引。

    array_2.find with (item > item.index)
    
    • 1

    返回的数组元素,它的值比它的索引大。

    module fixedsize_array;
    
        //declaration of array's
        int array_1[6]  ;
        int array_2[6]  ;
        int temp_qu[$]  ;
        int temp_cnt    ;
        int temp_value  ;
    
        initial begin
            //array initialization
            array_1 = '{10,20,2,40,67,5};
            array_2 = '{80,4,2,40,67,5};
    
            //type-1
            temp_qu = array_1.find with (item == item.index);
            temp_cnt = temp_qu.size();
            $display("Index and Elements are same for %0d index's", temp_cnt);
    
            for(int i = 0; i < temp_cnt; i++)begin
                temp_value = temp_qu.pop_front();
                $display("\tsame for value %0d", temp_value);
            end
    
            //type-2
            temp_qu = array_1.find with (item > item.index);
            temp_cnt = temp_qu.size();
            $display("Index and Elements satisfied for %0d index's", temp_cnt);
    
            for(int i = 0; i < temp_cnt; i++)begin
                temp_value = temp_qu.pop_front();
                $display("\t for value %0d", temp_value);
            end
        end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    上例中,item指代数据元素值,item.index则是元素的索引,find返回数据元素。通过item==item.index找到值和索引相等的元素,通过item>item.index找到值大于索引的元素。可见,同时使用了元素和元素索引。执行结果如下:
    在这里插入图片描述

    array slice

    slice切片,对于数组而言,就是数组中连续的元素,而part select片则是选择一个元素的连续bit。

    bit [31:0] data;
    bit [07:0] byte[4];
     
    byte[0] = data[07:0];
    byte[1] = data[15:8];
    byte[2] = data[23:16];
    byte[3] = data[31:24];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如上所示,part select与verilog类似,通过索引选择8bit赋值给byte,对一个元素的单独操作。
    而slice是将多个数组元素进行拆分,拆分成更小的数组,是对数组的操作。

      bit [31:0] packet_type_A [7:0]; //array of 8 elements of width 32bit
      bit [31:0] packet_type_B [1:0]; //array of 2 elements of width 32bit
     
      packet_type_B = packet_type_A[5:4]; //assigning 2 elements of array packet_type_A  to packet_type_B
    
    • 1
    • 2
    • 3
    • 4

    在systemverilog中,提供了更加翻篇的片选方法。
    +:NOTATION

    byte = data[j += k]
    
    • 1

    其中j表示起始位,k表示总的位数。如byte = data[0 +: 8]。则是等价于byte = data[7:0]。
    还可以指定最大的索引,然后通过-:设置其他索引。j依然是起始索引,k在-:依然表示k bit,但其他索引都从起始索引开始递减。如data[7-:8]等价于data[7:0]
    在这里插入图片描述
    需要指出的是,这里的j可以是变量,而k必须是常量。

  • 相关阅读:
    【花雕动手做】有趣好玩的音乐可视化系列项目(31)--LCD1602液晶屏
    android获取RAM、CPU频率、系统版本、CPU核数
    Guitar Pro2023吉他谱作曲和练习工具
    在云时代,我们该如何看待新的开源许可证?
    Android 10 分区存储
    LeetCode 5. 6. 题
    NR PDSCH(六) DL data operation
    【附源码】计算机毕业设计SSM商超销售系统
    3.2 AOP之代理模式
    [附源码]计算机毕业设计springboot农产品销售网站
  • 原文地址:https://blog.csdn.net/weixin_45614076/article/details/126504032