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探针插入位置。
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功能的正确性。以下为推荐的仿真验证步骤:
- 编写测试平台(testbench):生成时钟激励、复位序列、启动信号脉冲。
- 验证状态机跳转:检查IDLE→COUNT_UP→COUNT_DN→HOLD→IDLE的完整循环。
- 验证计数器行为:在COUNT_UP状态下检查递增,COUNT_DN状态下检查递减,HOLD状态下检查保持。
- 验证同步器功能:注入异步start信号,检查start_sync是否延迟两个时钟周期后稳定输出。
- 记录仿真波形:保存VCD/FSDB波形文件,作为后续Signal Tap捕获结果的对比基准。
完成上述验证后,即可将设计综合、布局布线,并生成.sof文件用于Signal Tap的在线调试。