Vivado中Verilog生成块用外部计数器无法综合问题求助
解决Vivado中Verilog代码仿真正常但无法综合的问题
你的问题核心在于generate块是静态编译阶段执行的逻辑,而cnt1是一个动态的时序寄存器变量——综合工具在编译时无法确定(i + cnt1)*5这个地址的具体值,因为cnt1是运行时才会变化的,这就导致综合工具无法完成静态的模块实例化和连线;而仿真工具是动态模拟运行过程,所以能正常工作。
下面给你两种可行的修改方案:
方案一:用多路选择器替代generate块中的动态参数引用
把pi_values的所有可能取值提前通过多路选择器选出来,再传给module1,这样综合工具能明确处理静态的连线:
module multiply_s1( input clk, input rst, input [9:0]in, input ena, output [9:0]out); localparam [0:24] pi_values = {5'h4, 5'h5, 5'h6, 5'h7, 5'h8}; reg [1:0] cnt1;//count CC times of GG coeffcient // 定义寄存器存储每个cnt1对应的pi值片段 reg [4:0] pi_sel_0; reg [4:0] pi_sel_1; always@(posedge clk or negedge rst) begin if(rst == 0) begin cnt1 <= 0; pi_sel_0 <= 5'h0; pi_sel_1 <= 5'h0; end else if(ena == 0) begin cnt1 <= 0; pi_sel_0 <= pi_values[0*5 +: 5]; pi_sel_1 <= pi_values[1*5 +: 5]; end else begin // 更新cnt1 if (cnt1 == 3) cnt1 <= 0; else cnt1 <= cnt1 + 1; // 根据当前cnt1选择对应的pi片段 case(cnt1) 2'd0: begin pi_sel_0 <= pi_values[(0+0)*5 +:5]; pi_sel_1 <= pi_values[(1+0)*5 +:5]; end 2'd1: begin pi_sel_0 <= pi_values[(0+1)*5 +:5]; pi_sel_1 <= pi_values[(1+1)*5 +:5]; end 2'd2: begin pi_sel_0 <= pi_values[(0+2)*5 +:5]; pi_sel_1 <= pi_values[(1+2)*5 +:5]; end 2'd3: begin pi_sel_0 <= pi_values[(0+3)*5 +:5]; pi_sel_1 <= pi_values[(1+3)*5 +:5]; end endcase end end // 直接实例化两个module1,使用提前选好的pi_sel信号 module1 mod1_0(.clk(clk), .rst(rst), .multiplier(in[0*5 +: 5]), .multiplicand(pi_sel_0), .result(out[0*5 +: 5])); module1 mod1_1(.clk(clk), .rst(rst), .multiplier(in[1*5 +: 5]), .multiplicand(pi_sel_1), .result(out[1*5 +: 5])); endmodule
方案二:将generate块的逻辑转换为纯时序逻辑(如果module1可以内联)
如果module1是一个简单的乘法器,你可以把它的逻辑直接写到multiply_s1的时序块里,避免模块实例化时的动态参数问题:
module multiply_s1( input clk, input rst, input [9:0]in, input ena, output reg [9:0]out); localparam [0:24] pi_values = {5'h4, 5'h5, 5'h6, 5'h7, 5'h8}; reg [1:0] cnt1;//count CC times of GG coeffcient always@(posedge clk or negedge rst) begin if(rst == 0) begin cnt1 <= 0; out <= 10'h0; end else if(ena == 0) begin cnt1 <= 0; out <= 10'h0; end else begin // 更新cnt1 if (cnt1 == 3) cnt1 <= 0; else cnt1 <= cnt1 + 1; // 直接计算乘法(假设module1是5位乘法,结果取低5位) out[4:0] <= in[4:0] * pi_values[(0 + cnt1)*5 +:5]; out[9:5] <= in[9:5] * pi_values[(1 + cnt1)*5 +:5]; end end endmodule
关键原理总结
- Generate块是静态的:它在编译阶段就确定了要实例化的模块数量、连线关系,只能使用
genvar或者编译时就能确定的常量,不能用运行时才变化的寄存器/线网变量。 - 仿真工具的灵活性:仿真工具是逐周期模拟运行过程,会动态计算
cnt1的值并解析参数引用,所以不会报错,但综合工具不支持这种动态的静态编译逻辑。
内容的提问来源于stack exchange,提问作者France
相关产品推荐
相关产品推荐

