求助:Verilog生成块中实现一次性变量索引的实例化代码修正
基于NI_TYPE参数正确实例化模块并分配索引
问题场景
已定义如下参数:
parameter int NI_TYPE[NUM_ROW][NUM_COL] = '{ '{0, 1, 2}, '{2, 1, 2}, '{2, 1, 0} };
需要根据NI_TYPE的值实例化axi_grid_mni(值为2)和axi_grid_sni(值为1)模块,要求mni_index和sni_index为静态一次性分配的索引,原生成块代码因Verilog生成块的并行执行逻辑无法实现预期的索引递增效果,现提供修正代码如下:
修正后的代码
// 预计算每种类型的实例总数 localparam int MNI_INSTANCE_COUNT = count_matching_type(NI_TYPE, 2); localparam int SNI_INSTANCE_COUNT = count_matching_type(NI_TYPE, 1); // 统计指定类型元素数量的函数 function int count_matching_type(int arr[NUM_ROW][NUM_COL], int target_val); int count = 0; for (int r = 0; r < NUM_ROW; r++) begin for (int c = 0; c < NUM_COL; c++) begin if (arr[r][c] == target_val) count++; end end count_matching_type = count; endfunction // 生成每个位置对应的MNI索引映射表 localparam int MNI_INDEX_MAP[NUM_ROW][NUM_COL] = generate_index_map(NI_TYPE, 2); // 生成每个位置对应的SNI索引映射表 localparam int SNI_INDEX_MAP[NUM_ROW][NUM_COL] = generate_index_map(NI_TYPE, 1); // 生成索引映射的函数 function int generate_index_map(int arr[NUM_ROW][NUM_COL], int target_val); int current_idx = 0; for (int r = 0; r < NUM_ROW; r++) begin for (int c = 0; c < NUM_COL; c++) begin if (arr[r][c] == target_val) begin generate_index_map[r][c] = current_idx; current_idx++; end else begin generate_index_map[r][c] = -1; // 标记非目标类型位置 end end end endfunction // 模块实例化生成块 genvar row, col; for (row = 0; row < NUM_ROW; row++) begin : gen_row for (col = 0; col < NUM_COL; col++) begin : gen_col if (NI_TYPE[row][col] == 2) begin : gen_mni axi_grid_mni #( .req_t (mni_req_t), .resp_t (mni_resp_t) ) u_axi_grid_mni ( .clk_i (clk_i), .arst_ni (arst_ni), .req_o (mni_req_o[MNI_INDEX_MAP[row][col]]), .resp_i (mni_resp_i[MNI_INDEX_MAP[row][col]]) ); end else if (NI_TYPE[row][col] == 1) begin : gen_sni axi_grid_sni #( .req_t (sni_req_t), .resp_t (sni_resp_t) ) u_axi_grid_sni ( .clk_i (clk_i), .arst_ni (arst_ni), .req_o (sni_req_i[SNI_INDEX_MAP[row][col]]), .resp_i (sni_resp_o[SNI_INDEX_MAP[row][col]]) ); end // 类型为0的位置无需实例化模块 end end
关键说明
- 原代码问题:Verilog的
genvar是编译阶段的静态变量,生成块是并行展开而非顺序执行的,直接在生成块中对mni_index/sni_index自增会导致索引分配混乱,无法保证顺序和唯一性。 - 修正核心:通过编译阶段执行的函数,预先遍历
NI_TYPE计算出每个位置对应的索引值,生成静态索引映射表,生成块仅需直接引用这些预计算的索引即可,确保索引一次性静态分配,无运行时修改。 - 额外优势:预计算的实例总数可用于后续总线信号的宽度定义(如
mni_req_o的宽度可设为MNI_INSTANCE_COUNT),提升代码的可维护性。
内容的提问来源于stack exchange,提问作者Foez Ahmed
相关产品推荐
相关产品推荐

