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

如何改写Verilog Generate块替代硬编码逻辑并解决多驱动问题

解决Verilog Generate块多驱动网问题并动态生成add_state分支逻辑

这段用于Spartan 7(Arty S-7)FPGA的Verilog累加器代码,原本尝试用Generate块动态生成add_state分支内的加法逻辑,仿真时功能正常,但Xilinx编译时触发多驱动网错误——因为每个Generate循环都会生成独立的always块,导致shift寄存器被多个时钟块驱动,编译器无法识别这些逻辑应归属主always块的add_state分支。无奈只能硬编码add_state里的if条件,现在需要实现基于array_size参数动态生成这部分逻辑,同时避免多驱动问题。

解决方案

核心思路是将Generate循环嵌入主always块的add_state分支内部,让所有对shift寄存器的赋值都属于同一个时钟触发的always块,从根源上消除多驱动冲突。这样既保留了动态生成逻辑的灵活性,又符合Xilinx编译器的综合规则。

修改后的完整代码

`timescale 1ns / 1ps

module acc #(
    parameter data_size = 8,
    parameter array_size = 3
) (
    input clk,
    input en,
    input wire [0:(data_size * array_size)-1] from_array, // 脉动阵列的所有输出线
    output wire [0:data_size-1] conv // 离散卷积的最终结果
);
    localparam shift_reg_size = (((array_size - 1) * 2 + 1) * data_size);
    reg [0:$clog2(((array_size - 1) * 2 + 1)*2)-1] cpt = 0;
    reg [0:shift_reg_size - 1] shift = 0;
    reg [0:(data_size * array_size)-1] shift_mem = 0;
    reg [0:data_size-1] conv_ = 0;
    assign conv = conv_;

    localparam add_state = 0;
    localparam shift_state = 1;
    reg state = shift_state;

    always @(posedge clk) begin
        if (en) begin
            case (state)
                shift_state: 
                begin
                    shift_mem <= from_array;
                    state <= add_state;
                    shift <= {shift_mem[0:data_size-1],shift[0:shift_reg_size - data_size - 1]};  
                end
                add_state: 
                begin
                    state <= shift_state;
                    // 动态生成add_state内的加法逻辑,替代硬编码if
                    genvar i;
                    generate
                        for (i = 1; i < array_size; i = i + 1) begin : add_gen
                            localparam j = ((i-1)*2 + 1);
                            if (cpt/2 > j) begin
                                shift[j*data_size:(j+1)*data_size-1] <= shift[j*data_size:(j+1)*data_size-1] + shift_mem[i*data_size:(i+1)*data_size-1];
                            end
                        end
                    endgenerate
                end
                default: state <= shift_state;
            endcase
            cpt <= cpt == {{1'b1},{($clog2(((array_size - 1) * 2 + 1)*2)-1){1'b0}}} ? cpt : cpt + 1;
            conv_ <= shift[shift_reg_size - data_size : shift_reg_size - 1];
        end
    end
endmodule

关键修改说明

  • 把原本独立的Generate块移到主always块的add_state分支内部,所有对shift的赋值都在同一个时钟触发块中,彻底解决多驱动问题。
  • 通过genvar i循环遍历1到array_size-1,动态计算每个分支的j值,生成对应的条件加法逻辑,完全替代硬编码的if语句。
  • 保留了原逻辑的触发条件:仅在时钟上升沿、en有效、state为add_state且cpt/2 > j时执行加法操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:40:10