4. 基于FPGA的TSN时间同步时钟源设计
任务说明
本案例实现一个可综合的本地时钟源模块 tsn_clk_src:以 125 MHz 系统时钟为基准,通过可配置的纳秒累加步进(频率调节)产生纳秒级时间戳,并支持相位对齐(时间戳预置/校正)。输出 ns_time 为 48 位纳秒计数,pps 为每秒脉冲,供 IEEE 802.1AS 时间同步使用。
设计要点
- 频率可调:
ns_inc为每个系统时钟周期累加的纳秒数(Q16.16 定点,1 ns = 65536)。标称 125 MHz 时ns_inc = 8 * 65536 = 524288。 - 相位对齐:
load_en有效时把load_val载入累加器,实现时间戳预置或校正。 - 纳秒输出:累加器高 16 位为整数纳秒,低 16 位为小数部分。
- PPS:纳秒整数部分跨秒时输出一个周期脉冲。
完整代码
module tsn_clk_src #(
parameter integer SYS_CLK_HZ = 125_000_000,
parameter integer NS_INC_DEF = 524288 // 8 ns * 65536
)(
input wire clk,
input wire rst_n,
input wire load_en, // 相位对齐/预置
input wire [47:0] load_val, // 载入的纳秒值
input wire [31:0] ns_inc, // Q16.16 每周期纳秒步进
output reg [47:0] ns_time, // 纳秒时间戳
output reg pps // 每秒脉冲
);
reg [63:0] acc; // 高16位整数ns,低16位小数
reg [47:0] ns_int;
reg [47:0] ns_int_d;
wire [63:0] acc_next = acc + {32'd0, ns_inc};
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
acc <= 64'd0;
ns_int <= 48'd0;
ns_int_d <= 48'd0;
ns_time <= 48'd0;
pps <= 1'b0;
end else if (load_en) begin
acc <= {load_val, 16'd0};
ns_int <= load_val;
ns_int_d <= load_val;
ns_time <= load_val;
pps <= 1'b0;
end else begin
acc <= acc_next;
ns_int <= acc_next[63:16];
ns_int_d <= ns_int;
ns_time <= acc_next[63:16];
pps <= (acc_next[63:16] != ns_int) &&
(acc_next[63:16][15:0] == 16'd0);
end
end
endmodule
仿真验证
module tb_tsn_clk_src;
reg clk = 0, rst_n = 0, load_en = 0;
reg [47:0] load_val = 0;
reg [31:0] ns_inc = 524288;
wire [47:0] ns_time;
wire pps;
tsn_clk_src dut(.clk(clk), .rst_n(rst_n), .load_en(load_en),
.load_val(load_val), .ns_inc(ns_inc),
.ns_time(ns_time), .pps(pps));
always #4 clk = ~clk; // 125 MHz
initial begin
#20 rst_n = 1;
// 相位对齐到 1_000_000_000 ns
@(posedge clk); load_en = 1; load_val = 48'd1_000_000_000;
@(posedge clk); load_en = 0;
// 运行 2 秒观察 PPS
#(2_000_000_000);
$display("ns_time=%0d pps=%b", ns_time, pps);
$finish;
end
endmodule
运行与判定
- 仿真:
iverilog -o tb tb_tsn_clk_src.v tsn_clk_src.v && vvp tb(或 Vivado/ModelSim 直接跑 tb)。 - 通过条件:复位后
ns_time从 0 开始,每 125 个时钟周期增加约 1000 ns;load_en后ns_time立即变为load_val;每约 1 秒pps出现一个时钟周期高电平。 - 频率调节验证:把
ns_inc改为 524288±N,观察ns_time增长速率相应变化,用于 802.1AS 频率补偿。