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

🎉欢迎来到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)beginif(!Rst_n)curr_st <= ST_H;else begin case(curr_st)ST_H:beginif(data == "H")curr_st <= ST_e;elsecurr_st <= ST_H;endST_e:beginif(data == "e")curr_st <= ST_la;elsecurr_st <= ST_H;endST_la:beginif(data == "l")curr_st <= ST_lb;elsecurr_st <= ST_H;endST_lb:beginif(data == "l")curr_st <= ST_o;elsecurr_st <= ST_H;endST_o:beginif(data == "o")curr_st <= ST_H;elsecurr_st <= ST_H;enddefault:curr_st <= ST_H;endcaseend
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)beginif(!Rst_n)curr_st <= ST_H;else begin case(curr_st)ST_H:beginif(data == "H")curr_st <= ST_e;elsecurr_st <= ST_H;endST_e:beginif(data == "e")curr_st <= ST_la;elsecurr_st <= ST_H;endST_la:beginif(data == "l")curr_st <= ST_lb;elsecurr_st <= ST_H;endST_lb:beginif(data == "l")curr_st <= ST_o;elsecurr_st <= ST_H;endST_o:beginif(data == "o")curr_st <= ST_H;elsecurr_st <= ST_H;enddefault:curr_st <= ST_H;endcaseendend//给led赋值,如果进入ST_o状态,并且data = "o",则led电平改变always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led <= led_off;else if(curr_st == ST_o && data == "o")led <= led_on;elseled <= led_off;endendmodule

RTL视图:

RTL33
状态转移333

编写测试激励文件:

FSM_Hello_tb.v:

