FPGA-Vivado

第一篇 FPGA基础知识

一.FPGA简介

1.FPGA基础知识

1.1.FPGA:现场可编程门阵列

​ 作用:通信接口设计、数字信号处理等高端场合,特别的,可用于ASIC的原型验证。

1.2.FPGA相较于集成电路虽然在开发难度上有所降低,且缩短了开发周期,但是因为它的高成本和低利用率,导致它不能真正替代集成电路,只有在小批量的开发中使用,当大规模生产时还是会选择将FPGA转化为集成电路去生产。

3.FPGA开发难度低于ASIC,高于单片机、CPU,需要抠时序、抠电路、抠细节,比较复杂。

2.FPGA基本结构

2.1.FPGA通过查找表(LUT)结构实现相应的数字逻辑,LUT是一个SRAM,相当于结果储存,输入后查找再进行输出。例:Y=A&B&C。

3.更复杂的FPGA结构

3.1.随着工艺的升级和技术发展,FPGA内部的查找表、门数量、晶体管个数都在不断升级。3.2.FPGA内部,有“软内核”和“硬内核”之分,比如若利用FPGA的可编程性在芯片内部构造实现一个计数器逻辑,那么在构造计数器逻辑过程中使用到的功能就被称为软功能,又称为软内核;而如果某个功能是直接利用芯片实现,则是利用了芯片内部的“硬功能”,又称为硬内核,如PLL倍频器,是FPGA芯片内部模拟电路搭出来的,而非数字逻辑电路可实现的。

4.带嵌入式处理器的FPGA芯片

4.1.传统方式为PCB上放置FPGA芯片和处理器芯片,协同合作,新方式为FPGA内部带嵌入式处理器,这样更方便PCB布局和通信等。

4.2.典型的SoC FPGA芯片如下图所示:

这个芯片完全以硬内核方式实现的双路ARM Cortex-A9微控制器子系统以及种类广泛的硬内核接口功能,还有一个硬内核的动态内存控制器,所有这些组件都利用大量的可编程构造和大量的通用输入输出(GPIO)引脚进行了性能增强。

当然,FPGA工程师只负责搭建周边电路,如ARM的接口、时钟配置多呢,还负责可编程逻辑部分的开发,而软件部分仍然还是由软件工程师负责。

5.数据存储以及配置方式

5.1.数据可以存储在RAM、SDRAM、DDR3等,但最终数据都是通过RAM进行存储和处理。

5.2.目前,主流的FPGA都是基于SRAM工艺,在大部分的FPGA开发板上,使用的都是串行配置模式。由于SRAM掉电就会丢失内部数据,因此往往都会外接一个能够掉电保存数据的片外存储器以保存程序。这样,上电时FPGA便将外部存储器中的数据读入片内RAM以完成配置,对FPGA编程完成后便进入工作状态;掉电后,FPGA内部SRAM中存储的数据丢失,逻辑清零。以这种方式配置FPGA不仅能反复使用,还无需重复的手动配置,完成一次主动配置后每次上电便会自动的实现FPGA的内部编程。

5.3.常见的4种FPGA配置模式:

​ 1.并行模式:通过并行PROM、Flash配置FPGA;

​ 2.主从模式:使用一片PROM配置多片FPGA;

​ 3.串行模式:串行PROM配置FPGA;

​ 4.外设模式:将FPGA作为微处理器的外设,由微处理器对其编程。这种方式常见于加密Flash的数据解密编程,防止Flash内的数据直接被人拿走复制盗用。

5.4.各种存储器名称及意义

存储器 名称 特点
ROM 只读存储器 只读、数据断电不丢失、在工厂一次性烧录,不可修改,适用于工厂批量生产
PROM 可编程只读存储器 只读、数据断电不丢失,用户一次性写入程序,不可修改,成本较高且烧录速度慢,适用于少量需求或者批量生产前的验证。
EPROM 可擦除可编程只读存储器 可读可写、数据断电不丢失,通过紫外线擦除。
EEPROM 电可擦除只读存储器 可读可写、数据断电不丢失,电擦除。如24C02、25LC256等。
Flash Memory 快闪存储器(闪存) 可读可写、数据断电不丢失。可多次进行读写的电子式存储器,如U盘。
RAM 随机存取存储器 可读可写、断电数据丢失,用来存储中间程序和数据。

