【FPGA零基础学习之旅#9】状态机基础知识

news2024/11/22 16:30:48

🎉欢迎来到FPGA专栏~状态机基础知识


  • ☆* o(≧▽≦)o *☆~我是小夏与酒🍹
  • 博客主页:小夏与酒的博客
  • 🎈该系列文章专栏:FPGA学习之旅
  • 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
  • 📜 欢迎大家关注! ❤️
    FPGQ2

CSDN

🎉 目录-状态机基础知识

  • 一、效果演示
  • 二、状态机基础知识
  • 三、Hello例程分析
  • 四、简单例程分析
    • 4.1 使用状态机实现流水灯
    • 4.2 使用状态机实现循迹小车的pwm

遇见未来

一、效果演示

🔸Hello状态机例程
RTL视图:
RTL1
状态转移:
状态转移1

🔸 流水灯状态机例程
使用小精灵V2实现的效果:
流水灯
小精灵V2基础使用记录:【FPGA-Spirit_V2】小精灵V2开发板初使用。
RTL视图:
RTL2状态转移:
状态转移2

🔸循迹小车pwm状态机例程
pwm

二、状态机基础知识

状态机全称是有限状态机(Finite State Machine,FSM),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

状态机分为摩尔(Moore)型有限状态机米利(Mealy)型有限状态机。摩尔状态机的输出只由输入确定(不直接依赖于当前状态)。米利有限状态机的输出不止与其输入有关,还与它的当前状态相关,这也是与摩尔有限状态机的不同之处。

对于状态机的描述方式,可分为一段式、两段式以及三段式。
一段式:整个状态机写到一个 always 模块里面。在该模块中既描述状态转移,又描述状态的输入和输出。
两段式:用两个 always 模块来描述状态机。其中一个 always 模块采用同步时序描述状态转移,另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律及其输出。
三段式:在两个 always 模块描述方法基础上,使用三个 always 模块。一个 always 模块采用同步时序描述状态转移,一个 always 采用组合逻辑判断状态转移条件,描述状态转移规律,另一个 always 模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

本篇文章主要以三个简单案例为主入门状态机,需要深入学习状态机相关的知识可以参考大佬的文章:FPGA状态机(一段式、二段式、三段式)、摩尔型(Moore)和米勒型(Mealy)。

三、Hello例程分析

Hello例程说明:使用状态机对“Hello”字符串进行检测,当检测到完整的“Hello”字符串时,改变led的电平。

状态转移过程说明:在状态H时,当检测到字符H,跳转到状态e,否则,一直保持在H状态;在状态e时,当检测到字符e,跳转到状态l,否则,跳转回H状态;…同理,在状态o时,当检测到字符o,跳转到状态H,同时改变led的电平,否则,跳转回H状态且不改变led电平。

为了便于转移过程的分析,使用独热码对状态进行编码:

localparam ST_H 	= 5'b00001;
localparam ST_e 	= 5'b00010;
localparam ST_la 	= 5'b00100;
localparam ST_lb 	= 5'b01000;
localparam ST_o 	= 5'b10000;

同时,需要定义一个状态机寄存器,用于判断当前的状态

//状态机寄存器
reg[4:0] curr_st;

由于对“Hello”字符串的检测分为5个状态,使用独热码进行编码占用了5个位宽,因此也需要定义一个5个位宽的状态机寄存器。

为了便于模块的维护和管理,在此定义好led的亮和灭:

//定义led状态
parameter led_on  = 1'b0;
parameter led_off = 1'b1;

根据上述状态转移的说明分析,编写状态机主程序

