You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过原SystemVerilog数组索引从转换后数组获取可综合对应数据?

问题:基于原数组索引规则访问转换后的固定位宽SystemVerilog数组

背景

原数组定义(元素位宽和数量可变):

reg [49:0] wvu[0:63] = {
    50'b00001111111101100111101111101010000010000000110011,
    50'b00000000000000000000000000000000000000000000000000,
    50'b00000000000001000000100100011111110001101001111010,
    //...
    50'b01111111111111111111111111111111011101111111111111
};

为避免修改位宽,转换为固定32位宽的数组(两者所有元素拼接后得到的总寄存器完全一致):

reg [31:0] wvu_prime [0:100] = {
    32'b00001111111101100111101111101010,
    32'b00001000000011001100000000000000,
    32'b00000000000000000000000000000000,
    32'b00000000000000000100000010010001,
    32'b11111100011010011110100000000000,
    //...
    32'b00000000000000011111111111111111,
    32'b11111111111111011101111111111111
};

需求:通过原数组的wvu[x][y:z]索引规则,从wvu_prime中获取对应数据,且实现方案可综合。

解决方案

核心思路是将原数组的索引转换为全局位位置,再映射到转换后数组的索引和位位置,最终通过组合逻辑拼接数据。

1. 定义参数(编译时常量)

parameter ORIG_WIDTH = 50;    // 原数组元素位宽
parameter ORIG_DEPTH = 64;    // 原数组元素个数
parameter PRIME_WIDTH = 32;   // 转换后数组元素位宽
localparam TOTAL_BITS = ORIG_DEPTH * ORIG_WIDTH;
localparam PRIME_DEPTH = (TOTAL_BITS + PRIME_WIDTH - 1) / PRIME_WIDTH;  // 向上取整计算转换后数组深度

2. 索引映射逻辑

对于原数组的wvu[x][y:z](假设y >= z,即高位到低位):

  • 计算全局位位置:原数组第x个元素的y/z位,对应总寄存器的全局位索引:
    start_w = (ORIG_DEPTH - 1 - x) * ORIG_WIDTH + y;  // 区间高位的全局索引
    end_w = (ORIG_DEPTH - 1 - x) * ORIG_WIDTH + z;    // 区间低位的全局索引
    
  • 映射到转换后数组:将全局位索引转换为wvu_prime的索引和元素内位位置:
    start_p = (TOTAL_BITS - 1 - start_w) / PRIME_WIDTH;  // 转换后数组的起始元素索引
    start_b = PRIME_WIDTH - 1 - ((TOTAL_BITS - 1 - start_w) % PRIME_WIDTH);  // 起始元素内的高位索引
    end_p = (TOTAL_BITS - 1 - end_w) / PRIME_WIDTH;      // 转换后数组的结束元素索引
    end_b = PRIME_WIDTH - 1 - ((TOTAL_BITS - 1 - end_w) % PRIME_WIDTH);      // 结束元素内的低位索引
    

3. 可综合的组合逻辑实现

通过always @*块实现数据提取,分两种情况处理:

input  int                   x, y, z;
output reg [ORIG_WIDTH-1:0]  wvu_out;
int                          start_w, end_w;
int                          start_p, start_b;
int                          end_p, end_b;
int                          num_bits;

always @* begin
    num_bits = y - z + 1;
    wvu_out = '0; // 初始化输出
    
    // 计算全局位索引
    start_w = (ORIG_DEPTH - 1 - x) * ORIG_WIDTH + y;
    end_w = (ORIG_DEPTH - 1 - x) * ORIG_WIDTH + z;
    
    // 映射到wvu_prime的索引和位位置
    start_p = (TOTAL_BITS - 1 - start_w) / PRIME_WIDTH;
    start_b = PRIME_WIDTH - 1 - ((TOTAL_BITS - 1 - start_w) % PRIME_WIDTH);
    end_p = (TOTAL_BITS - 1 - end_w) / PRIME_WIDTH;
    end_b = PRIME_WIDTH - 1 - ((TOTAL_BITS - 1 - end_w) % PRIME_WIDTH);
    
    // 情况1:目标区间在同一个wvu_prime元素内
    if (start_p == end_p) begin
        wvu_out[num_bits-1:0] = wvu_prime[start_p][start_b:end_b];
    end
    // 情况2:目标区间跨多个wvu_prime元素
    else begin
        // 提取起始元素的低位部分
        wvu_out[num_bits-1 : num_bits - (start_b + 1)] = wvu_prime[start_p][start_b:0];
        // 提取中间完整的元素
        for (int p = start_p + 1; p < end_p; p++) begin
            int offset = num_bits - (start_b + 1) - (p - start_p - 1)*PRIME_WIDTH;
            wvu_out[offset-1 : offset - PRIME_WIDTH] = wvu_prime[p];
        end
        // 提取结束元素的高位部分
        wvu_out[end_b : 0] = wvu_prime[end_p][31:end_b];
    end
end

4. 合法性检查(可选)

添加断言确保输入索引合法,避免越界:

assert (x >= 0 && x < ORIG_DEPTH) else $error("x out of range: %0d", x);
assert (y >= 0 && y < ORIG_WIDTH) else $error("y out of range: %0d", y);
assert (z >= 0 && z < ORIG_WIDTH) else $error("z out of range: %0d", z);
assert (y >= z) else $error("y must be >= z, got y=%0d, z=%0d", y, z);

关键说明

  • 所有参数必须是编译时常量,确保综合工具能展开逻辑。
  • 跨元素拼接的逻辑会被综合为多路选择器和拼接电路,无动态内存分配,符合可综合要求。
  • 总位宽TOTAL_BITS过大时,避免使用临时总向量存储全部数据,采用逐段拼接方式节省资源。

内容的提问来源于stack exchange,提问作者Roy Meijer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:49:55