Quick Start:快速体验国产FPGA在PLC IO扩展中的应用
本指南帮助工程师在30分钟内搭建一个基于紫光同创Logos-2系列(PGL22G)的PLC IO扩展模块原型,实现高速脉冲捕获(100ns分辨率)与PWM输出。您需要一块PGL22G开发板、JTAG下载器、以及PDS(PanGo Design Suite)EDA工具。完成本指南后,您将获得一个可运行的跨时钟域脉冲处理设计。
前置条件
- 硬件:紫光同创Logos-2 PGL22G开发板(或兼容板卡),JTAG下载器(如FT2232H)。
- 软件:PDS 2022.1及以上版本(含Synplify Pro综合器),ModelSim或Vivado Simulator(用于仿真)。
- 知识:熟悉Verilog标准RTL风格,了解跨时钟域同步基础(双触发器同步器或异步FIFO)。
- 文档:PGL22G数据手册(重点关注PLL配置与块RAM时序)。
目标与验收标准
- 目标1:在PGL22G上实现一个IO扩展模块,支持外部脉冲捕获(最小脉冲宽度100ns)和PWM输出(频率1kHz~100kHz可调)。
- 目标2:验证跨时钟域设计正确性——捕获时钟域(50MHz)与PWM时钟域(10MHz)之间无亚稳态错误。
- 验收:使用示波器测量PWM输出波形,频率误差≤1%;通过逻辑分析仪捕获外部脉冲,时间戳误差≤10ns。
实施步骤
步骤1:创建PDS工程并配置PLL
- 打开PDS,新建工程,选择器件PGL22G-6BG324。
- 调用PLL IP核:输入时钟50MHz(板载晶振),输出两路时钟——clk_cap(50MHz,用于脉冲捕获)和clk_pwm(10MHz,用于PWM生成)。启用锁定指示信号pll_locked。
- 注意:PGL22G的PLL支持整数分频,确保输出频率在数据手册范围内(典型10MHz~200MHz)。
步骤2:编写脉冲捕获模块(capture.v)
- 使用clk_cap(50MHz)作为采样时钟,周期20ns。通过双触发器同步器将外部脉冲信号同步到clk_cap域。
- 检测上升沿:当同步后的信号从0→1时,触发计数器记录当前时间戳(使用32位计数器,每20ns递增)。
- 输出:捕获到的脉冲宽度(以时钟周期数表示)和边沿时间戳,通过FIFO传递到PWM时钟域。
- 代码示例(关键片段):
reg [1:0] sync_pulse; always @(posedge clk_cap) sync_pulse <= {sync_pulse[0], ext_pulse}; wire rise_edge = (sync_pulse == 2'b01);
步骤3:编写PWM生成模块(pwm_gen.v)
- 使用clk_pwm(10MHz)作为工作时钟,周期100ns。设置一个周期计数器(例如10位,计数范围0~999,对应100kHz PWM频率)。
- 占空比由外部寄存器duty[9:0]控制(值0~1000),当计数器小于duty时输出高电平,否则低电平。
- 从FIFO读取捕获数据,用于调整占空比(例如根据脉冲宽度动态调节)。
步骤4:集成跨时钟域FIFO
- 实例化PDS提供的异步FIFO IP核(或手写双口RAM+双指针)。写时钟为clk_cap(50MHz),读时钟为clk_pwm(10MHz),深度16,数据宽度32位。
- 注意:FIFO满/空标志需使用格雷码指针同步,避免亚稳态。
步骤5:顶层连接与约束
- 在顶层模块中例化PLL、capture、pwm_gen和FIFO。分配引脚:外部脉冲输入(GPIO_P)、PWM输出(GPIO_N)。
- 编写SDC时序约束:对clk_cap和clk_pwm分别设置时钟周期,对跨时钟域路径设置false_path或set_clock_groups -asynchronous。
步骤6:综合、布局布线并生成比特流
- 在PDS中运行综合(Synplify Pro),检查无语法错误。注意:PDS对部分SystemVerilog语法支持有限,建议使用标准Verilog-2001。
- 运行布局布线,查看时序报告,确保两个时钟域内部路径无setup/hold违例。跨时钟域路径应被忽略。
- 生成比特流文件,下载到开发板。
验证结果
- PWM输出:用示波器测量PWM引脚,频率应为100kHz±1kHz,占空比与duty寄存器值一致(例如duty=500时占空比50%)。
- 脉冲捕获:用信号发生器输入100ns宽脉冲,逻辑分析仪捕获时间戳,两次捕获间隔误差≤10ns。
- FIFO功能:连续输入多个脉冲,观察FIFO空/满标志正常切换,无数据丢失。
排障指南
- 问题1:PWM输出频率不准。原因:PLL配置错误或时钟约束未生效。解决:检查PLL输出频率是否与SDC一致,重新运行时序分析。
- 问题2:脉冲捕获丢失。原因:同步器级数不足或FIFO溢出。解决:将同步器改为三级触发器,增加FIFO深度至32。
- 问题3:综合报错“unsupported syntax”。原因:使用了PDS不支持的Verilog结构(如always_ff)。解决:改用always @(posedge clk)风格。
扩展方向
- 参数化设计:将PWM频率、占空比、捕获分辨率定义为参数,便于复用。
- 高速数据采集:利用PGL22G内置块RAM构建FIFO,实现多通道同步采样(例如4通道、每通道100MSPS)。
- 跨平台移植:设计时使用纯Verilog RTL,避免厂商专用原语,可移植到其他国产FPGA(如安路、高云)。
- 工业协议支持:在FPGA中实现EtherCAT从站控制器(ESC),替代专用ASIC,降低BOM成本。
参考
- 紫光同创Logos-2系列数据手册(DS_L2_2022_v1.3)
- PDS用户指南(UG_PDS_2022.1)
- 《FPGA跨时钟域设计最佳实践》(Cummings, Clifford E.)
附录:关键代码片段
// capture.v - 脉冲捕获模块
module capture (
input wire clk_cap, // 50MHz
input wire rst_n,
input wire ext_pulse, // 外部脉冲
output reg [31:0] timestamp, // 捕获时间戳
output reg capture_valid
);
reg [1:0] sync_pulse;
always @(posedge clk_cap or negedge rst_n) begin
if (!rst_n) sync_pulse <= 2'b0;
else sync_pulse <= {sync_pulse[0], ext_pulse};
end
wire rise_edge = (sync_pulse == 2'b01);
reg [31:0] cnt;
always @(posedge clk_cap or negedge rst_n) begin
if (!rst_n) cnt <= 32'b0;
else cnt <= cnt + 1'b1;
end
always @(posedge clk_cap or negedge rst_n) begin
if (!rst_n) begin
timestamp <= 32'b0;
capture_valid <= 1'b0;
end else if (rise_edge) begin
timestamp <= cnt;
capture_valid <= 1'b1;
end else begin
capture_valid <= 1'b0;
end
end
endmodule