//状态机主程序
always@(posedge Clk or negedge Rst_n)begin
	if(!Rst_n)
		curr_st <= ST_H;
	else begin 
		case(curr_st)
			ST_H:begin
				if(data == "H")
					curr_st <= ST_e;
				else
					curr_st <= ST_H;
			end
			ST_e:begin
				if(data == "e")
					curr_st <= ST_la;
				else
					curr_st <= ST_H;
			end
			ST_la:begin
				if(data == "l")
					curr_st <= ST_lb;
				else
					curr_st <= ST_H;
			end
			ST_lb:begin
				if(data == "l")
					curr_st <= ST_o;
				else
					curr_st <= ST_H;
			end
			ST_o:begin
				if(data == "o")
					curr_st <= ST_H;
				else
					curr_st <= ST_H;
			end
			default:curr_st <= ST_H;
		endcase
	end
end

“Hello”例程的完整代码:

FSM_Hello.v:

/
//模块:状态机例程-Hello
//作者:CSDN-小夏与酒

module FSM_Hello(
	input 			Clk,
	input 			Rst_n,
	input 		 	[7:0]data,
	output 	reg 	led
);

	//状态机状态定义
	//使用独热码的编码方式
	//写法一:
	localparam ST_H 	= 5'b00001;
	localparam ST_e 	= 5'b00010;
	localparam ST_la 	= 5'b00100;
	localparam ST_lb 	= 5'b01000;
	localparam ST_o 	= 5'b10000;

	//写法二:
	//	localparam
	//			ST_H 	= 5'b00001,
	//          ST_e 	= 5'b00010,
	//          ST_la 	= 5'b00100,
	//          ST_lb 	= 5'b01000,
	//			ST_o 	= 5'b10000;
				
	//状态机寄存器
	reg[4:0] curr_st;
	
	//定义led状态
	parameter led_on  = 1'b0;
	parameter led_off = 1'b1;
	
	//状态机主程序
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			curr_st <= ST_H;
		else begin 
			case(curr_st)
				ST_H:begin
					if(data == "H")
						curr_st <= ST_e;
					else
						curr_st <= ST_H;
				end
				ST_e:begin
					if(data == "e")
						curr_st <= ST_la;
					else
						curr_st <= ST_H;
				end
				ST_la:begin
					if(data == "l")
						curr_st <= ST_lb;
					else
						curr_st <= ST_H;
				end
				ST_lb:begin
					if(data == "l")
						curr_st <= ST_o;
					else
						curr_st <= ST_H;
				end
				ST_o:begin
					if(data == "o")
						curr_st <= ST_H;
					else
						curr_st <= ST_H;
				end
				default:curr_st <= ST_H;
			endcase
		end
	end

	//给led赋值,如果进入ST_o状态,并且data = "o",则led电平改变
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led <= led_off;
		else if(curr_st == ST_o && data == "o")
			led <= led_on;
		else
			led <= led_off;
	end

endmodule

RTL视图:

RTL33
状态转移333

编写测试激励文件:

FSM_Hello_tb.v:

`timescale 1ns/1ns
`define clock_period 20

module FSM_Hello_tb;

	reg Clk;
	reg Rst_n;
	reg [7:0]ASCII;
	
	wire led;
	
	FSM_Hello FSM_Hello0(
		.Clk(Clk),
		.Rst_n(Rst_n),
	 	.data(ASCII),
	 	.led(led)
	);

	initial Clk = 1;
	always #(`clock_period/2) Clk = ~Clk;
	
	initial begin
		Rst_n = 0;
		ASCII = 0;
		#(`clock_period*20);
		Rst_n = 1;
		#(`clock_period*20 + 1);
		
		ASCII = "I";
		#(`clock_period);
		ASCII = "A";
		#(`clock_period);
		ASCII = "M";
		#(`clock_period);
		ASCII = "X";
		
		#(`clock_period);
		ASCII = "H";
		#(`clock_period);
		ASCII = "E";
		#(`clock_period);
		ASCII = "M";
		#(`clock_period);
		ASCII = "l";
		#(`clock_period);

		ASCII = "H";
		#(`clock_period);
		ASCII = "E";
		#(`clock_period);
		ASCII = "L";
		#(`clock_period);
		ASCII = "L";
		#(`clock_period);
		ASCII = "O";
		#(`clock_period);
		
		ASCII = "H";
		#(`clock_period);
		ASCII = "e";
		#(`clock_period);
		ASCII = "l";
		#(`clock_period);
		ASCII = "l";
		#(`clock_period);
		ASCII = "o";
		
		#(`clock_period);
		ASCII = "l"; 
		#(`clock_period);
		
		ASCII = "H";
		#(`clock_period);
		ASCII = "e";
		#(`clock_period);
		ASCII = "l";
		#(`clock_period);
		ASCII = "l";
		#(`clock_period);
		ASCII = "o";
		
		#(`clock_period);
		ASCII = "l"; 
		
		#(`clock_period);
		
		$stop;
	end		

