4. RTL设计基础与待测模块介绍

在部署嵌入式逻辑分析仪之前,必须深入理解待测设计(DUT)的RTL结构。本章以典型的计数器与状态机设计为例,系统讲解RTL设计基础、时钟域与复位策略,并逐层分析待测代码结构,为后续Signal Tap探针插入与触发条件设置奠定基础。

4.1 待测模块功能概述

本课程选用的待测模块是一个多模式计数器与状态机复合模块,它同时包含组合逻辑、时序逻辑、跨时钟域同步器以及有限状态机(FSM),非常适合演示Signal Tap的多种捕获与分析能力。

模块名称 功能描述 关键特性
counter_fsm_top 顶层模块,实例化所有子模块 包含时钟分频、状态机、计数器
clk_divider 系统时钟分频器 产生慢速使能时钟,用于演示跨时钟域
fsm_controller 有限状态机控制器 4状态:IDLE、COUNT_UP、COUNT_DOWN、HOLD
counter_core 可逆计数器核心 8位宽,支持同步复位与使能
sync_2ff 双级触发器同步器 用于异步信号同步化处理
设计意图: 该模块组合了RTL设计中常见的三种典型结构——纯组合逻辑(状态译码)、纯时序逻辑(计数器)、混合逻辑(FSM+计数器联动),使Signal Tap能够同时展示寄存器级、组合级和跨时钟域信号的行为。

4.2 时钟域与复位策略

Agilex器件支持多时钟域设计,本模块采用双时钟域架构,并遵循同步复位优先原则。

4.2.1 时钟域划分

  • 主时钟域(clk_sys, 100MHz):驱动FSM控制器、计数器核心、状态译码逻辑。
  • 慢速时钟域(clk_slow, 由clk_divider产生):驱动外部接口同步器,用于演示跨时钟域信号捕获。

两个时钟域之间通过双级触发器同步器(2-FF synchronizer)进行异步信号传递,避免亚稳态传播。

4.2.2 复位策略

复位类型 作用域 实现方式
全局异步复位 所有寄存器 低电平有效,异步置位
同步复位 计数器核心 在时钟上升沿采样复位信号
软件复位(FSM) 状态机 由状态机自身产生内部复位条件
Signal Tap捕获注意: 异步复位信号在Signal Tap中可能显示为毛刺或短暂无效电平。建议在触发条件中增加复位信号的稳定窗口过滤,避免误触发。

4.3 待测RTL代码结构分析

以下为核心模块的RTL代码片段,重点标注了与Signal Tap探针插入相关的关键信号。

4.3.1 顶层模块结构

module counter_fsm_top (
    input  wire        clk_sys,        // 100MHz 主时钟
    input  wire        rst_n,          // 异步复位,低有效
    input  wire        start,          // 启动信号(异步输入)
    output wire [7:0]  count_out,      // 计数器输出
    output wire [1:0]  state_out       // 当前状态输出
);

    // 内部信号声明
    wire        clk_slow;              // 分频时钟
    wire        start_sync;            // 同步后的启动信号
    wire [1:0]  fsm_state;             // FSM 当前状态
    wire        count_en;              // 计数器使能
    wire        count_up_down;         // 计数方向:1=加,0=减

    // 实例化时钟分频器
    clk_divider #(.DIV_FACTOR(100)) u_clk_div (
        .clk_in (clk_sys),
        .rst_n  (rst_n),
        .clk_out(clk_slow)
    );

    // 实例化双级同步器(异步信号同步化)
    sync_2ff u_sync_start (
        .clk    (clk_sys),
        .rst_n  (rst_n),
        .async_in (start),
        .sync_out (start_sync)
    );

    // 实例化FSM控制器
    fsm_controller u_fsm (
        .clk      (clk_sys),
        .rst_n    (rst_n),
        .start    (start_sync),
        .state    (fsm_state),
        .count_en (count_en),
        .up_down  (count_up_down)
    );

    // 实例化计数器核心
    counter_core u_counter (
        .clk      (clk_sys),
        .rst_n    (rst_n),
        .en       (count_en),
        .up_down  (count_up_down),
        .count    (count_out)
    );

    // 状态输出赋值
    assign state_out = fsm_state;

