Verilog参数化二叉树多路复用器:generate块变量修改报错求助
二叉树结构参数化Verilog多路复用器的索引变量问题
我想实现一个带参数化输入数量的Verilog多路复用器模块,目标采用二叉树结构(而非打包输入+选择信号切片的方式)。但遇到了核心问题:需要在内层for循环的每次迭代后修改整数变量P、M、K来正确索引中间连线interm_w,但尝试多次后始终报错。
原代码
module multiplexer_v2(input_data_array, select, output_data); parameter WIDTH = 16; parameter NUMBER_OF_INPUTS = 8; parameter SELECT_WIDTH = $clog2(NUMBER_OF_INPUTS); localparam INTERMEDIATE_WIRES_COUNT = interm_value(SELECT_WIDTH, NUMBER_OF_INPUTS); // 该函数工作正常 input [SELECT_WIDTH-1:0] select; input [WIDTH-1:0] input_data_array [0:NUMBER_OF_INPUTS-1]; output [WIDTH-1:0] output_data; wire [WIDTH-1:0] interm_w [0:INTERMEDIATE_WIRES_COUNT-1]; genvar i; genvar j; int K = NUMBER_OF_INPUTS / 2; int M = NUMBER_OF_INPUTS; int P = 0; generate for(i = 0; i < SELECT_WIDTH; i=i+1) begin for(j = 0; j < K; j=j+1) begin multiplexer_2_input #( .WIDTH(WIDTH) ) mux_i ( .input_0(interm_w[P + j * 2]), .input_1(interm_w[P + j * 2 + 1]), .select(select[SELECT_WIDTH - i - 1]), .output_data(interm_w[M + j]) ); end P = M; // 第51行,报错位置 M = M + K; K = K / 2; end endgenerate endmodule
报错信息
** Error: (vlog-13069) .../multiplexer_v2.sv(51): near "=" : syntax error, unexpected '='. ** Error: .../multiplexer_v2.sv(51): (vlog-13205) Syntax error found in the scope following 'P'. Is there a missing '::'?
辅助函数interm_value
function int interm_value(input int select_width, input int number_of_inputs); begin int i; int interm_value; int K; interm_value = 0; K = number_of_inputs; for(i = 0; i < select_width; i=i+1) begin interm_value = interm_value + K; K = K / 2; end return interm_value + 1; end endfunction
问题原因
generate块是Verilog的静态编译阶段结构,仅用于在编译时展开电路结构,不支持对int、integer等变量进行动态赋值操作。你尝试在generate循环内修改P、M、K的值,属于动态行为,违反了generate块的语法规则。
解决方案
放弃在generate内修改变量的思路,改用基于循环变量i的表达式直接计算每一轮的P、M、K值,同时补充输入数组到中间连线的初始连接,以及最终输出的连接。
修改后的代码
module multiplexer_v2(input_data_array, select, output_data); parameter WIDTH = 16; parameter NUMBER_OF_INPUTS = 8; parameter SELECT_WIDTH = $clog2(NUMBER_OF_INPUTS); localparam INTERMEDIATE_WIRES_COUNT = interm_value(SELECT_WIDTH, NUMBER_OF_INPUTS); input [SELECT_WIDTH-1:0] select; input [WIDTH-1:0] input_data_array [0:NUMBER_OF_INPUTS-1]; output [WIDTH-1:0] output_data; wire [WIDTH-1:0] interm_w [0:INTERMEDIATE_WIRES_COUNT-1]; genvar i; genvar j; // 将输入数组连接到中间连线的初始段(二叉树叶子节点) generate for(j = 0; j < NUMBER_OF_INPUTS; j = j + 1) begin assign interm_w[j] = input_data_array[j]; end endgenerate // 二叉树结构的MUX层级展开 generate for(i = 0; i < SELECT_WIDTH; i = i + 1) begin // 基于循环变量i静态计算当前层级的参数 localparam current_K = NUMBER_OF_INPUTS >> (i + 1); // 当前层级的MUX数量 localparam current_P = (i == 0) ? 0 : (NUMBER_OF_INPUTS + (NUMBER_OF_INPUTS * ((2**(i-1)) - 1)) >> (i-1)); // 当前层级输入的起始索引 localparam current_M = NUMBER_OF_INPUTS + (NUMBER_OF_INPUTS * ((2**i) - 1)) >> i; // 当前层级输出的起始索引 for(j = 0; j < current_K; j = j + 1) begin multiplexer_2_input #( .WIDTH(WIDTH) ) mux_i ( .input_0(interm_w[current_P + j * 2]), .input_1(interm_w[current_P + j * 2 + 1]), .select(select[SELECT_WIDTH - i - 1]), .output_data(interm_w[current_M + j]) ); end end endgenerate // 连接最终输出(二叉树根节点) assign output_data = interm_w[INTERMEDIATE_WIRES_COUNT - 1]; endmodule // 辅助函数保持不变 function int interm_value(input int select_width, input int number_of_inputs); begin int i; int interm_value; int K; interm_value = 0; K = number_of_inputs; for(i = 0; i < select_width; i=i+1) begin interm_value = interm_value + K; K = K / 2; end return interm_value + 1; end endfunction
关键说明
- 初始连接:通过
generate循环将input_data_array的每个元素映射到interm_w的前N个位置,作为二叉树的叶子节点。 - 静态参数计算:每一层的
current_K、current_P、current_M都通过循环变量i的表达式静态计算,完全符合generate块的编译期展开规则。 - 输出连接:最终输出直接取
interm_w的最后一个元素(对应二叉树的根节点输出)。
内容的提问来源于stack exchange,提问作者Moein
相关产品推荐
相关产品推荐

