有些人喜欢直接拿开发板看教程开干,我认为了解点历史发展没什么坏处,一些FPGA的基础知识也是同样重要的。
有个粉丝评论说建议把总结写在前面,估计多半是被中间大段文字折磨后看到我说其实大段文字也可以浏览浏览就行了。
总结:如果你能从头看到尾,说明你是真🐂,本文主要是一个FPGA的学前基础知识科普。中间大段的文字看起来很费解的可以浏览一下就可以了。
1.1. FPGA的主要厂商
XILINX |
占据FPGA绝大部分的市场份额 |
ALTERA 被 INTEL 167亿美元收购 改名为INTEL | |
LATTICE 被神秘的中国公司收购 |
瓜分军用 低功耗 等细分市场 |
ACTEL | |
国产: |
硬件可以逆向工程抄,瓶颈是开发环境 – 技术支持 |
1.2. FPGA发展史
为什么要采用可编程逻辑器件呢?
典型的系统设计 需要较大的电路板 容纳这些器件 提高 系统的设计成本和复杂度 |
简化的系统设计 把CPU I/O DSP 放在一个器件中,形成单片的片上可编程系统(SOPC system on programmable chip) 采用可编程逻辑器件代替外部器件,去掉很多硬件,降低成本和功耗 |
1.2.1晶体管-晶体管逻辑集成电路(TTL, Transistor-Transistor Logic)
TTL出来之前,使用分立的逻辑门芯片来实现设计,如NAND(与非门)、OR(或门)、复用器、触发器等
TTL出来之后,TTL被用来实现 尽量减少芯片的设计,好处是:降低成本,减少电路板的面积,常用TI(德州仪器)7400系列。 5400系列一般是军用
TTL是如何实现某种逻辑
① 首先是写出真值表 A B C D是输入,X是输出 |
② 然后转换成卡诺图 ③ 然后转换成逻辑表达式 |
④ 最后就是用TTL器件实现了 两级的逻辑,AB + CD + BD + BC + AD + AC这个叫做乘积和 |
1.2.2 从TTL 到 可编程逻辑阵列 (PAL, Programmable Array Logic)
在介绍此部分内容之前,请忘掉TTL没有6输入的或门器件这件事情。
再回到刚刚的那个逻辑表达式。 X = AB + CD + BD + BC + AD + AC。 我们管这个叫做乘积和,很容易理解,就是先乘积,再求和。
这里请直接记住一个事实,任何一个逻辑都可以使用乘积和的组合逻辑来表示。
X = AB + CD + BD + BC + AD + AC,这个逻辑表达式最方便的实现方式,还是6个2输入的与门和1个6输入的或门。
注意啦, PAL的每个基本的单元(宏单元),就是用N个N输入的与门和1个N输入的或门+一个寄存器组成的。如下图所示:
这个实现了 可编程乘积和阵列 和 输出控制
想象一个非常复杂的逻辑,比如100个输入的, 如果用TTL去搭的话,也要搭一大片电路板, 但是用PAL就可以只需要一个100输入的宏单元。
针对某个具体逻辑的时, 可编程阵列的线路连接是可以确定的。 确定之后,就可以直接给他连上啦。
最开始的时候,这个操作是一次性的,意思就是你把某些连接固定住了,它就无法改变,无法擦除了。
而如果有某种技术手段能够 反复的 修改和擦除 这个阵列交叉点的连接, 就实现了可编程。
不同的技术手段主要取决于 阵列交叉点 使用的 浮栅晶体管。 根据阵列交叉点上使用的器件不同 ,构成了反熔丝技术、EPROM技术和EEPROM技术。
它的意思是这个东西可以用编程来让它关闭。
正常情况下,是下面这样的。
如果我编程了之后,进行了某种操作之后,即使你在栅极加电,我也不会导通了。
看不懂不纠结,反正记住交叉点的那个位置是否连接,是可编程的就可以了。
1.2.3 从PAL 到 可编程逻辑器件 (PLD, Programmable Logic Device)
多个PAL构成了PLD。
注意: 原来的PAL是说,我可以用编程来改变下图左边的这些阵列交叉点的连接。 即 可变的乘积项分配。
现在, 咱们的PLD, 不仅由多个PAL组成,同时又添加了可编程宏单元,里面有寄存器啊,时钟啊,反馈啊,很多东西,能够实现更复杂的功能。
下面看看可编程宏单元里面有什么。
这样的设计,使得PLD 才是真正成为了可编程逻辑器件, 可以投入使用啦。
1.2.4 从PLD 到 复杂可编程逻辑器件 (CPLD, Complex Programmable Logic Device)
从PLD到CPLD的发展, 与从PLA到PLD的发展相似,
PLD由多个PLA构成,可编程宏单元是PLD主要贡献
CPLD由 多个PLD构成,采用可编程互联 和 与逻辑分离的I/O控制模块 连接多个PLD,这是CPLD的主要贡献, 这样一来, PLD功能就再次强大化啦。
上图的逻辑模块,全称叫做逻辑阵列模块,(Logic Array Block)。
相比于PLA,CPLD的LAB里面一般包含4-20个宏单元,而且宏单元添加了扩展乘积项,这是一种减少逻辑浪费的高效方法,代价是增加额外时延。
可编程互联阵列(PI/PIA)
一个LAB有4-20个宏单元, 一个CPLD有多个LAB,与PAL可编程阵列相似,LAB之间的互联, 全局布线连接器件中的任何信号和任何目的位置,采用EPROM、EEPROM或者闪存技术进行编程
I/O控制模块
由PI将其与逻辑分开,I/O专用逻辑提供控制以及更多功能,三态缓存控制实现任意I/O引脚的输入、输出或者双向功能
反正就是NB了
在线编程:
PAL或者PLD必须放在特定的编程单元当中,在正确的I/O口上加上正确的编程电压,这违背了在系统在线编程的理念,因为他需要把器件从电路板上拿下,放在编程单元当中,重新的编程。 或者在电路板上放一些特殊装置来进行编程。
为了避免这样, CPLD和FPGA包括了和设计I/O分开的编程接口,几乎所有的FPGA和CPLD都采用了一种流行的接口,是JTAG接口。
JTAG接口是简单的4线或者5线串行接口,构成单个器件长移位寄存器,或者,多个器件链。器件上的JTAG接口 一般作为器件自测试的一部分,来保证器件制造合格正常工作,数据在TDI输入上移入,在TDO输出上移出,如果输出和输入相匹配,则器件通过测试。
如果PLD本身可以产生编程所需要的电压,JTAG的接口能够控制,并指导芯片,在器件的哪一部分加上编程电压,这就简化了在实验室或者电路板产品线上对PLD的百编程,JTAG是业界的标准,因此任何JTAG的接口都可以进行器件自测试,然而通常需要,特殊控制器才能够通过 链接和供应商的器件进行绘画,实现编程,例如ALTERA器件使用ALTERA编程电缆,USB-Blaster和Byte-Blaser-II(并口),下载电缆,两种,一种是支持USB,一种是支持并口,JTAG的编程非常适合,应用在EEPROM器件上,这是因为编程是非易失的,在离去实验室之后,还需要一些其它硬件才能对FPGA进行编程。
CPLD优点:
CPLD比PLD具有优势,同时还保留了一些相同的特性,CPLD相对与PLD最大的优点,在于逻辑数量以及布线的选择。LAB逻辑和PI完全,全面可以编程的。在单片器件当中具有很大的设计灵活性,CPLD的I/O特性和功能远远超出了PLD的简单I/O ,在I/O怎样工作上,提供更多的选项和控制的功能,与PAL和PLD一样,CPLD在电路板上,上电即可瞬时接通工作,具有很低的成本,占用很少的电路板面积, 而非易失的EEPROM编程体系结构使其非常适合使用,特别是在在线系统方法下进行测试和调试,不需要在电路板上对其进行重新的编程。 MAX 3000, MAX 7000, MAX II, MAX IIZ
1.2.5 从CPLD到 现场可编程门阵列 (FPGA, Field Programmable Gate Array)
CPLD 相对于老的PLD器件 最大的进步主要 在于,它能够在单个器件当中,大容量容纳非常多的逻辑,理论上来说,可以不断在CPLD中加入LAB(逻辑阵列模块,Logic Array Block,一个LAB有4-20个宏单元, 一个CPLD有多个LAB),增加逻辑的数量,但是这样做,需要增加额外PI布线,实现所有这些LAB连接,其链接数量回呈指数的增长,直到芯片管芯的数量超过逻辑的数量,如果LAB以更好的组织方式进行排列,,情况会怎么样而不是围绕在布线互联的周围呢? 解决方法是LAB排列在网格当中,正如其名称所暗示的,排在阵列当中,那么这个就是FPGA从CPLD到FPGA的一个由来。
现场可编程逻辑门阵列FPGA便是如此,LAB都被排列在大型的阵列当中,器件可以现场编程或者重新编程,和CPLD一样,没有采用中心全局器件互联,而是把布线放置在LAB之间的空格上,就像大城市的街道,比如大北京的街道,那么这种布线被排列成行列互联的形式,它可以跨过器件的整个长度,宽度,或者器件的一小部分,只覆盖行列当中几个LAB。
LAB排列在阵列中、行列可编程互联、互联可以跨过所有或者部分阵列。
FPGA的LAB和CPLD的LAB设计不同,CPLD的LAB由宏单元构成,包括自己的本地可编程阵列。
而FPGA的LAB由大量的逻辑模块构成,这些模块被称为逻辑的单元,即LE(Logic Element),而且本地互联和逻辑分开,LE看起来可能CPLD宏单元相似,当更容易配置,有更丰富的特性来提高性能,减少逻辑资源的浪费,那么左边的结构图是一个典型的LE的形式,那么它是如何构成的呢? 我们仔细观察一下,
那么它(LE),是由一个四输入的查找表LUT+上进位逻辑(Carry Logic)+一个寄存器构成了一个基本的LE单元,这个是非常的重要,请大家务必记住,而右边的原理图详细的画出了典型FPGA LAB当中的LE, LE主要包括三个部分,我们刚才已经谈到了,查找表LUT,进位逻辑和输出寄存器,
LUT,是FPGA中组合逻辑输出乘积和的关键,LUT替代了CPLD当中的乘积项阵列,大部分器件使用4【6】输入的查找表LUT,而有些器件提供输入数量更大的LUT,以建立更复杂的功能,LUT由一系列级联复用的器件构成,其中LUT输入被用作选择线,复用器输入被设置为高或者低逻辑电平,逻辑之所以被称为查找表,是因为查找正确的编程级,来选择输出,并根据LUT输入信号,通过复用器将输出送到正确的地方,编程级的选择基于函数真值表,打一个比方来说,当A和B是高电平,C和D是低电平的时候,该小项通过LUT,那么这一特定的表达式对应于逻辑的乘积项,相当于CPLD宏单元来说,产生LUT输出可能需要更多的逻辑级,但是它能灵活遍历函数和LE链,从而提高了性能,有助于减少逻辑资源的浪费,后面对此,我们进行详细的介绍。
谈一谈,我个人的理解: 对于任意的4输入的逻辑表达式,它的输入组合有2^4=16种,这16种输入,对应16种结果。 那么对于任意的逻辑表达式,这16种结果都可以提前得到,编程的时候,就是把某一个具体的逻辑表达式的所有输入组合的结果预先地存到 EEPROM或者SRAM中。 输入来了,我的结果就直接查到了。 ‘
LUT里面存的其实就是某个逻辑表达式的真值表,这个视频是早期的FPGA学习视频,当前流行的LUT已经是6输入了,也就是2^6=64位。
补充资料:FPGA基础之LUT详解_dongtao Lv的博客-CSDN博客_fpga lut
1.3 FPGA相关基础知识
FPGA 之 可编程寄存器,
LE的同步部分,来自可编程逻辑的寄存器,该寄存器和CPLD当中的可编程宏单元相似,但是FPGA的LE的寄存器级要灵活得多,通过编程它可以配置工作在D触发器、T触发器、JK触发器或者SR触发器模式,通常用全局器件时钟来驱动它,而任何时钟都可以驱动任何的LE,寄存器的异步控制信号,比如说清位、复位或者预设等等,都可以有其他逻辑产生,也可以来自I/O引脚,寄存器输出通过LE后,驱动致器件布线的通道还可以反馈回LUT,与CPLD宏单元反馈相似,可以寄存器旁路产生严格的组合逻辑的功能,那么这也和CPLD相似,也可以完全旁路LUT只使用寄存器或者同步,这种灵活的LE输出级使其非常适合所有类型的逻辑操作。
LE和宏单元不同之处的最后一点是进位和寄存器链逻辑,在CPLD当中,进位bit宏单元输出可以送入其它的宏单元,而这通常需要反馈乘积项阵列,FPGA的LE含有专门的进位逻辑和LAB当中的寄存器链布线,为这些信号提供最短的链接,进位bit可以来自LAB当中其它LE, 也可以来自器件当中的其他的LAB。产生的进位bit,可以输出到其他的LE,或者,器件的互联当中,LAB中的LUT和进位逻辑,可以完全被旁路。 链接LAB当中的所有LE寄存器,把他们变成移位寄存器,这适合DSP的工作,可CPLD相比,进位逻辑和寄存器布线的通用性,进一步提高了性能,增强了对资源的管理。
由于LUT和寄存器都能够输出致器件的任意位置,不论是位于相同LAB当中,或者通过器件的布线通道,那么因此 FPGA的LE可以配置完成寄存器封装的功能,采用寄存器的封装,一个LE可以输出两路不同的函数,一路来自LUT和进位链逻辑,另一路来自输出寄存器,只使用模块的组合逻辑部分,完全不相关的寄存器函数可以封装到一个LE当中,那么因此这有助于节省器件的资源。
到目前为止,所讨论的FPGA LE 的确要比 CPLD宏单元在设计上更加灵活,但还是需要LE级联和反馈,才能产生较多输入的函数,为了解决这个问题,某些高级FPGA使用更通用的逻辑模块,来替代LE,就是自适应逻辑模块,即ALM,ALM和LE相似,但有些重要的优势,那么首先,ALM包括,两个输入的寄存器,为逻辑链和寄存器封装提供更多选项,那么在一个逻辑模块当中,生成多个函数,ALM还有内置硬件加法器模块,ALM当中的加法器是专用的资源,完成标准的算术操作,不需要在LUT或者在DSP当中生成这些数学的函数,那这提高了数学的性能,简化了LUT的逻辑,ALM当中的ALUT和LE的主要不同点,是什么呢? ALM当中的LUT是自适应的LUT即ALUT, ALUT和LUT相似但可以对它进行划分,配置为大小不同的LUT,与使用两种不同类型的函数,包括最简单到非常复杂的函数,那么所有8个输入都可以用于完成复杂算术的函数,而ALUT按照不同的方式来进行划分实现简单的函数,例如两个LUT,一个是3输入,一个是5输入的,还可以划分LUT成更复杂的7输入函数,即额外的输入用于寄存器的封装,分成两个4输入的LUT,使ALUT后项兼容标准LE当中的4输入LUT技术,那么最后如果两个函数之间可以共享输入的话,那么还能进行其他方式的划分,基于ALM的FPGA使用较少的资源,和智能的资源管理技术,大大提高了逻辑工作的性能。
FPGA当中的布线通道看起来要比CPLD当中的互联阵列简单,但是它们实际上提供更多的功能和互联,FPGA布线通道使器件资源,能够与芯片任何地方所有其它资源进行通信,老款的非FPGA器件是无法实现这一点的,曼哈顿型布线通道以及大小不同的固定长度的逻辑段,大大简化了通过布线调整来实现设计时序的要求,正如前面所提到的,随着器件资源的增加,布线通道数量线性增长,就可以连接所有的器件资源,FPGA布线通道可以分为两类,本地的互联,以及行列的互联。本地互联直接连接LE或者LAB中的ALM,而临近的LAB最短的链接称为直接的通路,这和CPLD中的LAB可编程阵列,非常的相似。 只适合FPGA本地互联,和LAB逻辑相分离。
那么另一类互联,是行列互联,这类互联的长度固定,通过一定数量的LAB,或者整个器件,LAB I/O可以连接到本地互联,实现高速的本地操作,或者直接连接至行列互联,向芯片的其它部分发送数据。
FPGA I/O控制功能,含在阵列外沿的模块当中,所有器件的资源都可以通过FPGA布线通道,使用该功能。FPGA单独的I/O模块通常被称为I/O单元,I/O单元含有和老款CPLD I/O控制模块相同的基本功能,但是功能更丰富了,使FPGA I/O单元非常适合用于所有类型的设计。那么除了基本的输入输出以及双向信号,I/O引脚还支持,多种的I/O标准,包括多种,最新的低电压高速标准,可以组合I/O引脚,来支持差分信号I/O标准,比如说LVDS等等。其它特性包含,可变电流驱动能力,等等,以提高电路板的信号完整性,那么上拉电阻形式的片内匹配功能有助于减少电路板上的匹配的原件的数量,某些器件的I/O 单元还含有钳位二极管,使能之后,可以用作PCI总线的I/O,那么根据设计的需要,器件当中,未使用的I/O引脚可以被设置为开 漏 或者 三态 , 这只是典型I/O部分的实例,别的器件还具有更多的功能。
典型I/O基本单元的例子,这张图上没有显式用于控制前面所提到I/O单元功能的所有其它的硬件,I/O单元分成三个主要的部分,输入通路, 采集,输出,寄存器输入引脚上的到达的数据,或者通过布线的通道把输入直接连接至器件当中的逻辑, 输出通道,含有用于同步逻辑或者存储功能的输出寄存器,这和CPLD宏单元当中的输出寄存器相似,由于主LAB逻辑和I/O单元中都有寄存器,都可以使用,从而,释放了寄存器逻辑,能用于其它目的,当然,如果需要,还可以旁路I/O单元的寄存器, I/O单元的最后一部分是输出使能逻辑,enable,该逻辑控制输出使能缓冲,那么如果I/O被配置为双向引脚的话,或者 需要同步输出数据和器件其它输出的时候,那么可以使用这一部分
很多现代FPGA器件,除了LAB之外含有特殊硬件模块,这些专用的资源占用了阵列当中的一个或者多个模块,通过FPGA布线通道可以访问这些模块,这些专用的资源通常在器件当中,以特殊行列模块的形式进行配列,存储器模块是专用的模块,可以配置为不同类型的存储器,FPGA存储器模块可以配置成单端口/双端口RAM或者可编程的ROM,还可以用作移位寄存器或者FIFO缓冲,以替代LAB逻辑。 由于FPGA存储器模块和器件当中的其它结构一样可以进行编程,因此上电时候能够以任意存储器内容对其进行初始化,可以初始化为任何存储器的模式,并进行测试,那么所以,这对设计的调试,非常的有用。现在的FPGA器件当中,另一类专用的资源模块, 嵌入式的乘法器, 嵌入式乘法器,是高性能模块,能够完成乘法/加法/乘累加操作,它可以替代ALUT来提高设计当中的算术性能,这DSP设计非常的有用,某些器件还具有高速的收发器,这些I/O结构支持高速的协议传输的速率可以达到每秒百兆位甚至千兆位,较高的传输速率一般用于通信和网络设备当中,比如说高速技术,不同FPGA器件可能含有不同的数量的各类的资源,那么正如这里所列出的,你应该经常查看器件的手册,以确保某器件能够有足够的资源来完成设计。
FPGA 时钟
由于FPGA是基于同步寄存器逻辑,因此,时钟和时钟控制结构是FPGA体系结构的重要组成部分,时钟基本上是高速算出控制信号, FPGA含有硬件来控制时钟信号应分配到哪里,以及时钟信号怎样达到目的地,所有的FPGA器件,都含有专用时钟输入引脚,这些引脚接收时钟信号,直接连接至芯片当中其它时钟控制结构,其它引脚可以用做时钟引脚,但信号需要通过其它逻辑结构,当不用做时钟的时候,时钟输入引脚,可以用作标准的I/O,时钟输入引脚一般馈于器件中的锁相环(PLL),PLL根据输入时钟的特性来产生其它时钟域,保证所有时钟彼此同相,**斜移最小,稍后部分我们将详细介绍。时钟控制模块用于管理时钟的控制,选择哪些时钟应送入器件的时钟布线网络,它们还用于使能或者静置上电和断电时选择的时钟,时钟布线网络含有用于向器件中所有逻辑输出时钟 的布线通道,这些特殊的通道,一般和普通的行列互联分开,时钟互联全局网络能够连接所有的逻辑,而有的器件还含有局部或者分层时钟网络,仅向器件中的某些部分输送时钟,比如说,时钟网络可以向指向器件当中某一块输送时钟,那么通过这种方式,只用在某一区域或者设计当中某一部分的时钟不完全占用全局时钟布线网络,从而节省了时钟的资源。
如前所示,PLL是能够产生不同时钟域的结构,保证在生成的输出时间斜移最小,PLL是可以编程的,使设计人员很容易建立不同频率、占空比和相移的多种时钟域,用于整个设计当中,比如说,这是一个非常简单的PLL设计,含有一路输入时钟,和基于输入时钟三路输出时钟域,100M的输入来自时钟输入引脚,PLL输出时钟是和输入同向的相同的100M时钟,或者200M时钟,以及相对于输入时钟相移90度的200M时钟,这些时钟,被输入时钟控制模块在器件时钟网络当中,进行分配,一般可以在上电时,对PLL进行编程,而某些器件的PLL在正常工作时,可以随时编程。
在配置并且控制FPGA当中不同类型的体系结构适合,需要很多的编程信息,而且,为支持各种资源之间的连接,同时还含有大量的用户逻辑,需要简单的小规模编程结构,为了达到这些目标, FPGA使用SRAM单元来设置逻辑集完成布线连接,为了解FPGA怎样采用SRAM 单元进行编程的,左侧显示了一个行列之间的典型互联节,互联包括水平和垂直布线之间,所有连接上的开关晶体管,我们可以看到一共有6个晶体管,然后SRAM分别来控制,互联包括水平和垂直布线之间所有连接的开关晶体管,这个我们已经谈到了, 每个晶体管的选择栅极控制功能来自SRAM单元,典型的SRAM单元如右侧所示,SRAM单元基本是一个锁存器,当编程使能之后,编程比特被锁存到单元当中,单元输出是编程比特的补码,因此在进行布线连接时候,编程比特是0,在编程互联晶体管栅极上设置1,关闭开关,进行连接,非常明显,这类编程体系机构的晶体管,多于CPLD阵列,但是,所有晶体管都是标准的,不需要浮栅晶体管,因此不用进行特殊的处理,那么这一类编程体系结构主要问题,不在于所需要的晶体管的数量,而是其易失性,断电之后,锁存被清位,这意味这FPGA器件,总是要在上电时候进行编程,以配置器件SRAM单元。
如果FPGA的所有编程硬件基于SRAM的,编程信息必须存储在非易失的地方,使器件能在上电时进行配置,一般来说,EEPROM,CPU甚至时CPLD等外部器件被用于实现FPGA器件的编程,对大部分的FPGA器件来说,有两种编程方法,采用主动编程方式,FPGA上电时自动开始和外部器件通信,进行编程。采用被动编程方式的时候,外部器件一般是CPU来控制FPGA什么时候以及怎样使用EEPROM或者其它配置器件中的存储的数据进行编程,不论采用哪种编程方式,当FPGA复位或者再次上电的时候,都会出现相同的编程过程,对于CPLD器件,FPGA提供JTAG的接口,用于在实验室当中通过PC进行编程,但是,在生产当中的时候,必须采用其它编程方法,在上电的时候,配置FPGA。
考虑到上面介绍的特性,很容易看出,FPGA给系统设计人员带来了很多的优势,他们在高密封装当中,提供大量的用户逻辑,以实现各种类型的逻辑功能,从简单的,到非常复杂的,FPGA是高性能的器件,老的逻辑可编程器件无法达到专用器件的速率,一般用于提到ASIC或者专用逻辑芯片,然而现代FPGA的性能可满足大量高速应用的需求,成为很多不同类型系统设计的解决方案,FPGA包括不同类型的专用硬件,例如存储器或者DSP模块,使其很容易在一个设计当中,组合实现不同的功能,FPGA I/O非常的灵活,可支持多种I/O标准,针对特定应用提供定制的功能,最后,借助其SRAM编程的单元,FPGA能够很快完成编程,上电时编程这一点几乎不成问题。
总结:如果你能从头看到尾,说明你是真🐂,本文主要是一个FPGA的学前基础知识科普。中间大段的文字可以浏览一下就可以了。文章来源:https://www.toymoban.com/news/detail-511197.html
最后愿我们共同进步! 感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。 文章来源地址https://www.toymoban.com/news/detail-511197.html
到了这里,关于FPGA_学习_01_基础知识(有点劝退,心灵弱小者勿入)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!