endmodule

4.3.2 FSM控制器状态机

module fsm_controller (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        start,
    output reg  [1:0]  state,
    output reg         count_en,
    output reg         up_down
);

    // 状态编码
    localparam IDLE     = 2'b00;
    localparam COUNT_UP = 2'b01;
    localparam COUNT_DN = 2'b10;
    localparam HOLD     = 2'b11;

    // 状态寄存器(时序逻辑)
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            state <= IDLE;
        else begin
            case (state)
                IDLE:     if (start) state <= COUNT_UP;
                COUNT_UP: if (start) state <= COUNT_DN;
                COUNT_DN: if (start) state <= HOLD;
                HOLD:     if (start) state <= IDLE;
                default:  state <= IDLE;
            endcase
        end
    end

    // 输出译码(组合逻辑)
    always @(*) begin
        count_en = 1'b0;
        up_down  = 1'b0;
        case (state)
            IDLE:     begin count_en = 1'b0; up_down = 1'b0; end
            COUNT_UP: begin count_en = 1'b1; up_down = 1'b1; end
            COUNT_DN: begin count_en = 1'b1; up_down = 1'b0; end
            HOLD:     begin count_en = 1'b0; up_down = 1'b0; end
        endcase
    end

endmodule

4.4 模块间信号流与探针布局

下图展示了待测模块的内部信号流向以及建议的Signal Tap探针插入位置。

待测模块信号流与Signal Tap探针布局 counter_fsm_top 顶层模块 clk_divider clk_sys → clk_slow sync_2ff start → start_sync fsm_controller IDLE/UP/DN/HOLD count_en, up_down counter_core 8-bit 可逆计数器 Signal Tap 探针建议插入点 ① clk_sys, rst_n (时钟/复位) ② start_sync (同步后启动信号) ③ fsm_state[1:0] (状态机当前状态) ④ count_en, up_down (控制信号) ⑤ count_out[7:0] (计数器输出)

4.5 关键信号分类与捕获优先级

根据Signal Tap的捕获深度和触发复杂度,将待测模块中的信号分为三个优先级等级:

优先级 信号类型 示例信号 捕获建议
P0(必须捕获) 时钟、复位、状态机状态 clk_sys, rst_n, fsm_state 作为触发条件的基础信号,始终使能捕获
P1(建议捕获) 控制信号、使能信号 count_en, up_down, start_sync 用于分析状态跳转与计数行为
P2(按需捕获) 数据总线、中间节点 count_out[7:0], clk_slow 根据调试需求选择性使能,节省存储深度
实战要点: 在Agilex器件中,Signal Tap的每个探针都会消耗逻辑资源。建议在初始调试阶段只使能P0和P1信号,待定位到问题区域后再逐步增加P2信号,避免过度占用FPGA资源。

4.6 待测模块的仿真验证准备

在将设计下载到Agilex硬件之前,建议先通过仿真验证RTL功能的正确性。以下为推荐的仿真验证步骤:

  1. 编写测试平台(testbench):生成时钟激励、复位序列、启动信号脉冲。
  2. 验证状态机跳转:检查IDLE→COUNT_UP→COUNT_DN→HOLD→IDLE的完整循环。
  3. 验证计数器行为:在COUNT_UP状态下检查递增,COUNT_DN状态下检查递减,HOLD状态下检查保持。
  4. 验证同步器功能:注入异步start信号,检查start_sync是否延迟两个时钟周期后稳定输出。
  5. 记录仿真波形:保存VCD/FSDB波形文件,作为后续Signal Tap捕获结果的对比基准。

完成上述验证后,即可将设计综合、布局布线,并生成.sof文件用于Signal Tap的在线调试。