万兆以太网MAC设计(2)MAC_RX模块
文章目录
- 前言
- 一、模块功能
- 二、代码
- 三、仿真波形
前言
上文我们打通了了万兆以太网物理层和数据链路层,其实就是会使用IP核了,本文将正式开始MAC层设计第一篇,接收端设计。
一、模块功能
MAC_RX模块功能如下:
- 解析接收的报文:接受报文的目的MAC、源MAC、报文类型
- 将XGMII接口输入数据转化为AXIS的数据流形式传递给上层用户
难点在于数据格式的转化,最主要的是尾端KEEP信号该如何与有效数据进行对齐。
数据恢复的过程:
- 判断起始位SOF和起始位的位置:起始字节8‘hFB’位置存在俩种情况:第一种情况自然是在接收数据的第一个字节位置,但也存在在第五个字节位置的情况,所以需要分情况讨论。

- 关键字段信息提取:根据起始位置的不同,目的MAC以及源MAC和类型信息都要分情况进行讨论。
- 数据恢复:同理,恢复数据也需要讨论。
- 结束位EOF以及结束位的位置判断 :结束位有八种情况,一拍数据64bit,结束位可能存在在任何一个byte上。
- 尾端KEPP对齐,根据起始位位置以及结束位位置,尾端KEEP信号需要讨论各种情况。
- AXIS数据转换 :前面相当于把KEEP和DATA信号处理好了,然后还需要产生VALID、LAST、USER信号。
二、代码
设计思路参考了FPGA奇哥系列网课
注意一下几点:
- 老生常谈的大小端问题,进入该模块的数据全部应该是大端数据,我完全是按照大端进行处理的。
- LAST信号和KEEP信号分类讨论条件是一样的,俩者是在数据尾端同时进行变化的,根据最后一拍有效数据字节数的多少,LAST信号会在不同的时刻拉高(在r_eof拉高或w_eof拉高时刻)。
- USER信号是用户自定义的,我这里暂时定义为接收数据的源MAC的低16位加类型(16位)。
- 万兆以太网控制字符定义:

