4. 命名规范(二):时钟与复位命名、总线命名、状态机命名

好,咱们接着聊命名。上一章讲了模块和信号的基础命名规则,这一章咱们深入一点,专门聊聊三个容易出乱子的地方:时钟与复位、总线、还有状态机。

这三个东西,说白了就是芯片的“心跳”、“血管”和“大脑”。名字起不好,后期调试能把你逼疯。我自己就吃过不少亏,今天把这些经验掰开了揉碎了讲给你听。

4.1 时钟与复位命名:别让“心跳”乱了节奏

时钟信号是芯片里最“忙”的信号,没有之一。它每时每刻都在翻转。复位信号则是芯片的“总开关”,一按下去,所有状态归零。这两个信号的名字,必须一眼就能看出它的用途和来源。

4.1.1 时钟命名:清晰标明来源与频率

我个人习惯,时钟信号的名字要包含三个信息:来源、用途、频率(如果有多时钟域)。

举个例子,一个从PLL(锁相环)出来的200MHz系统主时钟,我会这么命名:

// 推荐命名
wire clk_pll_sys_200m;
wire clk_pll_ddr_400m;
wire clk_osc_32k;  // 外部晶振输入的32KHz慢速时钟

你看,clk 开头,一眼就知道是时钟。接着是来源 pll 或 osc,然后是用途 sys 或 ddr,最后是频率 200m。这样写,不管谁拿到代码,都能快速理解。

核心原则: 时钟命名必须能“自解释”。不要用 clk1、clk2 这种名字,三个月后你自己都看不懂。

我曾经在一个项目中,看到有人把时钟命名为 c1、c2、c3。结果综合时发现 c2 和 c3 其实是同一个时钟源的不同分频,但因为名字看不出关联,导致后端工程师做了两套时钟树,白白浪费了功耗和面积。嗯,从那以后,我对时钟命名就特别较真。

4.1.2 复位命名:区分同步与异步,标明有效电平

复位信号比时钟稍微复杂一点,因为它有同步复位和异步复位的区别,还有高有效和低有效的区别。

我的建议是:

  • 低有效复位:用 _n 或 _b 后缀(n代表negative,b代表bar)。
  • 高有效复位:用 _p 后缀(p代表positive)。
  • 异步复位:名字里带上 async 或 arst。
  • 同步复位:名字里带上 sync 或 srst。
// 推荐命名
wire rst_n;              // 全局低有效异步复位
wire rst_pll_sync_n;     // PLL锁定后的同步复位(低有效)
wire rst_domain_a_async_p; // A时钟域的高有效异步复位
注意: 千万不要把同步复位和异步复位的名字混用。比如一个信号明明是同步复位,却起名叫 arst_n,这会让读代码的人产生严重误解,甚至导致综合工具推断出错误的寄存器类型。

你想想看,如果代码里写 always @(posedge clk or negedge arst_n),但 arst_n 实际上是一个同步复位信号,那综合工具会把它当成异步复位来处理,生成不必要的复位网络。这种坑,我见过不止一次。

4.2 总线命名:统一规范,避免“鸡同鸭讲”

总线是模块之间通信的“高速公路”。如果总线命名不规范,不同模块对接时就像鸡同鸭讲,光对齐信号名就能耗掉半天时间。

我参与过一个大项目,总线协议是自己定义的。一开始大家各写各的,A模块叫 data_in,B模块叫 din,C模块叫 wdata。结果集成的时候,光改名字就改了两天,还漏改了几个,导致仿真跑不通。后来我们痛定思痛,定了一套总线命名规范。

4.2.1 通用总线信号命名模板

对于大多数自定义总线,我建议采用以下模板:

<总线前缀>_<信号类型>_<方向/属性>

举个例子,一个简单的AHB-like总线:

信号名 含义
bus_haddr 总线地址
bus_hwdata 总线写数据
bus_hrdata 总线读数据
bus_hwrite 总线写使能
bus_hsel 总线从设备选择
bus_hready 总线就绪信号

你看,所有信号都以 bus_ 开头,一眼就知道这是总线信号。后面的 haddr、hwdata 等,则清晰表明了具体功能。

小技巧: 如果项目中有多种总线(比如AXI、APB、自定义总线),建议用不同的前缀区分。例如 axi_、apb_、mybus_。这样在代码里搜索时,可以快速定位到特定总线的所有信号。

