【以太网通信】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 的重…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
