【6.19】知识点清单逐点解答

一、四步学习知识点

第 1 步 核心概念问答(面向 C 语言、硬件零基础)

1. wire 和 reg 有什么区别?各用在什么场景?
  1. 本质硬件对应
    • wire:对应硬件导线,物理上就是连接线,只能持续传递信号,无存储能力;
    • reg:对应寄存器 / 触发器存储单元,能锁存、保存上一拍的数值,有记忆功能。
  2. 赋值规则
    • wire:只能用连续赋值 assign 变量 = 表达式,不能在always块内赋值;
    • reg:只能在always / initial过程块内赋值,使用=阻塞或<=非阻塞赋值,不能用 assign。
  3. 使用场景
    • wire:模块端口、模块内部连线、组合逻辑中间信号线;
    • reg:时序逻辑(触发器输出)、always 块内临时存储变量。
2. assign 和 always @(posedge clk) 有什么区别?
  1. assign纯组合逻辑
    • 硬件对应:纯导线、门电路,输入一变输出立刻同步变化;
    • 无时钟、无存储,实时连续运算,任何时刻输入更新输出马上更新。
  2. always @(posedge clk)时序逻辑
    • 硬件对应:D 触发器,只有时钟上升沿到来瞬间,才会更新输出;
    • 其余时间输出保持不变,具备数据锁存记忆能力。
3. 为什么 Verilog 是在 "画电路" 而不是 "写程序"?

C 语言是顺序执行软件指令 :CPU 按行逐条串行跑,同一时间只执行一行代码; Verilog 是硬件描述语言 HDL :所有代码对应真实硬件电路,所有电路并行同时工作,代码只是描述电路结构 / 连接关系,不是执行顺序指令。 比如:同时写 3 个 assign,硬件里 3 组门电路会同时运算,不存在先后执行。


第 2 步 3 道基础练习题完整代码 + 电路解释

1. 二输入与门(assign 组合逻辑)
复制代码
module and2(
    input a, b,
    output wire y
);
assign y = a & b;
endmodule
  • 电路:生成一个 2 输入与门,a、b 两根导线接入与门输入端,输出导线 y 实时输出两者相与结果;输入任意一个变化,y 立刻更新。
2. D 触发器(always 时序逻辑)
复制代码
module dff(
    input clk, d,
    output reg q
);
always @(posedge clk) begin
    q <= d;
end
endmodule
  • 电路:生成标准上升沿 D 触发器;只有 clk 上升沿瞬间,才会把 d 当前值存入寄存器 q,其余时刻 q 保持原值不变。
3. 4 位加法器(assign 组合逻辑)
复制代码
module add4(
    input [3:0] a, b,
    output wire [3:0] sum,
    output wire cout
);
assign {cout, sum} = a + b;
endmodule
  • 电路:生成 4 位全加器级联电路,4 组加法单元并行运算;{cout,sum}拼接进位 + 4 位和,输入 a/b 改变时,加法结果立刻更新。

第 3 步 代码修改拓展(导师自查修改点)

  1. 与门改或门:assign y = a | b; 电路替换为 2 输入或门;

  2. D 触发器改带复位:新增input rst_n,敏感列表加入 rst,复位时 q 置 0;

    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) q <= 1'b0;
    else q <= d;
    end

4 位加法器改减法器:assign {borrow, diff} = a - b; 生成 4 位减法器,输出借位 + 差值。


第 4 步 Verilog 对比 C 语言:为什么 FPGA/ASIC 比 MCU C 代码快?核心:并行 vs 顺序

  1. C 语言(MCU):串行顺序执行 MCU 只有 1 个 CPU 内核,代码逐行串行执行,同一时刻只能运算一条指令,复杂运算需要分多周期分步完成,速度受 CPU 主频、指令周期限制。
  2. Verilog(硬件电路):全并行执行 Verilog 综合后生成真实硬件电路,所有门、加法器、触发器同一时钟周期同时并行运算。 举例:4 位加法,C 要循环分步相加;Verilog 直接 4 个加法单元同时计算,1 个周期出结果,天然高吞吐、低延迟。

二、课后 4 道练习题标准答案

1. assign 实现 3 输入与门 y = a & b & c

复制代码
module and3(
    input a,b,c,
    output wire y
);
assign y = a & b & c;
endmodule

电路:3 输入与门,三根输入导线实时相与,输出持续更新。

2. always @(posedge clk) q <= d; 无 clk 上升沿时 q 变不变?

  • 不会变 posedge clk代表敏感事件只有时钟上升沿;只有检测到时钟上升沿,才会执行q<=d赋值,其余所有时刻触发器锁存原有数值,q 保持不变。 和 C 赋值区别:C 赋值执行后变量立刻更新;Verilog 时序赋值只在指定触发事件发生时才更新。

3. wire 和 reg 使用场景总结

wire:

  • 模块输入 / 输出端口、模块内部连接导线;
  • 仅用于assign连续赋值,描述纯组合逻辑连线。

reg:

  • always / initial过程块内定义变量;
  • 时序逻辑触发器输出、过程块内临时存储信号,具备锁存能力。

4. 代码问题:always 块内使用阻塞赋值 q = d;

复制代码
always @(posedge clk)
q = d; // 错误写法,时序逻辑禁止用=阻塞赋值
问题原因:
  1. = 阻塞赋值:执行时会立刻更新变量,会综合出锁存器 / 错误组合逻辑,破坏触发器时序行为;
  2. <= 非阻塞赋值:所有右端表达式统一在时钟沿采样,所有赋值同时更新,精准对应硬件 D 触发器行为,是时序逻辑标准写法。
核心规则:
  • 组合逻辑 always 块:用=阻塞赋值;
  • 时序逻辑(带时钟沿)always 块:必须用<=非阻塞赋值。

三、核心概念速记总结

  1. wire = 导线,reg = 寄存器;assign = 并行组合逻辑,posedge clk = 时序触发器;
  2. Verilog 并行硬件,C 串行软件,这是速度、语法差异根源;
  3. 时序逻辑时钟块统一用<=,组合逻辑 assign/always 用=
  4. 敏感列表决定电路什么时候更新信号,仅触发事件到来才执行赋值。