二.FPGA开发流程

FPGA的设计流程就是利用EDA开发软件和编程工具对FPGA芯片进行开发的过程。原理图和HDL(Hardware description language,硬件描述语言)是两种最常用的数字硬件电路描述方法。其中,运用HDL设计方法具有更好的移植性、通用性以及利于模块划分的特点,在工作学习中被广泛使用。典型FPGA的开发流程一般如下图所示:

1.功能定义/器件选型

1.1.在FPGA设计项目开始之前需要进行方案论证、系统设计和FPGA芯片的选型等准备工作,在确定并评估好方案后需要进行系统功能的定义和模块的划分。根据方案任务要求,如方案中指出的系统功能以及复杂度,对硬件的工作速度和器件自身的资源、成本、以及性能指标等各个方面进行综合考虑,选择出较合适的器件类型。在设计方法上,一般采用自顶向下的设计方法,首先将整个系统划分成若干个基本模块,然后再讲每个基本模块划分成下一层次的基本单元,这样依次划分后确定好哥哥模块的功能以及各个模块需要设计的输入输出信号,再通过EDA工具进行各个模块的设计。最终要实现的目标是:针对每个输入信号,利用EDA工具以及FPGA的资源设计出需要的输出信号逻辑。

1.2.确定接口,如PCIE、千兆网等,时钟PLL等。这些都是项目开始前选型所要考虑的。

2.设计输入

2.1.使用硬件描述语言(HDL)的当时来描述设计处最终的数字电路,主流HDL语言是Verilog HDL和VHDL,这两种语言在语法结构及设计标准上有差异,但是语言与芯片工艺无关,这两种语言都可以设计出想要的数字电路。

2.2.另一种设计方式是使用原理图输入的方法进行设计输入。从元件库中调出来需要的元件,画出原理图,类似于硬件开发过程中的原理图设计过程。这种方法设计至关且易于仿真,但设计效率不高,难以维护及改动,对模块的构造和重用的支持度不友好,芯片升级后,所有的原理图都需要重新进行一定的改动,可移植性很差。

3.功能仿真(RTL-Simulation)

3.1.**功能仿真也称为综合前仿真(是对代码的仿真),**用户设计好数字逻辑后需要检查自己的设计是否符合预期,在不需要综合之前通过仿真软件对电路进行逻辑验证。在功能仿真器件电路可以不用考虑延迟等因素,仅对初步的功能进行检验。通过建立测试平台即 Testbench,利用波形编译器(仿真软件)和硬件描述语言建立好波形文件和激励信号,在仿真软件上会模拟实际电路的波形显示出输出波形信号,并生成报告文件。用户通过观察各个时间点信号的变化情况来验证自己所设计逻辑的正确性。综合前仿真在FPGA 开发过程中不是一定要进行的步骤,但却是极为关键的一步。在实际的工作学习中,充分利用好仿真工具,能够提高设计的效率并及时发现设计缺陷,从而为后续的开发过程提供保障。常用的硬件描述语言的仿真工具有 Model Tech 公司的 ModelSim、VCS、Ncsim 以及 NC-VHDL 等软件。

4.综合优化(Synthesis)

4.1.综合优化是将代码变成数字逻辑符号看是否可以综合,但是没有连线,还不是电路,没有和FPGA挂起来。

5.综合后仿真

