跳转到内容
新建笔记

Verilog/SystemVerilog 语言基础

module mux2 #(
parameter int WIDTH = 8
) (
input logic [WIDTH-1:0] a,
input logic [WIDTH-1:0] b,
input logic sel,
output logic [WIDTH-1:0] y
);
always_comb begin
y = sel ? b : a;
end
endmodule

logic 表示四态变量,可由一个连续赋值、一个过程块或一个模块输出驱动,但不能有多个过程驱动。真正需要多驱动解析的网络使用 wire/net 类型。

类别运算符注意
算术+ - * / %除法和取模可能生成昂贵电路
位运算& | ^ ~对每一位操作
逻辑&& || !结果用于条件判断
归约&a |a ^a将向量归约为 1 位
比较== != < <= > >=注意符号和 x
拼接{a, b}位宽为各段之和
复制{N{value}}常用于扩展和掩码
选择cond ? a : b通常综合为多路选择器

===/!== 会把 x/z 也作为普通值比较,主要用于 Testbench;设计逻辑通常使用 ==/!=,并通过复位和断言处理未知值。

if、always、循环和 case 分支语法上只接受一条 statement;begin-end 把多条语句组成一个块。建议即使只有一条语句也保留,避免以后加语句时改变控制范围。

if (enable) begin
data <= next_data;
valid <= 1'b1;
end else begin
valid <= 1'b0;
end

语句块中的书写顺序不会自动让硬件串行工作;电路行为由赋值类型、数据依赖和时钟决定。

always_comb begin
grant = 4'b0000;
priority casez (request)
4'b1???: grant = 4'b1000;
4'b01??: grant = 4'b0100;
4'b001?: grant = 4'b0010;
4'b0001: grant = 4'b0001;
default: grant = 4'b0000;
endcase
end
  • case 逐位精确匹配,包括 x/z。
  • casez 将比较表达式和分支项两侧的 z/? 都视为通配符;只适合已控制输入四态来源的明确掩码匹配,否则输入上的 z 可能掩盖问题。
  • 避免 casex:它会把真实输入中的 x 也当通配符,可能掩盖未初始化或冲突。
  • priority 表明按顺序选择;unique 表明最多一个分支匹配。仿真器可据此检查意图,但前提是代码确实满足承诺。
  • 过程块中的固定边界 for:综合时展开重复逻辑。
  • generate for:在 elaboration 阶段生成模块实例或结构。
  • #delay、无限循环、文件 I/O 和 fork-join 通常只属于仿真环境,不应出现在可综合设计中。
  • 将 C 语言的“变量赋值”直觉套到信号和寄存器上。
  • 省略位宽和符号,导致扩展或截断错误。
  • 组合块遗漏默认值或 default。
  • 同一信号由 assign 和 always 同时驱动。
  • 把 x 当作综合优化提示;综合结果和仿真行为可能因此分离。