`timescale 1ns/1ns
`define clock_period 20module 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 beginRst_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)beginif(!Rst_n)curr_st <= ST1;else case(curr_st)ST1:beginif(cnt1 == 8'd9)curr_st <= ST2;else;	endST2:beginif(cnt2 == 8'd9)curr_st <= ST3;else;	endST3:beginif(cnt3 == 8'd9)curr_st <= ST1;else;	enddefault:;endcaseend//状态机ST1的计数器,当状态机等于ST1时,cnt1加1,否则cnt1等于0always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)cnt1 <= 8'b0;else if(curr_st == ST1)cnt1 <= cnt1 + 1'b1;elsecnt1 <= 8'b0;	end//状态机ST2的计数器,当状态机等于ST2时,cnt2加1,否则cnt2等于0always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)cnt2 <= 8'b0;else if(curr_st == ST2)cnt2 <= cnt2 + 1'b1;elsecnt2 <= 8'b0;	end//状态机ST3的计数器,当状态机等于ST3时,cnt3加1,否则cnt3等于0always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)cnt3 <= 8'b0;else if(curr_st == ST3)cnt3 <= cnt3 + 1'b1;elsecnt3 <= 8'b0;	end//给LED1赋值,当状态等于ST1时,LED1等于0,即点亮LED灯,否则LED1等于1,关闭LED灯always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led1 <= 1'b1;else if(curr_st == ST1)led1 <= 1'b0;elseled1 <= 1'b1;	end//给LED2赋值,当状态等于ST2时,LED2等于0,即点亮LED灯,否则LED2等于1,关闭LED灯always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led2 <= 1'b1;else if(curr_st == ST2)led2 <= 1'b0;elseled2 <= 1'b1;	end//给LED3赋值,当状态等于ST3时,LED3等于0,即点亮LED灯,否则LED3等于1,关闭LED灯always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led3 <= 1'b1;else if(curr_st == ST3)led3 <= 1'b0;elseled3 <= 1'b1;	endendmodule

RTL视图与状态转移:

RTL1
状态转移

FSM_01_led_tb.v:

`timescale 1ns/1ns
`define clock_period 20module 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 beginRst_n = 0;#(`clock_period*30);Rst_n = 1;#(`clock_period*300);$stop;endendmodule

仿真结果:

仿真结果

实现效果:

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

/
//模块:状态机例程-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)beginif(!Rst_n)curr_st <= ST1;else case(curr_st)ST1:beginif(cnt1 == cnt_max)curr_st <= ST2;else;	endST2:beginif(cnt2 == cnt_max)curr_st <= ST3;else;	endST3:beginif(cnt3 == cnt_max)curr_st <= ST1;else;	enddefault:;endcaseend//状态机ST1的计数器,当状态机等于ST1时,cnt1加1,否则cnt1等于0always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)cnt1 <= cnt_min;else if(curr_st == ST1)cnt1 <= cnt1 + cnt_add;elsecnt1 <= cnt_min;	end//状态机ST2的计数器,当状态机等于ST2时,cnt2加1,否则cnt2等于0always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)cnt2 <= cnt_min;else if(curr_st == ST2)cnt2 <= cnt2 + cnt_add;elsecnt2 <= cnt_min;	end//状态机ST3的计数器,当状态机等于ST3时,cnt3加1,否则cnt3等于0always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)cnt3 <= cnt_min;else if(curr_st == ST3)cnt3 <= cnt3 + cnt_add;elsecnt3 <= cnt_min;	end//给LED1赋值,当状态等于ST1时,LED1等于0,即点亮LED灯,否则LED1等于1,关闭LED灯always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led1 <= led_off;else if(curr_st == ST1)led1 <= led_on;elseled1 <= led_off;	end//给LED2赋值,当状态等于ST2时,LED2等于0,即点亮LED灯,否则LED2等于1,关闭LED灯always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led2 <= led_off;else if(curr_st == ST2)led2 <= led_on;elseled2 <= led_off;	end//给LED3赋值,当状态等于ST3时,LED3等于0,即点亮LED灯,否则LED3等于1,关闭LED灯always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)led3 <= led_off;else if(curr_st == ST3)led3 <= led_on;elseled3 <= led_off;	endendmodule

实现效果

学习方法:

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

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

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

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

现在讲解小车中的pwm模块

关于模块的端口列表:

module ctrl_moto_pwm(input				clk,//时钟50Minput				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)beginif(!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;endstep_low:begin//当低电平计数时间到达输入值时,进行状态跳转if(step_low_cnt == step_low_time)curr_st <= step_high;else;enddefault:;endcase
end

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

//该always块描述pwm的输出
always@(posedge clk or negedge rst_n)beginif(!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;elsepwm <= 1;
end

完整代码如下:

ctrl_moto_pwm.v:

//脉冲生成模块,通过控制输出脉冲频率及占空比来控制小车的速度
module ctrl_moto_pwm(input				clk,//时钟50Minput				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)beginif(!rst_n)beginstep_high_time <= 0;step_low_time <= 0;endelse beginstep_high_time <= spd_high_time;step_low_time <= spd_low_time;endend//状态机主程序always@(posedge clk or negedge rst_n)beginif(!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;endstep_low:begin//当低电平计数时间到达输入值时,进行状态跳转if(step_low_cnt == step_low_time)curr_st <= step_high;else;enddefault:;endcaseend//高电平持续时间计数器,当持续时间到达输入值时,进行状态跳转always@(posedge clk or negedge rst_n)beginif(!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;elsestep_high_cnt <= 0;end//低电平持续时间计数器,当持续时间到达输入值时,进行状态跳转always@(posedge clk or negedge rst_n)beginif(!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;elsestep_low_cnt <= 0;end//该always块描述pwm的输出always@(posedge clk or negedge rst_n)beginif(!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;elsepwm <= 1;endendmodule

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

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

ctrl_moto_pwm_tb.v:

`timescale 1ns/1ns
`define clock_period 20module 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 beginrst_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;endendmodule

仿真结果:

仿真4

csdn

🧸结尾


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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

macOS Ventura 13.5beta4(22G5059d)发布

系统介绍 黑果魏叔 6 月 28 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.5 开发者预览版 Beta 4 更新&#xff08;内部版本号&#xff1a;22G5059d&#xff09;&#xff0c;本次更新距离上次发布隔了 12 天。 macOS Ventura 带来了台前调度、连续互通相机、F…

TypeScript ~ 掌握基本类型 ②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; TypeScript ~ TS &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &…

SQL-每日一题【182.查找重复的电子邮箱】

题目 表: Person 编写一个 SQL 查询来报告所有重复的电子邮件。 请注意&#xff0c;可以保证电子邮件字段不为 NULL。 以 任意顺序 返回结果表。 查询结果格式如下例。 示例 1: 解题思路 前置知识 count&#xff08;&#xff09; 1.count(*) &#xff1a;统计所有的行数&a…

软考01进制转换

文章目录 前言一、二进制1.二进制转十进制2.二进制转十六进制 二、十进制1.十进制转二进制2.十进制转十六进制 二、十六进制1.十六进制转二进制2.十六进制转十进制 总结 前言 比较常用的进制有二进制、十进制、十六进制这是我们的主要学习目标。 一、二进制 二进制由0和1组成&…

单表-DQL

注意&#xff1a;这张图还包含了对于的顺序&#xff0c;先分组再排序&#xff0c;再分页&#xff0c;顺序不能乱 基本查询 # 1.基本查询 # 查询全部行 select * from tb_emp; select id, user_name, password, name, gender, image, job, entry_date, create_time, update_ti…

ZLMediaKit 的安装及使用介绍

ZLMediaKit 介绍 ZLMediaKit是一个基于C开发的开源流媒体服务器。它提供了高性能的音视频处理能力&#xff0c;支持常见的流媒体协议&#xff0c;如RTSP、RTMP、HLS和HTTP-FLV&#xff0c;并且具有低延迟和高并发处理能力。 开源地址&#xff1a;https://github.com/xia-chu/…

【JAVA】十分钟带你了解java的前世今生

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【初始JAVA】 文章目录 前言JAVA介绍诞生&#x1f52c;名字与图标&#x1f916;发展&#x1f6e9;️未来&#x1fa84; 前言 玩过我的世界的朋友想必对JAVA以及它的图标都很熟悉&#xff0c;在游戏开始画面…

Spring进阶学习(附面试快速答法)

文章目录 1、Bean线程安全问题小总结面试快速答法 2、AOP小总结面试快速答法 3、bean的生命周期小总结面试快速答法 4、循环引用小总结面试快速答法 &#xff15;、SpringMVC的执行流程小总结面试快速答法 6、Springboot自动配置原理小总结面试快速答法 7、Spring框架常见注解面…

【数据库原理】MyShop 商城数据库设计(SQL server)

MyShop 商城数据库设计 项目背景定义课程设计要求概念结构设计逻辑结构设计数据结构的描述用户信息数据结构的描述地址信息数据结构的描述商品类别数据结构的描述商品数据结构的描述购物车数据结构的描述订单数据结构的描述订单项数据结构的描述 物理结构设计用户表结构地址表结…

2013年全国硕士研究生入学统一考试管理类专业学位联考逻辑试题——纯享题目版

&#x1f3e0;个人主页&#xff1a;fo安方的博客✨ &#x1f482;个人简历&#xff1a;大家好&#xff0c;我是fo安方&#xff0c;考取过HCIE Cloud Computing、CCIE Security、CISP、RHCE、CCNP RS、PEST 3等证书。&#x1f433; &#x1f495;兴趣爱好&#xff1a;b站天天刷&…

基于appnium+python+夜神模拟器的自动化

目录 1、安装夜神模拟器 2、定位元素 3、开始编码 首先搭好appnium环境&#xff01;参考https://www.cnblogs.com/testlearn/p/11419797.html 1、安装夜神模拟器 下载安装夜神模拟器后&#xff0c;在cmd命令输入adb connect 127.0.0.1:62001&#xff0c;显示出设备则表示…

Elasticsearch:实用 BM25 - 第 2 部分:BM25 算法及其变量

这是第一部分 “Elasticsearch&#xff1a;实用 BM25 - 第 1 部分&#xff1a;分片如何影响 Elasticsearch 中的相关性评分” 的续篇。 BM25算法 我将尽可能深入这里的数学以解释正在发生的事情&#xff0c;但这是我们查看 BM25 公式的结构以深入了解正在发生的事情的部分。 首…