【以太网通信】RS232 串口转以太网
最近和 RK 研发同事在调试通信接口,排查与定位 RK3399 接收数据出错的问题。FPGA 与 RK3399 之间使用一路 RS232 串口进行通信,由于串口数据没有分包,不方便排查问题,想到可以开发一个 RS232 串口转以太网的工具,将串口接收到的数据封装为 UDP 数据报文,并通过网线传输到电脑,再进行后续问题的定位。
以下是串口转以太网工具,调试的效果图。

目录
1 模块设计
1.1 串口接收模块
1.2 以太网发送模块
2 上板调试
1 模块设计
1.1 串口接收模块

串口接收模块电路需要实现的功能包括:
(1)串口数据接收;
(2)串口数据缓存。
uart_rx_slice 是串口底层模块,负责接收单个 byte 数据。规定串口每帧传输的数据长度不超过 2048,需要例化一个深度为 4096,位宽为 8bit 的 Block RAM,并实现串口数据的乒乓缓存。

top_uart 模块代码:
`timescale 1ns / 1psmodule top_uart #(parameter FREQ_SYS_CLK = 32'd200_000_000,parameter BAUD_RATE = 32'd256_000
)(// System levelinput sys_rst ,input sys_clk ,// Uart received data flowoutput [7:0] uart_rcv_data ,output uart_rcv_valid ,// Uart Interfaceinput uart_rxd ,output uart_txd
);wire frame_ss ;
wire [7:0] rcv_data ;
wire rcv_valid ;reg frame_ss_r1 ;
reg frame_ss_r2 ;
reg [7:0] blk_mem_wdata ;
reg [11:0] blk_mem_waddr ;
reg [11:0] blk_mem_waddr_r ;
reg [0:0] blk_mem_wren ;
reg blk_mem_rd_busy ;
reg [11:0] blk_mem_raddr ;
wire [7:0] blk_mem_rdata ;
reg blk_mem_rdvld ;// uart_rx_slice: Uart receive module
uart_rx_slice uart_rx_slice_inst (.sys_rst (sys_rst ), // input.sys_clk (sys_clk ), // input.frame_ss (frame_ss ), // output.rcv_data (rcv_data ), // output.rcv_valid (rcv_valid ), // output.uart_rxd (uart_rxd ) // input
);defparam uart_rx_slice_inst.FREQ_SYS_CLK = FREQ_SYS_CLK;
defparam uart_rx_slice_inst.BAUD_RATE = BAUD_RATE;
// End of uart_rx_slice instantiation// blk_mem_4096x8b: Block Memory generator
blk_mem_4096x8b blk_mem_4096x8b_inst (.clka (sys_clk ), // input.ena (1'b1 ), // input.wea (blk_mem_wren ), // input.addra (blk_mem_waddr ), // input.dina (blk_mem_wdata ), // input.clkb (sys_clk ), // input.rstb (sys_rst ), // input.enb (1'b1 ), // input.addrb (blk_mem_raddr ), // input.doutb (blk_mem_rdata ), // output.rsta_busy ( ), // output.rstb_busy ( ) // output
);
// End of blk_mem_4096x8b_inst instantiationalways @(posedge sys_rst or posedge sys_clk) beginif (sys_rst == 1'b1) beginframe_ss_r1 <= 1'b0;frame_ss_r2 <= 1'b0;endelse beginframe_ss_r1 <= frame_ss;frame_ss_r2 <= frame_ss_r1;end
endalways @(posedge sys_rst or posedge sys_clk) beginif (sys_rst == 1'b1) beginblk_mem_waddr <= 12'd0;blk_mem_wdata <= 8'd0;blk_mem_wren <= 1'b0;endelse beginblk_mem_wdata <= rcv_data;blk_mem_wren[0] <= rcv_valid;if (frame_ss_r2 == 1'b1 && frame_ss_r1 == 1'b0) beginblk_mem_waddr[11] <= ~blk_mem_waddr[11];blk_mem_waddr[10:0] <= {11{1'b0}};endelse if (blk_mem_wren[0] == 1'b1) beginblk_mem_waddr[11] <= blk_mem_waddr[11];blk_mem_waddr[10:0] <= blk_mem_waddr[10:0] + 1'b1;endend
endalways @(posedge sys_rst or posedge sys_clk) beginif (sys_rst == 1'b1) beginblk_mem_waddr_r <= 12'd0;blk_mem_raddr <= 12'd0;blk_mem_rd_busy <= 1'b0;blk_mem_rdvld <= 1'b0;endelse beginif (blk_mem_rd_busy == 1'b0 && frame_ss_r2 == 1'b1 && frame_ss_r1 == 1'b0) beginblk_mem_waddr_r <= blk_mem_waddr - 1'b1;blk_mem_rd_busy <= 1'b1;endelse if (blk_mem_rd_busy == 1'b1) beginif (blk_mem_raddr == blk_mem_waddr_r) beginblk_mem_raddr[11] <= ~blk_mem_raddr[11];blk_mem_raddr[10:0] <= {11{1'b0}};blk_mem_rd_busy <= 1'b0;endelse beginblk_mem_raddr[11] <= blk_mem_raddr[11];blk_mem_raddr[10:0] <= blk_mem_raddr[10:0] + 1'b1;endendblk_mem_rdvld <= blk_mem_rd_busy;end
endassign uart_rcv_data = blk_mem_rdata;
assign uart_rcv_valid = blk_mem_rdvld;endmodule
1.2 以太网发送模块

以太网网络层使用 IPv4 协议,传输层使用 UDP 协议。
以太网发送模块电路需要实现的功能包括:
(1)IPv4 与 UDP 协议校验;
(2)以太网帧组帧(包括 CRC 校验);
(3)GMII 与 RGMII 桥接。
同样例化一个深度为 4096,位宽为 8bit 的 Block RAM,实现以太网帧数据的乒乓缓存,在初始化文件中写入以太网帧头,MAC 地址等信息。
使用 Python 代码生成 coe 文件,代码如下:
# 以太网帧头数据
f = b'\x55\x55\x55\x55\x55\x55\x55\xd5\xd4\x5d\x64\xad\x16\x47\x11\x22\x33\x44\x55\x66\x08\x00\x45\x00\x00\x00\x00\x00\x40\x00\x40\x11\xff\xff\xc0\xa8\x01\x08\xc0\xa8\x01\x09\x1f\x90\x1f\x90\x00\x00\x00\x00'
raw_data = list(map(lambda e: "{:02X}".format(e), f))while len(raw_data) < 2048:raw_data.append('00')# 写入coe文件
with open('blk_mem_4096x8b_MAC.coe', 'w') as f:f.write('memory_initialization_radix = 16;\n')f.write('memory_initialization_vector = \n')for i,e in enumerate(raw_data*2):if i != len(raw_data*2)-1:f.write("{:s},\n".format(e))else:f.write("{:s};".format(e))
在 IP 核配置界面,选择 coe 初始化文件,点击 Edit 查看数据。

top_ethernet 模块代码:
`timescale 1ns / 1psmodule top_ethernet #(parameter local_ip_addr = 32'hC0A80109,parameter remote_ip_addr = 32'hC0A8010A,parameter local_udp_port = 16'h1F90,parameter remote_udp_port = 16'h1F90
)(// System levelinput sys_rst ,input sys_clk ,// RGMII Interfaceinput rgmii_rxc ,input [3:0] rgmii_rxd ,input rgmii_rx_ctl ,output rgmii_txc ,output [3:0] rgmii_txd ,output rgmii_tx_ctl ,// UDP data input portsinput [7:0] eth_udp_txd ,input eth_udp_txen
);wire gmii_tx_clk;
wire [7:0] eth_mac_txd;
wire eth_mac_txen;// mac_tx_slice: MAC data pack and transmit module
mac_tx_slice mac_tx_slice_inst(.sys_rst (sys_rst ), // input.sys_clk (sys_clk ), // input.gmii_tx_clk (gmii_tx_clk ), // input.eth_udp_txd (eth_udp_txd ), // input.eth_udp_txen (eth_udp_txen ), // input.eth_mac_txd (eth_mac_txd ), // output.eth_mac_txen (eth_mac_txen ) // output
);defparam mac_tx_slice_inst.local_ip_addr = local_ip_addr;
defparam mac_tx_slice_inst.remote_ip_addr = remote_ip_addr;
defparam mac_tx_slice_inst.local_udp_port = local_udp_port;
defparam mac_tx_slice_inst.remote_udp_port = remote_udp_port;
// End of mac_tx_slice_inst instantiation// gmii_rgmii_bright: GMII to RGMII bridge
util_gmii_to_rgmii util_gmii_to_rgmii (.reset (sys_rst ), // input.rgmii_td (rgmii_txd ), // output.rgmii_tx_ctl (rgmii_tx_ctl ), // output.rgmii_txc (rgmii_txc ), // output.rgmii_rd (rgmii_rxd ), // input.rgmii_rx_ctl (rgmii_rx_ctl ), // input.rgmii_rxc (rgmii_rxc ), // input.gmii_txd (eth_mac_txd ), // input.gmii_tx_en (eth_mac_txen ), // input.gmii_tx_er (1'b0 ), // input.gmii_tx_clk (gmii_tx_clk ), // output.gmii_crs ( ), // output.gmii_col ( ), // output.gmii_rxd ( ), // output.gmii_rx_dv ( ), // output.gmii_rx_er ( ), // output.gmii_rx_clk ( ), // output.speed_selection(2'b10 ), // input.duplex_mode (1'b1 ) // input
);
// End of util_gmii_to_rgmii_inst instantiationendmodule
2 上板调试
使用 ALINX AX7035 开发板,进行工程调试。红色的线接 USB 转串口接口,蓝色的线接入千兆网口。使用电脑模拟发送串口数据,并接收以太网数据。