module TEN_GIG_MAC_RX(input i_clk ,input i_rst ,input [63:0] i_xgmii_rxd ,input [7 :0] i_xgmii_rxc ,output [63:0] m_axis_rdata ,output [31:0] m_axis_ruser ,//用户自定义{r_src_mac[15:0],r_type}output [7 :0] m_axis_rkeep ,output m_axis_rlast ,output m_axis_rvalid
);
/******************************function*****************************//******************************parameter****************************/
localparam P_FRAME_IDLE = 8'h07 ,P_FRAME_START = 8'hFB ,P_FRAME_END = 8'hFD ,P_FRAME_EEROR = 8'hFE ;
/******************************mechine******************************//******************************reg**********************************/
reg [63:0] ri_xgmii_rxd ;
reg [63:0] ri_xgmii_rxd_1d ;
reg [7 :0] ri_xgmii_rxc ;
reg [7 :0] ri_xgmii_rxc_1d ;
reg [63:0] rm_axis_rdata ;
//reg [63:0] rm_axis_rdata_1d ;
reg [31:0] rm_axis_ruser ;
reg [7 :0] rm_axis_rkeep ;
reg rm_axis_rlast ;
reg rm_axis_rvalid ;
//解析接收数据
reg [15:0] r_recv_cnt ;
reg r_comma ;
reg [47:0] r_dst_mac ;
reg [47:0] r_src_mac ;
reg [15:0] r_type ;
reg r_data_run ;//开始产生axis输出数据
reg r_data_run_1d ;
reg r_data_run_2d ;reg r_sof ;
reg r_eof ;
reg [2 :0] r_sof_location ;
reg [2 :0] r_eof_location ;
/******************************wire*********************************/
wire w_sof ;
wire w_eof ;
wire [2 :0] w_sof_location ;
wire [2 :0] w_eof_location ;
/******************************component****************************//******************************assign*******************************/
assign m_axis_rdata = rm_axis_rdata ;
assign m_axis_ruser = rm_axis_ruser ;
assign m_axis_rkeep = rm_axis_rkeep ;
assign m_axis_rlast = rm_axis_rlast ;
assign m_axis_rvalid = rm_axis_rvalid ;
//进入该模块的数据已经全部被转换为大端模式
//开始字符以及位置判断
assign w_sof = ((ri_xgmii_rxd[63:56] == P_FRAME_START) && (ri_xgmii_rxc[7] == 1)) || ((ri_xgmii_rxd[31:24] == P_FRAME_START) && (ri_xgmii_rxc[3] == 1));
assign w_sof_location = ((ri_xgmii_rxd[63:56] == P_FRAME_START) && (ri_xgmii_rxc[7] == 1)) ? 7 : ((ri_xgmii_rxd[31:24] == P_FRAME_START) && (ri_xgmii_rxc[3] == 1)) ? 3 :0;
//结束字符以及位置判断
assign w_eof = ((ri_xgmii_rxd[63:56] == P_FRAME_END) && (ri_xgmii_rxc[7] == 1)) || ((ri_xgmii_rxd[55:48] == P_FRAME_END) && (ri_xgmii_rxc[6] == 1)) ||((ri_xgmii_rxd[47:40] == P_FRAME_END) && (ri_xgmii_rxc[5] == 1)) ||((ri_xgmii_rxd[39:32] == P_FRAME_END) && (ri_xgmii_rxc[4] == 1)) ||((ri_xgmii_rxd[31:24] == P_FRAME_END) && (ri_xgmii_rxc[3] == 1)) ||((ri_xgmii_rxd[23:16] == P_FRAME_END) && (ri_xgmii_rxc[2] == 1)) ||((ri_xgmii_rxd[15: 8] == P_FRAME_END) && (ri_xgmii_rxc[1] == 1)) ||((ri_xgmii_rxd[7 : 0] == P_FRAME_END) && (ri_xgmii_rxc[0] == 1));assign w_eof_location = ((ri_xgmii_rxd[63:56] == P_FRAME_END) && (ri_xgmii_rxc[7] == 1)) ? 7 : ((ri_xgmii_rxd[55:48] == P_FRAME_END) && (ri_xgmii_rxc[6] == 1)) ? 6 :((ri_xgmii_rxd[47:40] == P_FRAME_END) && (ri_xgmii_rxc[5] == 1)) ? 5 :((ri_xgmii_rxd[39:32] == P_FRAME_END) && (ri_xgmii_rxc[4] == 1)) ? 4 :((ri_xgmii_rxd[31:24] == P_FRAME_END) && (ri_xgmii_rxc[3] == 1)) ? 3 :((ri_xgmii_rxd[23:16] == P_FRAME_END) && (ri_xgmii_rxc[2] == 1)) ? 2 :((ri_xgmii_rxd[15: 8] == P_FRAME_END) && (ri_xgmii_rxc[1] == 1)) ? 1 :((ri_xgmii_rxd[7 : 0] == P_FRAME_END) && (ri_xgmii_rxc[0] == 1)) ? 0 : 0;
/******************************always*******************************/
always @(posedge i_clk or posedge i_rst)beginif(i_rst)beginri_xgmii_rxd <= 'd0;ri_xgmii_rxc <= 'd0;ri_xgmii_rxd_1d <= 'd0;ri_xgmii_rxc_1d <= 'd0;endelse beginri_xgmii_rxd <= i_xgmii_rxd ;ri_xgmii_rxc <= i_xgmii_rxc ;ri_xgmii_rxd_1d <= ri_xgmii_rxd ;ri_xgmii_rxc_1d <= ri_xgmii_rxc ;end
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)beginr_sof <= 'd0;r_sof_location <= 'd0;endelse if(w_sof)beginr_sof <= w_sof ;r_sof_location <= w_sof_location ;endelse beginr_sof <= 'd0 ;r_sof_location <= r_sof_location ;end
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)beginr_eof <= 'd0;r_eof_location <= 'd0;endelse if(w_eof)beginr_eof <= w_eof ;r_eof_location <= w_eof_location ;endelse beginr_eof <= 'd0 ;r_eof_location <= r_eof_location ; end
end always @(posedge i_clk or posedge i_rst)beginif(i_rst)r_comma <= 'd0;else if(r_eof)r_comma <= 'd0;else if((r_sof_location == 7) && (ri_xgmii_rxd_1d[55:0] == 56'h55_5555_5555_5555) && (ri_xgmii_rxd[63:56] == 8'hd5))r_comma <= 'd1;else if((r_sof_location == 3) && (ri_xgmii_rxd_1d[23:0] == 24'h55_5555) && (ri_xgmii_rxd[63:24] == 40'h55_5555_55d5))r_comma <= 'd1;elser_comma <= r_comma;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_recv_cnt <= 'd0;else if(r_eof)r_recv_cnt <= 'd0;else if(r_sof | r_recv_cnt)r_recv_cnt <= r_recv_cnt + 'd1;elser_recv_cnt <= r_recv_cnt;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_dst_mac <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 1)r_dst_mac <= ri_xgmii_rxd_1d[55:8];else if(r_sof_location == 3 && r_recv_cnt == 1)r_dst_mac <= {ri_xgmii_rxd_1d[23:0],ri_xgmii_rxd[63:40]};elser_dst_mac <= r_dst_mac;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_src_mac <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 1)r_src_mac <= {ri_xgmii_rxd_1d[7:0],ri_xgmii_rxd[63:24]};else if(r_sof_location == 3 && r_recv_cnt == 2)r_src_mac <= {ri_xgmii_rxd_1d[39:0],ri_xgmii_rxd[63:56]};elser_src_mac <= r_src_mac;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_type <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 2)r_type <= ri_xgmii_rxd_1d[23:8];else if(r_sof_location == 3 && r_recv_cnt == 3)r_type <= ri_xgmii_rxd_1d[55:40];elser_type <= r_type;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)r_data_run <= 'd0;else if(rm_axis_rlast)r_data_run <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 1)r_data_run <= 'd1;else if(r_sof_location == 3 && r_recv_cnt == 2)r_data_run <= 'd1;elser_data_run <= r_data_run;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)beginr_data_run_1d <= 'd0;r_data_run_2d <= 'd0;endelse beginr_data_run_1d <= r_data_run;r_data_run_2d <= r_data_run_1d;end
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rdata <= 'd0;else if(rm_axis_rlast)rm_axis_rdata <= 'd0;else if(r_sof_location == 7 && r_data_run)rm_axis_rdata <= {ri_xgmii_rxd_1d[7:0],ri_xgmii_rxd[63:8]};else if(r_sof_location == 3 && r_data_run)rm_axis_rdata <= {ri_xgmii_rxd_1d[39:0],ri_xgmii_rxd[63:40]};elserm_axis_rdata <= 'd0;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_ruser <= 'd0;else if(r_sof_location == 7 && r_recv_cnt == 2)rm_axis_ruser <= {r_src_mac,ri_xgmii_rxd_1d[23:8]};else if(r_sof_location == 3 && r_recv_cnt == 3)rm_axis_ruser <= {r_src_mac,ri_xgmii_rxd_1d[55:40]};elserm_axis_ruser <= rm_axis_ruser;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rkeep <= 'd0;else if(r_sof_location == 7 && w_eof)case (w_eof_location)7 : rm_axis_rkeep <= 8'b1000_0000;6 : rm_axis_rkeep <= 8'b1100_0000;5 : rm_axis_rkeep <= 8'b1110_0000;4 : rm_axis_rkeep <= 8'b1111_0000;3 : rm_axis_rkeep <= 8'b1111_1000;2 : rm_axis_rkeep <= 8'b1111_1100;1 : rm_axis_rkeep <= 8'b1111_1110;0 : rm_axis_rkeep <= 8'b1111_1111;default : rm_axis_rkeep <= 8'b1111_1111;endcaseelse if(r_sof_location == 3 && (w_eof && w_eof_location >= 4))case (w_eof_location)7 : rm_axis_rkeep <= 8'b1111_1000;6 : rm_axis_rkeep <= 8'b1111_1100;5 : rm_axis_rkeep <= 8'b1111_1110;4 : rm_axis_rkeep <= 8'b1111_1111;3 : rm_axis_rkeep <= 8'b1000_0000;2 : rm_axis_rkeep <= 8'b1100_0000;1 : rm_axis_rkeep <= 8'b1110_0000;0 : rm_axis_rkeep <= 8'b1111_0000;default : rm_axis_rkeep <= 8'b1111_1111;endcaseelse if(r_sof_location == 3 && (r_eof && r_eof_location < 4))case (r_eof_location)7 : rm_axis_rkeep <= 8'b1111_1000;6 : rm_axis_rkeep <= 8'b1111_1100;5 : rm_axis_rkeep <= 8'b1111_1110;4 : rm_axis_rkeep <= 8'b1111_1111;3 : rm_axis_rkeep <= 8'b1000_0000;2 : rm_axis_rkeep <= 8'b1100_0000;1 : rm_axis_rkeep <= 8'b1110_0000;0 : rm_axis_rkeep <= 8'b1111_0000;default : rm_axis_rkeep <= 8'b1111_1111;endcaseelserm_axis_rkeep <= 8'b1111_1111;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rlast <= 'd0;else if(r_sof_location == 7 && w_eof)rm_axis_rlast <= 'd1;else if(r_sof_location == 3 && (w_eof && w_eof_location >= 4))rm_axis_rlast <= 'd1;else if(r_sof_location == 3 && (r_eof && r_eof_location < 4))rm_axis_rlast <= 'd1;elserm_axis_rlast <= 'd0;
endalways @(posedge i_clk or posedge i_rst)beginif(i_rst)rm_axis_rvalid <= 'd0;else if(rm_axis_rlast)rm_axis_rvalid <= 'd0;else if(r_data_run && !r_data_run_1d)rm_axis_rvalid <= 'd1;elserm_axis_rvalid <= rm_axis_rvalid;
endendmodule
三、仿真波形
仿真文件当中要遍历所有的起始位置与结束为止组合,一共16种。