5.1.综合后仿真是用来检查综合结果是否和原设计一致。后仿真与前仿真的区别在于:前仿真是指综合前的仿真,如在 Modelsim 对撰写的代码直接进行仿真,而后仿真是综合后的仿真,也就是功能仿真。假设设计师在 Modelsim 中用 HDL 编写了一个计数器代码,其通过了行为级的仿真后被加载到quartus 或者其他的综合工具中进行综合,完成综合后会生成功能网表,将行为语言转换成寄存器传送级语言,此时设计师再将其加载到 Modelsim 中进行的仿真被叫做后仿真。后仿真成功后还需要在quartus 中进行映射和布局布线,并进行时序分析生成时序网表,描述器件里门或者布线的延时。最后将延时网表和功能网表一起加载到 Modelsim 中仿真,这一仿真为门级仿真,而在实际的设计过程中,一般来说不做综合后仿真也不会带来太大的影响。

6.布局布线

6.1.布局布线可理解为利用实现工具把逻辑映射到目标器件结构的资源中从而决定逻辑的最佳布局,选择逻辑与输入功能链接的布线通道进行连线,并产生相应文件(配置文件和相关报告)。实现试讲综合生成的逻辑网表配置到具体的FPGA芯片上,布局布线是其中最重要的过程。综合之后,就相当于有了各种元件,但如何建立元件之间的连接,就像在PCB上把元件放在哪里,元件之间的连接以及相连关系又是怎么样的,这都是布局布线完成的工作,综合的结果可能每次都一样,但是布局布线的结果基本每次都不一样。

7.时序仿真(Timing)

7.1.加上延时后进行仿真,验证有无时序违规现象。

8.板级仿真与验证

8.1.板级仿真主要应用于高速电路设计中,对高速系统的信号完整性、电磁干扰等特征进行分析,一般都是以第三方工具进行验证和仿真,在实际的工作中一般接触较少。

9.编程与调试

9.1.设计的最后一步就是芯片的编程与调试。编程是指将FPGA开发工具最后产生使用的数据文件(位数据流文件,BitStream Generation)加载到FPGA芯片中。数据文件下载到芯片中还需要进行调试验证,逻辑分析仪(Logic Analyzer,LA)便是FPGA设计的主要调试工具。目前,主流的FPGA芯片生产商都提供了内嵌的在线逻辑分析仪(如Xilinx ISE中的ChipScope、Altera QuartusII中的SignalTapII以及SignalProb),它们只需要占用芯片少量的逻辑资源便可达到同样的效果,在实际的工程提哦啊是种发挥了极大的作用。

10.小结

10.1.实际开发流程中的重点环节如下图所示,静态时序分析可以帮助你找到存在的时序问题,所以综合后仿真和时序仿真在实际开发中基本上不用再多花时间,大多数时间是在功能仿真和调试上。

三.硬件描述语言Verilog

1.Verilog的历史

硬件描述语言已有二十多年历史,VHDL在欧洲、中国一些高校中用的较多,而Verilog HDL在美国、中国的很多设计型企业中用的比较多,所以现在VerilogHDL的使用在中国更普及。Verilog语法简单,规则少,易于上手,VHDL语法规则多,严谨,比较难上手。

2.综合和仿真

2.1.综合

​ Verilog 是硬件描述语言,顾名思义,就是用代码的形式描述硬件的功能,最终在硬件电路上实现该功能。在 Verilog 描述出硬件功能后需要使用综合器对 Verilog 代码进行解释并将代码转化成实际的电路来表示,最终产生实际的电路,也被称为网表。这种将 Verilog 代码转成网表的工具就是综合器。

2.2.仿真

​ 在FPGA 设计的过程中,不可避免会出现各种BUG。如果在编写好代码、综合成电路、烧写到
FPGA 后才发现问题,此时再去定位问题就会非常地困难。而在综合前,设计师可以在电脑里通过仿
真软件对代码进行仿真测试,检测出 BUG 并将其解决,最后再将程序烧写进 FPGA。一般情况下可
以认为没有经过仿真验证的代码,一定是存在 BUG 的。

2.3.可综合设计

​ 可综合与不可综合的区别在于是否可以综合出硬件电路。

