FPGA 组合逻辑和时序逻辑

vivado在进行实现阶段的opt_design过程报错,出现多驱动问题;

DRC MDRV-1 multiple Drive Nets:Net UNCONN_OUT1 has multiple drivers: genblk10.tmp_max_1d_reg11/Q,and genblk11.tmp_max_1d_reg11/Q;

问题代码1:

复制代码
 'd1: begin // 实现每2个数累加求和,320个数,一共输出160个
       group_size = 2;
       group_num = 320 / group_size;  // 160组
       group_idx = m;  // 每组输出一个累加和
                                
        if(group_idx < group_num) begin
            start_idx <= group_idx * group_size;
            temp_sum  <= 'd0;
                                    
             // 计算组内累加和
             for(i=0; i<group_size; i=i+1) begin
                  temp_sum <= temp_sum + din[start_idx + i];
             end
                                    
            // 只取低8位输出(如果累加和超过8位)
             dout[m] <= temp_sum;
         end
         else begin
               dout[m] <= 'd0;
         end
       end

问题代码2:

复制代码
'd6: begin // 实现每160个数比较,输出一个最大值和最小值,320个数,一共输出4个
    group_idx = m / 2;
    start_idx = group_idx * 160;
    
    if(group_idx < 2) begin  // 共2组,每组160个数
        // 找到当前组的最大值和最小值
        max_val = din[start_idx];
        min_val = din[start_idx];
        
        for(i=1; i<160; i=i+1) begin
            if(din[start_idx+i] > max_val) begin
                max_val <= din[start_idx+i];
            end
            if(din[start_idx+i] < min_val) begin
                min_val <= din[start_idx+i];
            end
        end
        
        // 分配输出
        if(m % 2 == 0) begin  // 偶数位置输出最大值
            dout[m] <= max_val;
        end
        else begin  // 奇数位置输出最小值
            dout[m] <= min_val;
        end
    end
    else begin
        dout[m] <= 'd0;
    end
end

分析原因,对于赋值,尽管这些逻辑是在一个always 块里面实现的,但是在for 循环中进行循环计算再赋值,不应该用非阻塞赋值,而是要用阻塞赋值;

正确代码1:

复制代码
'd1: begin // 实现每2个数累加求和,320个数,一共输出160个
    group_size = 2;
    group_num = 320 / group_size;  // 160组
    group_idx = m;  // 每组输出一个累加和
    
    if(group_idx < group_num) begin
        start_idx <= group_idx * group_size;
        temp_sum  <= 'd0;
        
        // 计算组内累加和
        for(i=0; i<group_size; i=i+1) begin
            temp_sum = temp_sum + din[start_idx + i];
        end
        
        // 只取低8位输出(如果累加和超过8位)
        dout[m] <= temp_sum;
    end
    else begin
        dout[m] <= 'd0;
    end
end

正确代码2:

'd6: begin // 实现每160个数比较,输出一个最大值和最小值,320个数,一共输出4个

group_idx = m / 2;

start_idx = group_idx * 160;

if(group_idx < 2) begin // 共2组,每组160个数

// 找到当前组的最大值和最小值

max_val = dinstart_idx;

min_val = dinstart_idx;

for(i=1; i<160; i=i+1) begin

if(dinstart_idx+i > max_val) begin

max_val = dinstart_idx+i;

end

if(dinstart_idx+i < min_val) begin

min_val = dinstart_idx+i;

end

end

// 分配输出

if(m % 2 == 0) begin // 偶数位置输出最大值

doutm <= max_val;

end

else begin // 奇数位置输出最小值

doutm <= min_val;

end

end

else begin

doutm <= 'd0;

end

end

区别分析:

特性 第一段代码(正常) 第二段代码(有多驱动)
赋值方式 阻塞赋值 (=) 非阻塞赋值 (<=)
变量性质 临时变量(组合逻辑) 推断为寄存器(时序逻辑)
执行时机 立即计算,在同一时钟周期内完成 值在时钟边沿后更新,延迟生效
关键影响 每个 m 实例独立计算自己的 max_val/min_val 所有 m 实例共享并竞争同一个 max_val/min_val 寄存器

1. 非阻塞赋值 (<=) 的硬件含义

always @(posedge i_clk) 块中使用 <= 赋值,综合工具会推断出寄存器。这意味着:

  • max_valmin_val 不再是临时计算变量,而是会在时钟沿之间保持状态的物理寄存器

  • 循环中的 max_val <= din[start_idx+i]; 不是立即更新,而是安排一个"计划",在时钟周期结束时更新。因此,for 循环中后续的比较使用的 max_val 值始终是该寄存器在上一个时钟周期的旧值,这完全打破了查找最大值的逻辑。

2. 多驱动冲突的产生

这是最关键的一点:generate 循环中,每个展开的 m 实例都包含自己的 always 块,但所有这些块都试图驱动名为 max_valmin_val 的同一个(全局)寄存器。

  • group_idx < 2 时(即 m = 0, 1, 2, 3),4个并行的硬件实例会在每个时钟沿同时执行。

  • 每个实例都试图根据自己的 start_idx 和循环逻辑,向 max_valmin_val 写入数据。

  • 这就造成了4个驱动源同时驱动同一根线,即 multiple driver 错误。

第一段代码之所以正确 ,是因为它使用了阻塞赋值 (=),且没有将 max_val/min_val 声明为 reg (它们很可能是 integer 或隐式的临时变量)。这样,每个 m 实例的 always 块中的 max_valmin_val 都是该实例本地、独立的组合逻辑变量,彼此互不干扰。

在时序逻辑的 always 块中,<= 用于推断寄存器,= 用于临时计算。

设计原则"计算用阻塞,输出用非阻塞"。在时钟触发的块内进行复杂的组合逻辑计算时,使用阻塞赋值和局部变量;只有需要寄存到下一个时钟周期的最终结果,才使用非阻塞赋值输出。

相关推荐
Rambo.xia13 小时前
接口协议避坑 · 第5篇:多器件级联时序踩坑实录
fpga开发
紫霄芯语19 小时前
观察者模式在FPGA中断系统的实战重构
观察者模式·fpga开发·重构
ARM+FPGA+AI工业主板定制专家1 天前
国产化RK3576+FPGA架构|晶圆传输机器人高速定位+AI瑕疵检测一体化方案
fpga开发·架构·机器人·嵌入式·fpga·工控·机器人运控
Eloudy2 天前
FPGA (QSFP28 + CMAC US+ RoCEv2) 与 Ubuntu22 + Mellanox 网卡直连分析
fpga开发
szxinmai主板定制专家2 天前
RK3568+FPGA高速并行采集|半导体探针测试设备多通道同步数据采集系统设计
人工智能·嵌入式硬件·计算机视觉·fpga开发
ARM|X86+FPGA工业主板厂家3 天前
RK3588+FPGA+EtherCAT异构架构解析|工业场景如何同时保住AI算力与微秒级运动实时性
人工智能·fpga开发·架构
zlinear数据采集卡3 天前
从“脏信号”到“纳伏级纯净”:硬核拆解DABL7606的多级抗混叠滤波与24位过采样算法
arm开发·科技·嵌入式硬件·fpga开发·开源
尤老师FPGA4 天前
HDMI数据的接收发送实验(二十)
fpga开发
千寻xun4 天前
三、实战篇-NVME SSD控制之FPGA实现(一)
fpga开发·nvme ssd·nvme协议
XMAIPC_Robot4 天前
软硬协同实时控制|RK3588业务调度+FPGA硬件时序,ethercat实现半导体设备微秒级响应(125us)
linux·arm开发·人工智能·fpga开发