4.2.2 总线接口信号分组

对于复杂的总线接口(比如AXI),信号非常多。我建议按通道分组命名,每组内部再按功能细分。

// AXI 写地址通道
wire axi_awid;
wire axi_awaddr;
wire axi_awlen;
wire axi_awsize;
wire axi_awburst;

// AXI 写数据通道
wire axi_wdata;
wire axi_wstrb;
wire axi_wlast;
wire axi_wvalid;

// AXI 写响应通道
wire axi_bid;
wire axi_bresp;
wire axi_bvalid;

这样分组后,代码的可读性会大大提高。你看到 axi_aw 开头的,就知道是写地址通道的信号;看到 axi_w 开头的,就知道是写数据通道的信号。

4.3 状态机命名:让“大脑”逻辑一目了然

状态机是数字电路设计的核心。一个设计精良的状态机,代码读起来就像在读一个故事。而命名,就是这个故事里的“角色名”。

4.3.1 状态编码命名:用枚举,别用魔法数字

我强烈建议使用 enum 或 parameter 来定义状态,而不是直接用二进制数字。

// 不推荐
parameter IDLE = 3'b000;
parameter READ = 3'b001;
parameter WRITE = 3'b010;
parameter DONE = 3'b011;

// 推荐(SystemVerilog)
typedef enum logic [2:0] {
    ST_IDLE,
    ST_READ,
    ST_WRITE,
    ST_DONE
} state_t;

state_t current_state, next_state;

你看,用枚举后,代码里到处都是 ST_READ、ST_WRITE 这样的名字,而不是 3'b001、3'b010。哪个更容易理解?一目了然。

命名惯例: 状态名建议以 ST_ 或 S_ 开头,后面跟描述状态的英文单词。比如 ST_IDLE、ST_FETCH、ST_DECODE、ST_EXECUTE。

4.3.2 状态机变量命名:区分当前状态和下一状态

状态机通常有两个核心变量:current_state 和 next_state。我建议统一使用这两个名字,不要用 cs、ns 这种缩写。

// 推荐
always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        current_state <= ST_IDLE;
    else
        current_state <= next_state;
end

always_comb begin
    next_state = current_state;  // 默认保持
    case (current_state)
        ST_IDLE: begin
            if (start)
                next_state = ST_READ;
        end
        ST_READ: begin
            if (data_valid)
                next_state = ST_DONE;
        end
        // ...
    endcase
end

我曾经见过有人用 state 和 state_next,或者 st 和 st_nxt。说实话,这些写法虽然也能用,但不如 current_state 和 next_state 来得直观。你想想看,在代码里搜索 current_state,是不是比搜索 st 要准确得多?

4.3.3 状态机输出信号命名:标明来源状态

状态机的输出信号,我建议在名字里带上状态机的名字,方便追踪来源。

// 假设有一个状态机叫 fsm_ahb_master
wire fsm_ahb_master_idle;     // 状态机处于IDLE状态
wire fsm_ahb_master_busy;     // 状态机处于忙状态
wire fsm_ahb_master_done;     // 状态机完成操作

这样,当你在顶层模块里看到 fsm_ahb_master_done 这个信号时,你立刻就知道它来自 fsm_ahb_master 这个状态机模块。调试的时候,这种命名方式能帮你节省大量时间。

4.4 本章知识体系

说了这么多,我画了一张图,帮你把这一章的核心逻辑串起来:

命名规范(二):核心知识体系 时钟与复位命名 总线命名 状态机命名 时钟:来源_用途_频率 复位:同步/异步 + 有效电平 后缀 _n/_b(低有效)_p(高有效) 前缀_类型_方向/属性 按通道分组(AXI: aw/w/b/ar/r) 不同总线用不同前缀区分 用枚举定义状态,不用魔法数字 current_state / next_state 输出信号标明来源状态机 核心目标:自解释、可搜索、易维护 好的命名,让代码自己“说话”

好了,这一章的内容就到这里。命名规范这东西,说起来简单,做起来需要坚持。刚开始可能会觉得麻烦,但养成习惯后,你会发现代码质量提升了一大截。下一章咱们聊聊代码布局和注释规范,那也是很多工程师容易忽略的地方。

可可精品资料库