FPGA 组合逻辑和时序逻辑

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

DRC MDRV-1\] multiple Drive Nets:Net UNCONN_OUT\[1\] has multiple drivers: genblk1\[0\].tmp_max_1d_reg\[1\]\[1\]/Q,and genblk1\[1\].tmp_max_1d_reg\[1\]\[1\]/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 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 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 区别分析: | 特性 | 第一段代码(正常) | 第二段代码(有多驱动) | |----------|------------------------------------|---------------------------------------------| | **赋值方式** | 阻塞赋值 (`=`) | 非阻塞赋值 (`<=`) | | **变量性质** | 临时变量(组合逻辑) | 推断为寄存器(时序逻辑) | | **执行时机** | 立即计算,在同一时钟周期内完成 | 值在时钟边沿后更新,延迟生效 | | **关键影响** | 每个 `m` 实例独立计算自己的 `max_val/min_val` | **所有 `m` 实例共享并竞争同一个 `max_val/min_val` 寄存器** | **1. 非阻塞赋值 (`<=`) 的硬件含义** 在 `always @(posedge i_clk)` 块中使用 `<=` 赋值,综合工具会**推断出寄存器**。这意味着: * `max_val` 和 `min_val` 不再是临时计算变量,而是会在时钟沿之间保持状态的**物理寄存器**。 * 循环中的 `max_val <= din[start_idx+i];` 不是立即更新,而是安排一个"计划",在时钟周期结束时更新。因此,`for` 循环中后续的比较使用的 `max_val` 值始终是**该寄存器在上一个时钟周期的旧值**,这完全打破了查找最大值的逻辑。 **2. 多驱动冲突的产生** 这是最关键的一点:**在 `generate` 循环中,每个展开的 `m` 实例都包含自己的 `always` 块,但所有这些块都试图驱动名为 `max_val` 和 `min_val` 的同一个(全局)寄存器。** * 当 `group_idx < 2` 时(即 `m = 0, 1, 2, 3`),**4个并行的硬件实例**会在每个时钟沿同时执行。 * 每个实例都试图根据自己的 `start_idx` 和循环逻辑,向 `max_val` 和 `min_val` 写入数据。 * 这就造成了4个驱动源同时驱动同一根线,即 **`multiple driver`** 错误。 **第一段代码之所以正确** ,是因为它使用了阻塞赋值 (`=`),且**没有将 `max_val/min_val` 声明为 `reg`** (它们很可能是 `integer` 或隐式的临时变量)。这样,每个 `m` 实例的 `always` 块中的 `max_val` 和 `min_val` 都是该实例**本地、独立的组合逻辑变量**,彼此互不干扰。 在时序逻辑的 `always` 块中,`<=` 用于推断寄存器,`=` 用于临时计算。 **设计原则** :**"计算用阻塞,输出用非阻塞"**。在时钟触发的块内进行复杂的组合逻辑计算时,使用阻塞赋值和局部变量;只有需要寄存到下一个时钟周期的最终结果,才使用非阻塞赋值输出。

相关推荐
maverick_11112 小时前
【FPGA】 在Verilog中,! 和 ~ 的区别
fpga开发
黄埔数据分析2 天前
QDMA把描述符当数据搬移, 不用desc engine
fpga开发
南檐巷上学2 天前
基于FPGA的正弦信号发生器、滤波器的设计(DAC输出点数受限条件下的完整正弦波产生器)
fpga开发·数字信号处理·dsp·dds
嵌入式-老费2 天前
Linux Camera驱动开发(fpga + csi rx/csi tx)
fpga开发
ALINX技术博客3 天前
【202601芯动态】全球 FPGA 异构热潮,ALINX 高性能异构新品预告
人工智能·fpga开发·gpu算力·fpga
JJRainbow3 天前
SN75176 芯片设计RS-232 转 RS-485 通信模块设计原理图
stm32·单片机·嵌入式硬件·fpga开发·硬件工程
s9123601013 天前
FPGA眼图
fpga开发
北京青翼科技3 天前
【PCIe732】青翼PCIe采集卡-优质光纤卡- PCIe接口-万兆光纤卡
图像处理·人工智能·fpga开发·智能硬件·嵌入式实时数据库
minglie13 天前
verilog信号命名规范
fpga开发
XINVRY-FPGA3 天前
中阶FPGA效能红线重新划定! AMD第2代Kintex UltraScale+登场,记忆体频宽跃升5倍
嵌入式硬件·fpga开发·硬件工程·dsp开发·fpga