​ “综合”要做的事情有:编译 rtl 代码,从库里选择用到的门器件,把这些器件按照
“逻辑”搭建成“门”电路。
​ 不可综合,是指找不到对应的“门”器件来实现相应的代码。比如“#100”之类的延时功能,
简单的门器件是无法实现延时 100 个单元的,还有打印语句等,也是门器件无法实现的。在设计的时候要确保所写的代码是可以综合的,这就依赖于设计者的能力,知道什么是可综合的代码,什么是不可综合的代码。对于初学者来说,最好是先记住规则,遵守规则,先按规则来设计电路并在这一过程中逐渐理解,这是最好的学习路径。

一些不可综合或不推荐使用的代码:

代码 要求
initial 严禁在设计中使用,只能在测试文件中使用。
task/function 不推荐在设计中使用,在测试文件中可用。
for 在设计中、测试文件中均可以使用。但在设计中多数会将其用错,所以建议在初期设计时不使用,熟练后按规范使用
while/repeat/forever 严禁在设计中使用,只能在测试文件中使用
integer 不推荐在设计中使用
三态门 内部模块不能有三态接口,三态门只有顶层文件才使用。三态门目的是为了节省管脚,FPGA 内部完全没有必要使用。关于三态门的介绍,请看后续三态门章节内容
casex/casez 设计代码内部不能有 X 态和 Z 态,因此 casez、casex 设计时不使用。
force/wait/fork 严禁在设计中使用,只能在测试文件中使用
#n 严禁在设计中使用,只能在测试文件中使用

一些推荐使用的设计代码:

代码 备注
reg/wire 设计中所有的信号类型定义,只有 reg 和 wire 两种
parameter 设计代码中所有的位宽、长度、状态机命名等,建议都用参数表示,阅读方便并且修改容易。
assign/always 程序块主要部分,至简设计法对 always 使用有严格规范。
组合逻辑格式为:
always@(*) begin
代码语句;
end
或者用 assign
时序逻辑格式为:
always@(posedge clk or negedgerst_n) begin
if(rst_n==1’b0)begin
代码语句;
end
else begin
代码语句;
end
end
时序逻辑中,敏感列表一定是 clk 的上升沿和复位的下降沿、最
开始必须判断复位。详细见本章组合逻辑和时序逻辑一节。
if else和case always 里面的语句,使用 if else 和 case 两种方法用来作选择判断,可以完成全部设计。
算术运算符(+,-,×,/,%) 可以直接综合出相对应的电路。但除法和求余运算的电路面积一
般比较大,不建议直接使用除法和求余。
赋值运算符(=,<=) 时序逻辑用“<=”,组合逻辑用“=”;其他情况不存在。
关系运算符(==,!=,>,<,>=,<=,) 详细见本章组合逻辑一节
逻辑运算符(&&,||,!) 详细见本章组合逻辑一节
位运算符(~,|,^,&) 详细见本章组合逻辑一节
移位运算符 (<<,>>) 详细见本章组合逻辑一节
拼接运算符({ }) 详细见本章组合逻辑一节

3.模块结构

3.1.模块介绍

​ 模块(module)是 Verilog 的基本描述单位,是用于描述某个设计的功能或结构及与其他模块通信的外部端口。

3.2.模块名和端口定义

​ module 模块名(端口 1,端口 2,端口 3,……);
其中模块是以 module 开始,以 endmodule 结束。模块名是模块唯一的标识符,一般建议模块名尽量用能够描述其功能的名字来命名,并且模块名和文件名相同。模块的端口表示的是模块的输入和输出口名,也是其与其他模块联系端口的标识。

3.3.参数定义

​ 参数定义是将常量用符号代替以增加代码可读性和可修改性。这是一个可选择的语句,用不到的情况下可以省略,参数定义一般格式如下:
​ parameter DATA_W = x;

3.4.接口定义

​ I/O(输入/输出)说明,模块的端口可以是输入端口、输出端口或双向端口。其
说明格式如下。

输入端口: input [信号位宽-1 : 0] 端口名 1;
input [信号位宽-1 : 0] 端口名 2;
……;
输出端口: output [信号位宽-1 : 0] 端口名 1;
output [信号位宽-1 : 0] 端口名 2;
……;
双向端口: inout [信号位宽-1 : 0] 端口名 1;
inout [信号位宽-1 : 0] 端口名 2;
……;