endmodule

仿真结果:

仿真结果

四、简单例程分析

4.1 使用状态机实现流水灯

使用Verilog实现一个流水灯并不难,但是使用状态机的方式实现,就提供了新的编程思路。

在状态机的文章中加入流水灯的实现,主要是为了学习 【小月电子】 大佬的状态机写法风格,大佬博客主页链接:Moon_3181961725。

先上完整代码:

FSM_01_led.v:

/
//模块:状态机例程-LED-分析
//作者:CSDN-小夏与酒

module FSM_01_led(
	input 		Clk,
	input 		Rst_n,
	output reg 	led1,
	output reg 	led2,
	output reg 	led3
	);
	
	//定义状态机
	parameter	ST1		= 1;
	parameter	ST2		= 2;
	parameter	ST3		= 3;
	
	reg[3:0]	curr_st;//状态机寄存器
	reg[7:0]	cnt1;//定义计数寄存器
	reg[7:0]	cnt2;//定义计数寄存器
	reg[7:0]	cnt3;//定义计数寄存器
	
	//状态机主程序
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			curr_st <= ST1;
		else case(curr_st)
			ST1:begin
				if(cnt1 == 8'd9)
					curr_st <= ST2;
				else;	
			end
			ST2:begin
				if(cnt2 == 8'd9)
					curr_st <= ST3;
				else;	
			end
			ST3:begin
				if(cnt3 == 8'd9)
					curr_st <= ST1;
				else;	
			end
			default:;
		endcase
	end
	
	//状态机ST1的计数器,当状态机等于ST1时,cnt1加1,否则cnt1等于0
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt1 <= 8'b0;
		else if(curr_st == ST1)
			cnt1 <= cnt1 + 1'b1;
		else
			cnt1 <= 8'b0;	
	end
	
	//状态机ST2的计数器,当状态机等于ST2时,cnt2加1,否则cnt2等于0
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt2 <= 8'b0;
		else if(curr_st == ST2)
			cnt2 <= cnt2 + 1'b1;
		else
			cnt2 <= 8'b0;	
	end
	
	//状态机ST3的计数器,当状态机等于ST3时,cnt3加1,否则cnt3等于0
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt3 <= 8'b0;
		else if(curr_st == ST3)
			cnt3 <= cnt3 + 1'b1;
		else
			cnt3 <= 8'b0;	
	end
	
	//给LED1赋值,当状态等于ST1时,LED1等于0,即点亮LED灯,否则LED1等于1,关闭LED灯
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led1 <= 1'b1;
		else if(curr_st == ST1)
			led1 <= 1'b0;
		else
			led1 <= 1'b1;	
	end
	
	//给LED2赋值,当状态等于ST2时,LED2等于0,即点亮LED灯,否则LED2等于1,关闭LED灯
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led2 <= 1'b1;
		else if(curr_st == ST2)
			led2 <= 1'b0;
		else
			led2 <= 1'b1;	
	end
	
	//给LED3赋值,当状态等于ST3时,LED3等于0,即点亮LED灯,否则LED3等于1,关闭LED灯
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led3 <= 1'b1;
		else if(curr_st == ST3)
			led3 <= 1'b0;
		else
			led3 <= 1'b1;	
	end
	
endmodule
	

RTL视图与状态转移:

RTL1
状态转移

FSM_01_led_tb.v:

`timescale 1ns/1ns
`define clock_period 20

module FSM_01_led_tb;
	
	reg Clk;
	reg Rst_n;
	
	wire led1;
	wire led2;
	wire led3;
	
	FSM_01_led FSM_01_led0(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.led1(led1),
		.led2(led2),
		.led3(led3)
	);
	
	initial Clk = 1;
	always #(`clock_period/2) Clk = ~Clk;
	
	initial begin
	Rst_n = 0;
	
	#(`clock_period*30);
	Rst_n = 1;
	
	#(`clock_period*300);
	
	$stop;
	
	end
	
endmodule

仿真结果:

仿真结果

实现效果:

在上板验证前记得修改计数器的计数值,即:

/
//模块:状态机例程-LED
//作者:CSDN-小夏与酒

module FSM_01_led(
	input 		Clk,
	input 		Rst_n,
	output reg 	led1,
	output reg 	led2,
	output reg 	led3
	);
	
	//定义状态机
	parameter	ST1		= 1;
	parameter	ST2		= 2;
	parameter	ST3		= 3;
	
	reg[3:0]	curr_st;//状态机寄存器
	reg[24:0]	cnt1;//定义计数寄存器
	reg[24:0]	cnt2;//定义计数寄存器
	reg[24:0]	cnt3;//定义计数寄存器
	
	//定义计数值范围
	parameter cnt_max = 25'd24_999_999;	//定时器最大值
	parameter cnt_min = 25'd0;			//定时器最小值
	parameter cnt_add = 1'b1;			//定时器定时增量
	
	//定义led状态
	parameter led_on  = 1'b0;
	parameter led_off = 1'b1;
	
	//状态机主程序
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			curr_st <= ST1;
		else case(curr_st)
			ST1:begin
				if(cnt1 == cnt_max)
					curr_st <= ST2;
				else;	
			end
			ST2:begin
				if(cnt2 == cnt_max)
					curr_st <= ST3;
				else;	
			end
			ST3:begin
				if(cnt3 == cnt_max)
					curr_st <= ST1;
				else;	
			end
			default:;
		endcase
	end
	
	//状态机ST1的计数器,当状态机等于ST1时,cnt1加1,否则cnt1等于0
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt1 <= cnt_min;
		else if(curr_st == ST1)
			cnt1 <= cnt1 + cnt_add;
		else
			cnt1 <= cnt_min;	
	end
	
	//状态机ST2的计数器,当状态机等于ST2时,cnt2加1,否则cnt2等于0
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt2 <= cnt_min;
		else if(curr_st == ST2)
			cnt2 <= cnt2 + cnt_add;
		else
			cnt2 <= cnt_min;	
	end
	
	//状态机ST3的计数器,当状态机等于ST3时,cnt3加1,否则cnt3等于0
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt3 <= cnt_min;
		else if(curr_st == ST3)
			cnt3 <= cnt3 + cnt_add;
		else
			cnt3 <= cnt_min;	
	end
	
	//给LED1赋值,当状态等于ST1时,LED1等于0,即点亮LED灯,否则LED1等于1,关闭LED灯
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led1 <= led_off;
		else if(curr_st == ST1)
			led1 <= led_on;
		else
			led1 <= led_off;	
	end
	
	//给LED2赋值,当状态等于ST2时,LED2等于0,即点亮LED灯,否则LED2等于1,关闭LED灯
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led2 <= led_off;
		else if(curr_st == ST2)
			led2 <= led_on;
		else
			led2 <= led_off;	
	end
	
	//给LED3赋值,当状态等于ST3时,LED3等于0,即点亮LED灯,否则LED3等于1,关闭LED灯
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led3 <= led_off;
		else if(curr_st == ST3)
			led3 <= led_on;
		else
			led3 <= led_off;	
	end
	
endmodule
	

实现效果

学习方法:

将状态机主程序分割开来单独写,会使整个程序思路清晰。状态机主程序部分:

//状态机主程序
always@(posedge Clk or negedge Rst_n)begin
	if(!Rst_n)
		curr_st <= ST1;
	else case(curr_st)
		ST1:begin
			if(cnt1 == 8'd9)
				curr_st <= ST2;
			else;	
		end
		ST2:begin
			if(cnt2 == 8'd9)
				curr_st <= ST3;
			else;	
		end
		ST3:begin
			if(cnt3 == 8'd9)
				curr_st <= ST1;
			else;	
		end
		default:;
	endcase
end

4.2 使用状态机实现循迹小车的pwm

关于FPGA实现简单的循迹小车链接:【FPGA-Spirit_V2】基于FPGA的循迹小车-小精灵V2开发板。

现在讲解小车中的pwm模块

关于模块的端口列表:

module ctrl_moto_pwm(
	input				clk,//时钟50M
	input				rst_n,//复位,低电平有效
	input	[7:0]		spd_high_time,//输入高电平持续时间
	input	[7:0]		spd_low_time,//输入低电平持续时间
	output				period_fini,//一个pwm周期结束的标志位
	output	reg			pwm//脉冲信号									
);

该模块需要输入时钟信号、复位信号、高电平持续时间和低电平持续时间;输出一个pwm周期结束的标志位和pwm信号

定义pwm产生的三个状态

//状态机
parameter	idle		= 8'h0;//空闲状态
parameter	step_high 	= 8'h1;//脉冲高电平状态,当为该状态时,pwm为高电平
parameter	step_low  	= 8'h2;//脉冲低电平状态,当为该状态时,pwm为低电平

为了debug的方便,在模块中加入判断产生了一个pwm的标志位

//产生一个pwm周期的标志位,当一个pwm产生后,输出高电平,否则输出低电平
assign period_fini = (step_low_cnt == step_low_time)?1'b1:1'b0;

同样,与上文相同,为了编程思路的清晰,将状态机主程序单独写

//状态机主程序
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		curr_st <= idle;
	else case(curr_st)
		idle:curr_st <= step_high;
		step_high:begin
				//当高电平计数时间到达输入值时,进行状态跳转
				if(step_high_cnt == step_high_time)
					curr_st <= step_low;
				else;
		end
		step_low:begin
				//当低电平计数时间到达输入值时,进行状态跳转
				if(step_low_cnt == step_low_time)
					curr_st <= step_high;
				else;
		end
		default:;
	endcase
end

在不同的状态下(空闲、高电平、低电平),pwm的信号输出:

//该always块描述pwm的输出
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		pwm <= 0;
	else if(curr_st == idle)
		pwm <= 0;
	else if(curr_st == step_high)
		pwm <= 1;
	else if(curr_st == step_low)
		pwm <= 0;
	else
		pwm <= 1;
end

完整代码如下:

ctrl_moto_pwm.v:

//脉冲生成模块,通过控制输出脉冲频率及占空比来控制小车的速度
module ctrl_moto_pwm(
	input				clk,//时钟50M
	input				rst_n,//复位,低电平有效
	input	[7:0]		spd_high_time,//输入高电平持续时间
	input	[7:0]		spd_low_time,//输入低电平持续时间
	output				period_fini,//一个pwm周期结束的标志位
	output	reg			pwm//脉冲信号									
);
				
	//状态机
	parameter	idle		= 8'h0;//空闲状态
	parameter	step_high 	= 8'h1;//脉冲高电平状态,当为该状态时,pwm为高电平
	parameter	step_low  	= 8'h2;//脉冲低电平状态,当为该状态时,pwm为低电平

	reg	[7:0]	curr_st;
	reg	[10:0]	step_high_time;
	reg	[10:0]	step_low_time;
	reg	[10:0]	step_high_cnt;
	reg	[10:0]	step_low_cnt;
	
	//产生一个pwm周期的标志位,当一个pwm产生后,输出高电平,否则输出低电平
	assign period_fini = (step_low_cnt == step_low_time)?1'b1:1'b0;
	
	//将输入值(高、低电平持续时间)存入寄存器中
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
				step_high_time <= 0;
				step_low_time <= 0;
		end
		else begin
				step_high_time <= spd_high_time;
				step_low_time <= spd_low_time;
		end
	end
	
	//状态机主程序
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			curr_st <= idle;
		else case(curr_st)
			idle:curr_st <= step_high;
			step_high:begin
					//当高电平计数时间到达输入值时,进行状态跳转
					if(step_high_cnt == step_high_time)
						curr_st <= step_low;
					else;
			end
			step_low:begin
					//当低电平计数时间到达输入值时,进行状态跳转
					if(step_low_cnt == step_low_time)
						curr_st <= step_high;
					else;
			end
			default:;
		endcase
	end
	
	//高电平持续时间计数器,当持续时间到达输入值时,进行状态跳转
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			step_high_cnt <= 0;
		else if(curr_st == idle)
			step_high_cnt <= 0;
		else if(curr_st == step_high)
			step_high_cnt <= step_high_cnt + 1;
		else
			step_high_cnt <= 0;
	end
	
	//低电平持续时间计数器,当持续时间到达输入值时,进行状态跳转
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			step_low_cnt <= 0;
		else if(curr_st == idle)
			step_low_cnt <= 0;
		else if(curr_st == step_low)
			step_low_cnt <= step_low_cnt + 1;
		else
			step_low_cnt <= 0;
	end
	
	//该always块描述pwm的输出
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			pwm <= 0;
		else if(curr_st == idle)
			pwm <= 0;
		else if(curr_st == step_high)
			pwm <= 1;
		else if(curr_st == step_low)
			pwm <= 0;
		else
			pwm <= 1;
	end

endmodule

pwm产生模块的代码中我每一部分都写了对应的注释,可供大家参考,该模块可以直接在需要用到pwm的地方直接调用

该模块对应的RTL视图和状态转移:
RTL4
状态转移4
我们编写一个简单的测试激励文件:

ctrl_moto_pwm_tb.v:

`timescale 1ns/1ns
`define clock_period 20

module ctrl_moto_pwm_tb;
	
	reg clk;
	reg rst_n;
	reg [7:0]spd_high_time;
	reg [7:0]spd_low_time;
	
	wire period_fini;
	wire pwm;
	
	ctrl_moto_pwm Uctrl_moto_pwm0(
		.clk(clk),//时钟50M
		.rst_n(rst_n),//复位,低电平有效
		.spd_high_time(spd_high_time),//输入高电平持续时间
		.spd_low_time(spd_low_time),//输入低电平持续时间
		.period_fini(period_fini),//一个pwm周期结束的标志位
		.pwm(pwm)//脉冲信号									
	);

	initial clk = 1;
	always #(`clock_period/2) clk = ~clk;
	
	initial begin
	
		rst_n = 0;
		spd_high_time = 0;
		spd_low_time = 0;
		#(`clock_period*100);
	
		rst_n = 1;
		spd_high_time = 15;
		spd_low_time = 5;
		#(`clock_period*2000);
		
		$stop;
	
	end

endmodule

仿真结果:

仿真4

csdn

🧸结尾


  • ❤️ 感谢您的支持和鼓励! 😊🙏
  • 📜您可能感兴趣的内容:
  • 【FPGA-Spirit_V2】基于FPGA的循迹小车-小精灵V2开发板
  • 【Verilog HDL】FPGA-Verilog文件的基本结构
  • 【Arduino TinyGo】【最新】使用Go语言编写Arduino-环境搭建和点亮LED灯
  • 【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制
    遇见未来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/686722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MAC电脑使用技巧

Mac打开根目录 /user下的文件 mac 上怎么显示隐藏的/user文件夹&#xff0c;有两种方法可选~~~ 1&#xff0c;Finder界面是&#xff0c;最上方&#xff0c;通过“前往”进入“电脑”或文件夹 先进入到需要显示隐藏文件的文件夹下 接着按Command苹果键F,在窗格上会显示搜索栏 然…

爬虫框架和库有多重要?

爬虫框架和库在网络数据提取和分析中非常重它们为开发人员提供了工具和功能&#xff0c;使他们能够更轻松地从互联网上抓取数据。爬虫框架和库通常提供了高效的网络请求、数据解析和存储机制&#xff0c;简化了爬取过程。 使用爬虫框架库有以下几个重要优势&#xff1a; 快速开…

探索Android Jetpack Compose的Surface组件

随着声明性 UI 框架 Jetpack Compose 的出现&#xff0c;Android 开发变得更加简洁和直观。在这篇博客中&#xff0c;我们将深入探讨其中的一项基本构建块 —— Surface 组件&#xff0c;了解它如何影响 UI 的显示和设计。 一、Jetpack Compose和Surface组件 二、Surface组件…

强化学习:值函数近似

例子引入 值得注意的是&#xff0c;之前学习的 状态值和动作值 实际上都是以表格的形式表示的&#xff0c;他的好处是便于直观理解与分析&#xff0c;但缺点是难以处理大量的数据的或连续的状态或行动空间&#xff0c;表现在存储和泛化能力两个方面。如下&#xff1a; 为了解决…

Css设置border从中间向两边的颜色渐进效果

Css设置border从中间向两边的颜色渐进效果 .list-item {border-bottom: 1rpx solid;border-image: linear-gradient(to right, rgba(0,0,0,.1) 0%, rgba(81, 110, 197, 0.76) 50%, rgba(0,0,0,.1) 100%) 1;}效果如图&#xff1a;

js精度问题之bignumber.jsdecimal.js的基本使用

一、背景 JavaScript中存在精度缺失问题 为什么&#xff1f; 主要是由于浮点数的表示方式以及计算机的二进制运算原理导致的 JavaScript使用IEEE 754标准定义了浮点数的表示和计算规则。在这种表示方式中&#xff0c;浮点数由符号位、指数位和尾数位组成。尾数位的长度是固…

智慧高校IT智能运维方案

当前高校网络已成为每个学校必备的信息基础设施&#xff0c;也成了学校提高教学、科研及管理水平的重要途径和手段。随着信息化发展&#xff0c;高校网络建设逐步走向数字化、智慧化&#xff0c;传统的人力巡检、运维逐渐难以支撑高校校园稳定运行。因此&#xff0c;如何在有限…

半导体芯片封装工艺流程,芯片定制封装技术

当我们购买电子产品时&#xff0c;比如手机、电视或计算机&#xff0c;这些设备内部都有一个重要的组成部分&#xff0c;那就是半导体芯片。半导体芯片是由许多微小的电子元件组成的&#xff0c;为了保护和使用这些芯片&#xff0c;它们需要经过一个被称为封装的工艺流程。下面…

EasyRecovery16免费版电脑数据恢复工具

EasyRecovery是一款优质的数据恢复软件&#xff0c;Windows和Mac两个平台都可以运行。可恢复电脑、相机、移动硬盘、U盘、SD卡、内存卡、光盘以及本地存储的电子邮件等数据。同时支持100多种不同格式的文件恢复。EasyRecovery开发了个人版、专业版和企业版三重安装包&#xff0…

想要财务自由

*近日&#xff0c;有调查称“大概五分之一的年轻人存款在一万元以内。10万元存款是一个“坎”&#xff0c;存款超过10万就会超过53.7%的人。”“年轻人”“存款”两个词碰撞在一起&#xff0c;引来了广泛的关注和讨论。你认为年轻人存款难吗&#xff1f;可以从以下几个角度发表…

MapBox 实现自定义地图样式配置(包含本地静态引入)

Mapbox 官方提供了非常多的样式的底图,但是有的时候我们想要自己定义地图的样式基调,比如我们想看到这种样式的地图: 这就需要我们要有自己配置地图的能力了。 那么接下来我们说说怎么做。 首先我们还是登录 mapbox 的官网,找到样式配置的页面,这里直接给大家链接: A…

软件外包开发测试工具

软件测试是软件项目中非常重要的一个环节&#xff0c;在软件项目上线前必须要将问题测出来&#xff0c;否则上线后出现大量问题不但可能引起经济损失&#xff0c;而且也会失去客户的信任。今天和大家分享软件测试中常用的一些工具&#xff0c;希望对大家有所帮助。北京木奇移动…

系列六、Typora下载安装

一、下载 链接&#xff1a;https://pan.baidu.com/s/1c_OMBN_MdWi6-PjKjtcXPg?pwdyyds 提取码&#xff1a;yyds 二、安装 选择安装目录&#xff0c;直接下一步&#xff0c;下一步...即可&#xff0c;例如

SpringBoot01:认识并构建SpringBoot项目

目录 一、Spring Boot简介 1、回顾什么是Spring&#xff1f; 2、Spring是如何简化java开发的&#xff1f; 3、什么是SpringBoot&#xff1f; 3.1、什么是SpringBoot呢&#xff1f; 3.2、所有技术框架的发展似乎都遵循一条主线规律 3.3、SpringBoot开发背景 3.4、Spring…

聊一聊布隆过滤器

布隆过滤器是一个精巧而且经典的数据结构。 你可能没想到&#xff1a;RocketMQ、 Hbase 、Cassandra 、LevelDB 、RocksDB 这些知名项目中都有布隆过滤器的身影。 对于后端程序员来讲&#xff0c;学习和理解布隆过滤器有很大的必要性。下面&#xff0c;一起看一看布隆过滤器的…

智能客服外包服务在医药行业的应用

随着科技的不断进步&#xff0c;智能客服已经在各个行业得到了广泛应用&#xff0c;医药行业也不例外。那么&#xff0c;智能客服在医药行业中又有哪些应用呢&#xff1f;让我们一起来看看吧。 医药行业作为一个高度专业化且具有广泛需求的行业&#xff0c;每天都会涉及到大量…

10个免费PDF转PPT方法,请收好以备不时之需!

众所周知&#xff0c;PDF&#xff08;便携式文档格式&#xff09;文件广泛用于交换各种信息&#xff0c;包括文本、图像和图形。但有时&#xff0c;您可能想将 PDF 文件转换为其他格式&#xff0c;例如 PowerPoint。在本文中&#xff0c;我们将讨论 10 种将 PDF 转换为 PPT 的免…

6-js基础-2

JavaScript 基础 - 2 理解什么是流程控制&#xff0c;知道条件控制的种类并掌握其对应的语法规则&#xff0c;具备利用循环编写简易ATM取款机程序能力 类型转换语句综合案例 今日重点单词&#xff1a; 类型转换 类型转换&#xff1a;把一种数据类型转换成另外一种数据类型 为…

快速搭建 Nuxt2 项目

文章目录 01 Nuxt 能提供哪些功能&#xff1f;有什么益处&#xff1f;02 快速搭建项目2.1 安装 create-nuxt-app 脚手架工具2.2 使用脚手架搭建项目 01 Nuxt 能提供哪些功能&#xff1f;有什么益处&#xff1f; 服务端渲染&#xff1a;Nuxt 是基于 Vue.js 的 服务端渲染 框架&…

文献学习-联合抽取-Joint entity and relation extraction based on a hybrid neural network

目录 1、Introduction 2、Related works 2.1 Named entity recognition 2.2 Relation classification 2.3 Joint entity and relation extraction 2.4 LSTM and CNN models On NLP 3、Our method 3.1 Bidirectional LSTM encoding layer 3.2 Named entity recogniton …