当前位置: 首页 > news >正文

16路串口光纤通信FPGA项目实现指南

16路串口光纤通信FPGA项目实现指南 - 第一部分

项目概述

本项目实现了一个基于Xilinx FPGA的16路RS422串口光纤通信系统,通过Aurora 8B/10B协议将16路串口数据通过光纤进行高速传输。系统包含32个LED状态指示器,能够实时显示每路串口的数据活动状态。

系统特点

  • 16路串口并行处理
  • 光纤高速传输
  • 实时状态指示
  • 模块化设计
  • IP核复用

一、硬件设计与引脚约束

1.1 引脚分配策略

系统总计使用71个引脚:

  • 时钟引脚:1个(25MHz输入时钟)
  • 串口引脚:32个(16路接收 + 16路发送)
  • LED引脚:34个(32个状态LED + 2个系统LED)
  • 光纤引脚:4个(时钟和收发差分信号)

1.2 引脚约束文件

文件位置uart_fiber.srcs/constrs_1/new/pin.xdc

系统配置设置
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
时钟引脚定义
set_property PACKAGE_PIN P14 [get_ports clk_25m]
set_property IOSTANDARD LVCMOS33 [get_ports clk_25m]
串口引脚定义
# 16路串口接收引脚
set_property PACKAGE_PIN T4 [get_ports {uart_rx[0]}]
set_property PACKAGE_PIN U2 [get_ports {uart_rx[1]}]
# ... 其他14路接收引脚# 16路串口发送引脚
set_property PACKAGE_PIN P4 [get_ports {uart_tx[0]}]
set_property PACKAGE_PIN V2 [get_ports {uart_tx[1]}]
# ... 其他14路发送引脚# 电平标准设置
set_property IOSTANDARD LVCMOS33 [get_ports {uart_rx[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {uart_tx[*]}]
LED引脚定义
# 16个接收LED引脚
set_property PACKAGE_PIN G17 [get_ports {uart_rx_led[0]}]
set_property PACKAGE_PIN D16 [get_ports {uart_rx_led[1]}]
# ... 其他14个接收LED# 16个发送LED引脚
set_property PACKAGE_PIN G16 [get_ports {uart_tx_led[0]}]
set_property PACKAGE_PIN C17 [get_ports {uart_tx_led[1]}]
# ... 其他14个发送LED# 电平标准设置
set_property IOSTANDARD LVCMOS33 [get_ports {uart_rx_led[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {uart_tx_led[*]}]
光纤通信引脚定义
set_property PACKAGE_PIN D6 [get_ports GTPQ0_P]
set_property PACKAGE_PIN D5 [get_ports GTPQ0_N]
set_property PACKAGE_PIN E4 [get_ports RXP]
set_property PACKAGE_PIN H2 [get_ports TXP]
系统状态LED引脚定义
set_property PACKAGE_PIN G14 [get_ports {fpga_led[0]}]
set_property PACKAGE_PIN F14 [get_ports {fpga_led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fpga_led[*]}]

二、顶层模块设计与实现

2.1 模块接口定义

文件位置uart_fiber.srcs/sources_1/new/uart_fiber_top.v

module uart_fiber_top(input           clk_25m,        // 25MHz系统时钟input [15:0]    uart_rx,        // 16路串口接收output [15:0]   uart_tx,        // 16路串口发送output [15:0]   uart_rx_led,    // 接收LED指示output [15:0]   uart_tx_led,    // 发送LED指示input           GTPQ0_P,        // 光纤时钟正端input           GTPQ0_N,        // 光纤时钟负端input           RXP,            // 光纤接收正端input           RXN,            // 光纤接收负端output          TXP,            // 光纤发送正端output          TXN,            // 光纤发送负端output [1:0]    fpga_led        // 系统状态LED
);

2.2 时钟管理实现

wire clk_50m;        // 50MHz时钟信号
wire locked;         // 时钟锁定状态// 时钟IP核实例化
init_clk inst_init_clk (.clk_out1(clk_50m),     // 输出50MHz时钟.reset(1'b0),           // 不复位.locked(locked),        // 时钟锁定状态.clk_in1(clk_25m)       // 输入25MHz时钟
);

2.3 复位逻辑实现

// 复位控制信号
(*mark_debug = "true"*)reg [31:0] rst_cnt;    // 复位计数器
(*mark_debug = "true"*)reg rst_gen;           // 复位生成信号
(*mark_debug = "true"*)reg rst_state;         // 复位状态机// 复位控制状态机
always@(posedge clk_50m) beginif(!locked) beginrst_cnt <= 32'b0;rst_gen <= 1'b0;rst_state <= 1'b0;end else begincase(rst_state)1'd0 : beginif(channle_up_reg) beginrst_cnt <= 32'b0;rst_gen <= 1'b0;rst_state <= 1'b0;end else beginrst_cnt <= 32'b0;rst_gen <= 1'b1;rst_state <= 1'b1;endend    1'd1 : beginif(rst_cnt == 32'd50000000) beginif(channle_up_reg) beginrst_cnt <= 'b0;rst_gen <= 1'b0;rst_state <= 1'b0;end else beginrst_cnt <= 'b0;rst_gen <= 1'b1;rst_state <= 1'b1;end    end else if(rst_cnt < 32'd10000) beginrst_cnt <= rst_cnt + 1'b1;rst_gen <= 1'b1;rst_state <= 1'b1;end else beginrst_cnt <= rst_cnt + 1'b1;rst_gen <= 1'b0;rst_state <= 1'b1;endend    endcase end    
end

2.4 Aurora通信模块实例化

aurora_top inst_aurora_top (.init_clk(clk_50m),            // 初始化时钟.user_clk_i(user_clk_i),       // 用户时钟.CHANNEL_UP(CHANNEL_UP),       // 通道建立状态.RESET(rst_gen),               // 复位信号.GT_RESET_IN(rst_gen),         // GT复位信号.GTPQ0_P(GTPQ0_P),             // 光纤时钟正端.GTPQ0_N(GTPQ0_N),             // 光纤时钟负端.RXP(RXP),                     // 光纤接收正端.RXN(RXN),                     // 光纤接收负端.TXP(TXP),                     // 光纤发送正端.TXN(TXN),                     // 光纤发送负端.uart_rx(uart_rx),             // 串口接收.uart_tx(uart_tx)              // 串口发送
);

三、LED控制逻辑实现

3.1 信号声明与同步

// LED控制相关寄存器
reg [27:0] uart_rx_led_cnt [15:0];     // 接收LED计数器数组
reg [27:0] uart_tx_led_cnt [15:0];     // 发送LED计数器数组
reg [15:0] uart_rx_led_flag;           // 接收LED标志
reg [15:0] uart_tx_led_flag;           // 发送LED标志// 串口信号寄存器
reg [15:0] uart_rx_reg0, uart_tx_reg0, uart_rx_reg1, uart_tx_reg1;// 信号同步逻辑
always@(posedge clk_50m) beginuart_rx_reg0 <= uart_rx;uart_tx_reg0 <= uart_tx;uart_rx_reg1 <= uart_rx_reg0;uart_tx_reg1 <= uart_tx_reg0;
end

3.2 生成循环与状态机

genvar i;
generate for(i=0; i<16; i=i+1) begin : rs422_uart// 接收LED控制逻辑always@(posedge clk_50m) beginif(locked == 1'b0) beginuart_rx_state[i] <= 'b0;uart_rx_led_cnt[i] <= 'b0;uart_rx_led_flag[i] <= 1'b1;end else begincase(uart_rx_state[i]) 2'd0 : begin// 边沿检测if((!uart_rx_reg1[i]) && uart_rx_reg0[i] || (!uart_rx_reg0[i]) && uart_rx_reg1[i]) beginuart_rx_state[i] <= 2'd1;uart_rx_led_cnt[i] <= uart_rx_led_cnt[i] + 1'b1;uart_rx_led_flag[i] <= !uart_rx_led_flag[i];end else beginuart_rx_state[i] <= 'b0;uart_rx_led_cnt[i] <= 'b0;uart_rx_led_flag[i] <= 1'b1;endend2'd1 : beginif(uart_rx_led_cnt[i] == 28'd12500000) beginuart_rx_state[i] <= 2'd0;uart_rx_led_cnt[i] <= 'b0;uart_rx_led_flag[i] <= 1'b1;end else beginuart_rx_state[i] <= 2'd1;uart_rx_led_cnt[i] <= uart_rx_led_cnt[i] + 1'b1;uart_rx_led_flag[i] <= uart_rx_led_flag[i];end   enddefault : uart_rx_state[i] <= 2'd0;endcase                                                                endend   // 发送LED控制逻辑(类似接收逻辑)always@(posedge clk_50m) beginif(locked == 1'b0) beginuart_tx_state[i] <= 'b0;uart_tx_led_cnt[i] <= 'b0;uart_tx_led_flag[i] <= 1'b1;end else if(channle_up_reg == 1'b1) begincase(uart_tx_state[i]) 2'd0 : beginif((!uart_tx_reg1[i]) && uart_tx_reg0[i] || (!uart_tx_reg0[i]) && uart_tx_reg1[i]) beginuart_tx_state[i] <= 2'd1;uart_tx_led_cnt[i] <= uart_tx_led_cnt[i] + 1'b1;uart_tx_led_flag[i] <= !uart_tx_led_flag[i];end else beginuart_tx_state[i] <= 'b0;uart_tx_led_cnt[i] <= 'b0;uart_tx_led_flag[i] <= 1'b1;endend2'd1 : beginif(uart_tx_led_cnt[i] == 28'd12500000) beginuart_tx_state[i] <= 2'd0;uart_tx_led_cnt[i] <= 'b0;uart_tx_led_flag[i] <= 1'b1;end else beginuart_tx_state[i] <= 2'd1;uart_tx_led_cnt[i] <= uart_tx_led_cnt[i] + 1'b1;uart_tx_led_flag[i] <= uart_tx_led_flag[i];endenddefault : uart_tx_state[i] <= 'b0;endcase                                                             end else beginuart_tx_state[i] <= 'b0;uart_tx_led_cnt[i] <= 'b0;uart_tx_led_flag[i] <= 1'b1;    endendend
endgenerate

3.3 LED输出赋值

assign uart_rx_led = uart_rx_led_flag;
assign uart_tx_led = uart_tx_led_flag;
assign fpga_led[0] = !channle_up_reg;
assign fpga_led[1] = !channle_up_reg;

3.4 关键设计原理

边沿检测原理
// 检测信号从低到高的上升沿
(!uart_rx_reg1[i]) && uart_rx_reg0[i]// 检测信号从高到低的下降沿  
(!uart_rx_reg0[i]) && uart_rx_reg1[i]// 综合检测上升沿或下降沿
(!uart_rx_reg1[i]) && uart_rx_reg0[i] || (!uart_rx_reg0[i]) && uart_rx_reg1[i]
状态机设计
  • 状态0:等待信号变化,检测到变化后转到状态1
  • 状态1:LED闪烁延时,延时结束后回到状态0
时序控制
  • 使用50MHz时钟,计数到12500000需要0.25秒
  • LED闪烁持续0.25秒后自动熄灭
  • 每次检测到信号变化都会重新触发闪烁

第一部分结束,请查看第二部分文档继续了解Aurora通信接口、核心控制逻辑、调试功能和项目总结。

http://www.lryc.cn/news/590235.html

相关文章:

  • 数据结构-1(顺序表)
  • 关于 OpenAI 的反思
  • GESP2025年6月认证C++四级( 第三部分编程题(2)排序)
  • 多态,内部类(匿名内部类),常用API(1)
  • HTTP vs HTTPS
  • 【React Native】布局文件-顶部导航栏
  • 从零开始学习 Redux:React Native 项目中的状态管理
  • 3D TOF 安全防护传感器
  • Ubuntu 上 GBase 8s 实例重启与字符集踩坑实录
  • 在UE中如何给骨骼网格体赋予动画
  • conda activate 时报错: CondaError: Run ‘conda init‘ before ‘conda activate‘
  • React Native 在 Web 前端跨平台开发中的优势与实践
  • Django ORM 查询工具对象详解
  • 基于WebRTC技术实现一个在线课堂系统
  • 线上分享:解码eVTOL安全基因,构建安全飞行生态
  • 主机安全---开源wazuh安装
  • 前端面试题(React 与 Vue)
  • Elasticsearch+Logstash+Filebeat+Kibana部署
  • [时序数据库-iotdb]时序数据库iotdb的安装部署
  • C++11 std::uninitialized_copy_n 原理与实现
  • 边缘计算革命:AWS Snowcone在智慧工厂的落地实践(2025工业4.0实战指南)
  • Jenkins+Docker(docker-compose、Dockerfile)+Gitee实现自动化部署
  • 【时序数据库-iotdb】时序数据库iotdb的可视化客户端安装部署--dbeaver
  • Datawhale AI夏令营笔记-TF-IDF方法
  • 玩转Docker | 使用Docker部署vnStat网络流量监控服务
  • java之-文件预览终极解决方案
  • java工具类Hutool
  • 深度剖析C++生态系统:一门老牌语言如何在开源浪潮中焕发新生?
  • [Java安全】JDK 动态代理
  • 浅谈SQL注入注释符#和--+的运用场景和区别