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通信接口、核心控制逻辑、调试功能和项目总结。