电脑端同时打开串口调试助手,和 wireshark 工具,开始抓包。
在串口调试助手中输入待发送数据,选择定时 1s 发送,观察 wireshark 界面是否间隔 1s 收到数据包。

相关文章:
【以太网通信】RS232 串口转以太网
最近和 RK 研发同事在调试通信接口,排查与定位 RK3399 接收数据出错的问题。FPGA 与 RK3399 之间使用一路 RS232 串口进行通信,由于串口数据没有分包,不方便排查问题,想到可以开发一个 RS232 串口转以太网的工具,将串口…...
分享两道Java面试的算法上机题目(后续会持续补充更多)
所有题目参考答案均是小编自己想法,仅供参考,解法很多,大可不必局限,有更优解的大神无解,可评论或私聊博主指正! 题目1 找大串,给定一个字符串其中包含任意组连续字符,我们把超过3个…...
如何使用CSS实现一个平滑过渡效果?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现平滑过渡效果⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚…...
网络常见设备
目录 1.网络常见设备 1.交换路由设备 2.网络安全设备 3.无线网络设备 4.网络设备生产厂商 1.网络常见设备 当用户通过电子邮件给远方的朋友送去祝福时,一定不会想到这封邮件在网络中将会经历怎样复杂的行程。就好比将一封真实的信件投到邮局后,无法了解…...
数据结构与算法:通往编程高地的必修课(文末送书)
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
python小脚本——批量将PDF文件转换成图片
语言:python 3 用法:选择PDF文件所在的目录,点击 确定 后,自动将该目录下的所有PDF转换成单个图片,图片名称为: pdf文件名.page_序号.jpg 如运行中报错,需要自行根据报错内容按照缺失的库 例如&#x…...
cUrl的介绍和基本使用
cURL 如果你在开发接口的时候,需要调试。那么cUrl将是你必备的技能。也许你用过postman,但这个未免太重量级了。curl将会是你最佳轻量级,调试接口的工具😀 1.Curl函数的基本选项✨ 1.1 --request和 -x —request 和 -X 指定与HTTP服务器通信…...
ONLYOFFICE协作空间服务器如何一键安装自托管私有化部署
ONLYOFFICE协作空间服务器如何一键安装自托管私有化部署 如何在 Ubuntu 上部署 ONLYOFFICE 协作空间社区版?https://blog.csdn.net/m0_68274698/article/details/132069372?ops_request_misc&request_id&biz_id102&utm_termonlyoffice%20%E5%8D%8F%E4…...
java分析公司名称:AI智能工具助力提取地名、品牌名、行业名
java分析公司名称:AI智能工具助力提取地名、品牌名、行业名 一、java智能提取地名 /*** 通过“武汉”补全省市区* throws Exception*/public void getPlace4() throws Exception{String r1 "武汉";String fileName2 "D:\\Personal\\Desktop\\txt…...
php 二维数组排序
要对二维数组进行排序,可以使用 PHP 的函数 array_multisort()。该函数可以按照指定的键值对对数组进行排序。 下面是一个示例代码,展示如何对二维数组按照某个键进行排序: // 定义一个二维数组 $students array(array(name > John, ag…...
postgresql 性能调优
性能调优是为了提高 PostgreSQL 数据库的性能和响应速度。下面是一些常见的 PostgreSQL 性能调优技巧: 1 确保合适的硬件资源:确保数据库服务器具有足够的内存、处理器和磁盘空间,以满足数据库负载的需求。2 优化查询语句:检查并优…...
派森 #P128. csv存json格式
描述 编写一个 Python 程序,读取movie.in(csv格式,utf-8编码) 的数据,将数据转成保存到movie.out(接送格式,utf-8编码)文件中。 格式 输入 movie.in文件,测试格式,utf-8编码。 …...
iPhone开启“轻点唤醒”功能但点击屏幕无反应怎么解决?
iPhone的“轻点唤醒”功能启用时,用户只需手指轻触或点击手机屏幕即可快速唤醒设备,无需按压任何按钮。然而,有些用户在使用“轻点唤醒”功能唤醒屏幕时,遇到该功能失灵,无法正常唤醒屏幕的情况,这是怎么回…...
论AI与大数据之间的关系
前言 在21世纪,"AI"和"大数据"已经成为科技领域的热门词汇。它们不仅是创新的代名词,更是现代技术发展的双翼。然而,很多人对于AI与大数据之间的关系仍然停留在表面的理解。本文旨在深入探讨这两者之间的深厚关系&#…...
6.ES基础概念及术语详细解读
一、Elasticsearch概述: ES是基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全问搜索引擎,且ES支持RestFulweb风格的url访问。ES是基于Java开发的开源搜索引擎,设计用于云计算,能够达到实时搜索,…...
大语言模型微调实践——LoRA 微调细节
1. 引言 近年来人工智能领域不断进步,大语言模型的崛起引领了自然语言处理的革命。这些参数量巨大的预训练模型,凭借其在大规模数据上学习到的丰富语言表示,为我们带来了前所未有的文本理解和生成能力。然而,要使这些通用模型在特…...
国内ChatGPT对比与最佳方案
很久没写内容了,主要还是工作占据了太多时间。简单分享下我这段时间的研究吧,由于时间仓促,有很多内容没有具体写,请自行到我分享的网站体验查看。 前言 ChatGPT 的出现确实在很大程度上改变了世界。许多人已经亲身体验到了ChatGPT作为一个…...
绝美的古诗词AI作画,惊艳到我了!
前言 时光荏苒,科技的飞速发展催生出了许多令人惊叹的创新成果。近年来,人工智能技术在艺术领域的应用日益引人注目,其中最为引人瞩目的莫过于AI作画。这项技术将传统的古诗词与现代的人工智能相结合,创造出一幅幅令人叹为观止的…...
数据结构—排序
8.排序 8.1排序的概念 什么是排序? 排序:将一组杂乱无章的数据按一定规律顺序排列起来。即,将无序序列排成一个有序序列(由小到大或由大到小)的运算。 如果参加排序的数据结点包含多个数据域,那么排序往…...
GraphScope,开源图数据分析引擎的领航者
文章首发地址 GraphScope是一个开源的大规模图数据分析引擎,由Aliyun、阿里巴巴集团和华为公司共同开发。GraphScope旨在为大规模图数据处理和分析提供高性能、高效率的解决方案。 Github地址: https://github.com/alibaba/GraphScope GraphScope 的重…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