以起始位在第五个byte,结束位在第一个byte为例,其波形如下,结果正确,对比其他16种情况,波形全部正确。

相关文章:
万兆以太网MAC设计(2)MAC_RX模块
文章目录 前言一、模块功能二、代码三、仿真波形 前言 上文我们打通了了万兆以太网物理层和数据链路层,其实就是会使用IP核了,本文将正式开始MAC层设计第一篇,接收端设计。 一、模块功能 MAC_RX模块功能如下: 解析接收的报文&…...
D. Solve The Maze Codeforces Round 648 (Div. 2)
题目链接: Problem - 1365D - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/problemset/problem/1365/D 题目大意: 有一张地图n行m列(地图外面全是墙),…...
CPU核心数、线程数都是什么意思?
最早,每个物理 cpu 上只有一个核心,对操作系统而言,也就是同一时刻只能运行一个进程/线程。 为了提高性能,cpu 厂商开始在单个物理 cpu 上增加核心(实实在在的硬件存在),也就出现了多核 cpu&…...
每日一篇 4.12
misstep:失误 epic proportions.:史无前例 arguably:按理来说 assembly:组装 performed :执行 underpins:支撑 holds a monopoly:垄断了 shipped:发货 a market capitalizati…...
鸿蒙南向开发:【智能烟感】
样例简介 智能烟感系统通过实时监测环境中烟雾浓度,当烟雾浓度超标时,及时向用户发出警报。在连接网络后,配合数字管家应用,用户可以远程配置智能烟感系统的报警阈值,远程接收智能烟感系统报警信息。实现对危险及时报…...
【主题广|检索稳定】2024年生态工程与农业科技国际会议 (EEAT 2024)
2024年生态工程与农业科技国际会议 (EEAT 2024) 2024 International Conference on Ecological Engineering and Agricultural Technology 【会议简介】 2024年生态工程与农业科技国际会议即将在贵阳召开。本次会议将汇集全球生态工程与农业科技领域的专家学者,共…...
代码随想录算法训练营第三十八天|509. 斐波那契数、 70. 爬楼梯、746. 使用最小花费爬楼梯
509 题目: 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2),…...
07-app端文章搜索
app端文章搜索 1) 今日内容介绍 1.1)App端搜索-效果图 1.2)今日内容 文章搜索 ElasticSearch环境搭建 索引库创建 文章搜索多条件复合查询 索引数据同步 搜索历史记录 Mongodb环境搭建 异步保存搜索历史 查看搜索历史列表 删除搜索历史 联想词查询 联想词的来源 联…...
✔ ★Java项目——设计一个消息队列(二)
Java项目——设计一个消息队列 四. 项⽬创建五. 创建核⼼类创建 Exchange(名字、类型、持久化)创建 MSGQueue(名字、持久化、独占标识)创建 Binding(交换机名字、队列名字、bindingKey用于与routingKey匹配)…...
Java语言实现生产者/消费者问题
经典例题:生产者/消费者问题 生产者(Productor)将产品放在柜台(Counter),而消费者(Customer)从柜台 处取走产品,生产者一次只能生产固定数量的产品(比如:1), 这时柜台中不能 再放产品,此时生产者应停止生产等待消费者…...
bugku-web-file_get_contents
<?php extract($_GET); if (!empty($ac)){$f trim(file_get_contents($fn));if ($ac $f){echo "<p>This is flag:" ." $flag</p>";}else{echo "<p>sorry!</p>";} } ?> 这里涉及到几个不常用的函数 这里直接构…...
Python数据处理和常用库(如NumPy、Pandas)
Python是一种功能强大的编程语言,广泛应用于数据处理和分析领域。在Python中,有一些常用的库可以帮助我们进行数据处理和分析,其中包括NumPy和Pandas。下面是关于这两个库的简介和使用示例:NumPy(Numerical Python&…...
[SystemVerilog]Simulation and Test Benches
Simulation and Test Benches 测试语言中有很大一部分专门用于测试台和测试。在本章中,我们将介绍为硬件设计编写高效测试台的一些常用技术。 6.1 How SystemVerilog Simulator Works 在深入研究如何编写适当的测试台之前,我们需要深入了解模拟器的工作原…...
lightgbm-安装失败(解决方案)
1.pip install lightgbm 报错,出现长篇标黄和标红的,本人表示看不懂,直接忽略,如下所示: 2.尝试pip install lightgbm -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com,安装也报错&…...
halcon图像相减算子sub_image
1.图像相减算子 sub_image(ImageMinuend , ImageSubtrahend : ImageSub : Mult , Add :) (1)参数解释: ImageMinuend :输入参数需要被减的图片 ImageSubtrahend :输入参数拿来减的图片 ImageSub :输出…...
final、finally 和 finalize 有什么区别?
final 是一个关键字,用于声明一个类、方法或变量。当用 final 修饰一个类时,表示该类不能被继承;当用 final 修饰一个方法时,表示该方法不能被子类重写;当用 final 修饰一个变量时,表示该变量只能被赋值一次…...
智能运维场景 | 科技风险预警,能实现到什么程度?
[ 原作者:擎创夏洛克,本文略做了节选和改编 ] 每次一说到“风险预警”,就会有客户问我们能做怎样的风险预警。实际上在智能运维厂商来说,此风险非彼风险,不是能做银行的业务上的风险预警(比如贷款风险等&a…...
中颖51芯片学习3. 定时器
中颖51芯片学习3. 定时器 一、SH79F9476定时器简介1. 简介2. 定时器运行模式 二、定时器21. 说明(1)时钟(2)工作模式 2. 寄存器(1)控制寄存器 T2CON(2)定时器2模式控制寄存器 T2MOD …...
[python] Numpy库用法(持续更新)
先导入一下 import numpy as np 一、np.random用法 生成随机整数:np.random.randint(low, high, size) low: 最小值high: 最大值size: 生成的数组大小(可以是多维,下面同理) 生成随机浮点数:np.random.uniform(low, …...
vue快速入门(十七)v-model数据双向绑定修饰符
注释很详细,直接上代码 上一篇 新增内容 v-model.trim 自动去除首尾空格v-model.number 自动转换成数字类型 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" con…...
谷歌账户注册改用发短信验证,注重隐私者如何创建新账户成焦点?
谷歌账户注册方式变更 2026年3月8日下午2点20分,anon28387880称谷歌创建新账户时用二维码取代短信验证,自己试过无法再用二维码注册。扫描智能手机二维码会触发手机向谷歌发短信验证手机号。据说这是为安全考虑,能增加钓鱼难度,但…...
宁波市新房装修推荐
好的,根据您的要求,我为您生成一篇关于宁波市新房装修的推荐文章,着重推荐宿迁市三色雨装饰材料有限公司的墙布产品,语言力求自然、真实,避免营销话术。宁波新房装修,墙面选择不妨多看看“三色雨”在宁波&a…...
2026年主流地图API AI功能开发与零代码工具横评
核心观点摘要 行业趋势判断:AI与零代码正深度融合地图API开发,推动位置智能从专业编码向业务自助快速演进,2026年主流平台将在多模态数据融合与行业化场景能力上形成分水岭。选型关键维度:需综合考量数据覆盖广度、模型智能水平、…...
ISSCC传感器设计启示:从高精度温度测量到低功耗系统优化
1. 从ISSCC看传感器设计的巅峰与启示每年二月的国际固态电路会议,对于像我这样泡在实验室和产线里的硬件工程师来说,就像一场技术界的“春晚”。它不发布概念,不空谈趋势,只展示过去一年里,全球顶尖研究团队在硅片上实…...
别再傻傻传文件了!用Java Base64把图片和PDF直接“塞”进HTML页面(附完整代码)
告别文件传输:Java Base64技术实现图片与PDF的HTML直嵌方案 在Web开发中,我们经常遇到需要将图片或PDF文档直接嵌入HTML页面的场景。传统做法通常需要先将文件上传到服务器,然后通过URL引用,这不仅增加了网络请求,还引…...
CVPR2019 Oral论文DVC复现指南:用TensorFlow搭建你的第一个端到端深度学习视频压缩模型
CVPR2019 Oral论文DVC复现实战:从零构建端到端视频压缩模型 视频压缩技术正经历从传统编码标准向深度学习范式的革命性转变。2019年CVPR Oral论文《DVC: An End-to-end Deep Video Compression Framework》首次提出了完整的端到端深度学习视频压缩框架,其…...
应用安全从被动到主动:企业如何提升弹性与可靠性,降低安全债务?
ZDNET核心观点应用安全需董事会层面问责,企业文化影响“设计即安全”工作,运营模式将预防转化为行动。企业聚焦软件策略改变网络安全结果,挑战是在开发周期早期融入安全措施,构建捕捉漏洞和隐患的工具技术。本文将从被动到主动的转…...
实战配置指南:5个技巧让PlayStation手柄在Windows上发挥专业级性能
实战配置指南:5个技巧让PlayStation手柄在Windows上发挥专业级性能 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows DS4Windows是一款功能强大的开源控制器兼容工具,…...
Diem存储协议终极指南:如何构建高性能分布式文件存储系统
Diem存储协议终极指南:如何构建高性能分布式文件存储系统 【免费下载链接】diem Diem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world. 项目地址: https://gitcode.com/gh_mirrors/di…...
NanoSVG完整教程:从SVG文件解析到贝塞尔曲线渲染
NanoSVG完整教程:从SVG文件解析到贝塞尔曲线渲染 【免费下载链接】nanosvg Simple stupid SVG parser 项目地址: https://gitcode.com/gh_mirrors/na/nanosvg NanoSVG是一款轻量级的SVG解析库,能够将SVG文件高效转换为贝塞尔曲线数据,…...