3.5.信号类型

​ reg [width-1 : 0] R 变量 1, R 变量 2 ……;
​ wire [width-1 : 0] W 变量 1,W 变量 2 ……;

​ 如果没有定义信号类型,默认是 wire 型,并且信号位宽为 1。

3.6.功能描述

​ 模块中最重要的部分是逻辑功能定义部分,有三种方法可在模块中产生逻辑。

  1. 用“assign”声明语句,如描述一个两输入与门:assign a = b & c。详细功能见“功能描述-
    组合逻辑”一节。
  2. 用“always”块。即前面介绍的时序逻辑和组合逻辑。
  3. 模块例化。详细功能见“模块例化”一节。

3.7.模块例化

​ 在例化的端口映射中请采用名字关联。如下代码所示:

            DFF d1 (.Q(QS),.Qbar ( ), // 该管脚悬空.Data (D ) ,.Preset ( ), // 该管脚悬空.Clock (CK) ); //名称对应方式。

4.信号类型

​ Verilog HDL 的信号类型有很多种,主要包括两种数据类型:线网类型(net type) 和寄存器类型(reg type)。在进行工程设计的过程中也只会使用到这两个类型的信号。

4.1.信号位宽

​ 用“wire [7:0]”来表示该 wire 型信号的位宽为 8 位。

信号的位宽取决于要该信号要表示的最大值。该信号能表示的无符号数最大值是:2 n -1,其中 n
表示该信号的位宽。例如,信号 a 的最大值为 1000,那么信号 a 的位宽必须大于或等于10位。

4.2.线网类型wire

​ 线网类型用于对结构化器件之间的物理连线的建模,如器件的管脚,芯片内部器件如与门的输出等。由于线网类型代表的是物理连接线,因此其不存储逻辑值,必须由器件驱动。通常用assign 进行赋值,如 assign A = B ^ C。
wire 类型定义语法如下:
wire [msb: lsb] wire1, wire2, . . .,wireN;
 msb 和 lsb 定义了范围,表示了位宽。例如[7:0]是 8 位位宽,也就是可以表示成 8’b0 至 8’b1111_1111;
 msb 和 lsb 必须为常数值;
 如果没有定义范围,缺省值为 1 位;
 没有定义信号数据类型时,缺省为 wire 类型。
 注意数组类型按照降序方式,如[7:0] ,不要写成[0:7]。
​ 下面对上述情况进行举例说明:
wire [3:0] Sat; // Sat 为 4 位线型信号
wire Cnt; //1 位线型信号
wire [31:0] Kisp, Pisp, Lisp ;// Kisp, Pisp, Lisp 都是 32 位的线型信号。

4.3.寄存器类型reg

​ reg 是最常用的寄存器类型,寄存器类型通常用于对存储单元的描述,如 D 型触发器、ROM
等。寄存器类型信号的特点是在某种触发机制下分配了一个值,在下一触发机制到来之前保留原值。
但必须注意的是:reg 类型的变量不一定是存储单元,如在 always 语句中进行描述的必须是用 reg类型的变量。
reg 类型定义语法如下:
reg [msb: lsb] reg1, reg2, . . . reg N;
 msb 和 lsb 定义了范围,表示了位宽。例如[7:0]是 8 位位宽,也就是可以表示成 8’b0 至8’b1111_1111;
 msb 和 lsb 必须为常数值;
 如果没有定义范围,缺省值为 1 位;
 没有定义信号数据类型时,缺省为 wire 类型,不是 reg 型。
 对数组类型按照降序方式,如[7:0] ;不要写成[0:7]。
​ 例如:
reg [3:0] Sat; // Sat 为 4 位寄存器型信号。
reg Cnt; //1 位寄存器。
reg [31:0] Kisp, Pisp, Lisp ; // Kisp, Pisp, Lisp 都是 32 位的寄存器型信号。

4.4.wire和reg的区别

​ reg 型信号并不一定生成寄存器。针对什么时候使用 wire 类型,什么时候用 reg 类型这一问题,本书总结出一套解决方法:在本模块中使用 always 设计的信号都定义为 reg 型,其他信号都定义为 wire 型。

​ 总结:在本模块中alwaysreg;assignwire.

5.功能描述-组合逻辑

5.1.程序语句

5.1.1.assign语句

​ assign 语句是连续赋值语句,一般是将一个变量的值不间断地赋值给另一变量,两个变量之间就类似于被导线连在了一起,习惯上当做连线用。assign 语句的基本格式是:
assign a = b (逻辑运算符)c …;
assign 语句的功能属于组合逻辑的范畴,应用范围可以概括为一下几点:
(1)持续赋值;
(2)连线;
(3)对 wire 型变量赋值,wire 是线网,相当于实际的连接线,如果要用 assign 直接连接,就用 wire 型变量,wire 型变量的值随时发生变化。

需要说明的是,多条 assign 连续赋值语句之间互相独立、并行执行。

5.1.2.always语句

​ always 语句是条件循环语句,执行机制是通过对一个称为敏感变量表的事件驱动来实现的,下面会具体讲到。

always 语句的基本格式是:

                always @(敏感事件)begin程序语句end

always 是“一直、总是”的意思,@后面跟着事件。整个 always 的意思是:当敏感事件的条件
满足时,就执行一次“程序语句”。敏感事件每满足一次,就执行“程序语句”一次。

    always @(a or b or d or sel)beginif(sel==0)c = a + b;elsec = a + d;end

这种条件信号变化结果立即变化的 always 语句被称为“组合逻辑”。

always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginc < = 0;endelse if(sel==0)c < = a + b;elsec < = a + d;
end

这种信号边沿触发,即信号上升沿或者下降沿才变化的 always,被称为“时序逻辑”,此时信号clk 是时钟。注意:识别信号是不是时钟不是看名称,而是看这个信号放在哪里,只有放在敏感列表并且是边沿触发的才是时钟。而信号 rst_n 是复位信号,同样也不是看名字来判断,而是放在敏感列表中且同样边沿触发,更关键的是“程序语句”首先判断了 rst_n 的值,这表示 rst_n 优先级最高,一般都是用于复位。

设计时需要注意以下几点:
1、组合逻辑的 always 语句中敏感变量必须写全,或者用“*”代替。
2、组合逻辑器件的赋值采用阻塞赋值“=,时序逻辑器件的赋值语句采用非阻塞赋值“< =”,具体原因见“阻塞赋值和非阻塞赋值”一节内容。

FPGA-Vivado相关推荐

  1. 基于 FPGA Vivado 的数字钟设计(附源工程)

    今天给大侠带来基于 FPGA Vivado 的数字钟设计,开发板实现使用的是Digilent basys 3,如有想要入手 basys 3 开发板的,可以联系牛总:18511371833.话不多说,上 ...

  2. 基于 FPGA Vivado 的74系列IP封装(附源工程)

    今天给大侠带来基于 FPGA Vivado 的 74 系列IP封装,开发板使用的是Digilent basys 3,如有想要入手 basys 3 开发板的,可以联系牛总:18511371833.话不多 ...

  3. 基于 FPGA Vivado 信号发生器设计(附源工程)

    今天给大侠带来基于 FPGA Vivado 信号发生器设计,开发板实现使用的是Digilent basys 3,如有想要入手 basys 3 开发板的,可以联系牛总:18511371833.话不多说, ...

  4. 基于 FPGA Vivado 示波器设计(附源工程)

    今天给大侠带来基于 FPGA Vivado 示波器设计,开发板实现使用的是Digilent basys 3,如有想要入手 basys 3 开发板的,可以联系牛总:18511371833.话不多说,上货 ...

  5. FPGA Vivado设计流程

    今天给大侠带来Vivado设计流程,话不多说,上货. 本篇通过创建一个简单的HDL工程,学会使用Vivado集成开发环境.学会如何使用Vivado进行设计.仿真.综合以及实现一个项目,生成比特流文件并 ...

  6. FPGA Vivado XDC 约束文件编写方式语法笔记

    参考手册: UG625:https://china.xilinx.com/support/documentation/sw_manuals/xilinx14_7/cgd.pdf UG903:https ...

  7. FPGA — Vivado下ILA(逻辑分析仪)详细使用方法

    使用软件: Vivado 开发板: EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA 使用程序:按键案例 ILA详细使用方法 一.ILA简介 二.ILA的使用方法 ...

  8. [学习笔记-FPGA]Vivado出现信号差分问题

    个人笔记. 用Vivado写串口时出现了[DRC IOSTDTYPE-1] IOStandard Type: I/O port sys_clk is Single-Ended but has an I ...

  9. FPGA VIVADO仿真详解 TEST BENCH

    待测试工程-流水灯 建立新工程的方法不再赘述,这里只针对TEST BENCH文件的建立进行描述.测试工程如下,功能是控制流水灯闪烁 `timescale 1ns / 1ps //时延单位为1ns,时延 ...

  10. [FPGA/Vivado/ILA]Vivado的ILA核在Waveform界面无任何变化,抓取不到信号和数据

    使用Vivado软件操作ILA核,在Waveform界面如遇到抓取不到信号的问题,如下图所示: 可能在以下方面出现问题: 最基础也是最重要的: 通过IP Catalog产生ILA核后,是否在代码里例化 ...

最新文章

  1. linux chattr命令
  2. BigData:根据最新2018人工智能行业创新企业Top100名单,绘制AI地区热点图,一目了然,看清哪个是AI最热门城市,以及VC最AI的热门领域
  3. 从零点五开始用Unity做半个2D战棋小游戏(九)
  4. java中如何将非整数保留到小数点后指定的位数
  5. c语言无符号数除法,[求助]关于双字节无符号数除法
  6. java swing 如何设置按钮大小_Java Swing - Button不改变宽度的大小
  7. python抽取指定url页面的title_Python新手写爬虫全过程记录分析
  8. python3哪个版本稳定-python3哪个版本稳定
  9. [知识库:python-tornado]异步调用中的上下文控制Tornado stack context
  10. 关于chrome上的网银安全控件开发技术(chrome 调用本地dll)
  11. 51单片机对GPS卫星信号的解码并通过LCD1602或12864显示
  12. 服务器lnixs系统,Navicat for MySQL v12.1.19 强大的数据库管理和开发工具 _ 黑苹果乐园...
  13. 下载keep运动软件_keep运动下载安装
  14. 360篡改Edge、Google浏览器主页的应对方法
  15. RevitAPI: 如何判断天花板的族类型是否是复合结构
  16. C++:应用有限差分法求解 稳平流扩散方程 v*ux-k*uxx=0 in 一个空间维度,具有恒定的速度 v 和扩散系数 k(附完整源码)
  17. 计算机空格符号,电脑打印出现空格符号怎么办
  18. Dell PowerEdge T140服务器安装系统笔记
  19. 音箱选购必备20秘诀
  20. 安卓系统的指纹解锁_安卓全面屏都用的屏幕下指纹识别,科普超声波指纹识别的原理...

热门文章

  1. LabVIEW播放提示声音或者音乐
  2. cuteftp.exe
  3. SolidWorks焊件中将各结构构件分解成单个零件的方法
  4. 深圳学位分数计算机,深圳各区学位录取积分出炉!罗湖录取到C类,南山最高降40分……...
  5. 这5个PNG免抠素材网站,可商用,赶紧马住了
  6. 大数据应用要经得起考验,不可盲目跟风_光点科技
  7. setproxy_SetProxy:一个设置IE代理的命令行小工具
  8. 关于 DWave dimod 使用详解
  9. usleep java_sleep()和usleep()的使用和区别
  10. 牛客网计算机考研机试真题-abc