手把手Verilog HDL同步Vaild-Ready握手FIFO机制

这篇具有很好参考价值的文章主要介绍了手把手Verilog HDL同步Vaild-Ready握手FIFO机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一级目录

二级目录

三级目录

1、V-R握手FIFO简介

V-R握手FIFO机制,即是两级时钟速率不同的模块之间传递信号的机制,上游往下游传递的数据暂时缓存在FIFO中,上游和FIFO、FIFO和下游之间通过握手传递信号。即在一个FIFO模块外层套了一层握手机制。如下图:
verilog握手协议经典代码,EDA学习,可综合 Verilog HDL,fpga开发,visual studio code如何用Verilog代码实现呢?我们可以这么来做,
1、先实现一个同步FIFO,
2、再实现一个单信号握手,
3、把握手机制套在FIFO外面。

2、先实现一个同步FIFO

2.1 FIFO简介

FIFO:Frist-in-first-out,先进先出,是一种数据缓存器,实现速率匹配。FIFO包括同步 FIFO 和异步 FIFO 两种,同步FIFO有一个时钟信号,读和写逻辑全部使用这一个时钟信号,异步FIFO有两个时钟信号,读和写逻辑用的各自的读写时钟。
FIFO 与普通存储器RAM 的区别是没有外部读写地址线,使用起来非常简单,但缺点就是只能顺序写入数据,顺序读出数据,其数据地址由内部读写指针自动加 1 完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。 FIFO本质上是由 RAM 加读写控制逻辑构成的一种先进先出的数据缓冲器。

2.2 同步FIFO指标

FIFO的宽度:即 FIFO一次读写操作的数据位。
FIFO的深度:指的是 FIFO可以存储多少个 N位的数据(如果宽度为 N)。
满标志:FIFO 已满或将要满时由 FIFO 的状态送出的一个信号,以阻止 FIFO的写操作继续向 FIFO 中写数据而造成溢出(overflow)。
空标志:FIFO 已空或将要空时由 FIFO 的状态送出的一个信号,以阻止 FIFO 的读操作继续从 FIFO中读出数据而造成无效数据的读出(underflow)。
读/写时钟:读/些操作所遵循的时钟,在每个时钟沿来临时读/写数据。

2.3 同步FIFO设计

FIFO 读写指针(读写地址)的工作原理:
写指针:总是指向下一个被写入的单元,复位时,指向第1个单元(编号为0); 
读指针:总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0);


FIFO 的“空”/“满”检测 
FIFO 设计的关键:产生可靠的 FIFO 读写指针和生成 FIFO“空”/“满”标志。 
当读写指针相等时,表明FIFO为空,这种情况发生在复位操作时,或者当读指针读出 FIFO 中最后一个字后,追赶上了写指针时,如下图1所示:
当读写指针再次相等时,表明 FIFO为满,这种情况发生在,当写指针转了一圈,折回来(wrapped around) 又追上了读指针,如下图2:

verilog握手协议经典代码,EDA学习,可综合 Verilog HDL,fpga开发,visual studio code 读写指针可以在读写使能有效时,每时钟周期+1,而如何产生可靠的“空”/“满”信号则成了同步FIFO设计的重点。下面有两种解决方法:计数器法和高位扩展法。 本次采用计数器法

2.4 计数器法实现同步FIFO

构建一个计数器fifo_cnt,该计数器用于指示当前 FIFO 中数据的个数:
复位时,该计数器为0,FIFO中的数据个数为0;
当读写使能信号均有效时,说明又读又写,计数器不变,FIFO中的数据个数无变化;
当写使能有效且 full =0,则 fifo_cnt +1;表示写操作且 FIFO 未满时候,FIFO 中的数据个数增加了 1; 
当读使能有效且 empty=0,则 fifo_cnt -1;;表示读操作且 FIFO 未空时候,FIFO 中的数据个数减少了 1 ;
fifo_cnt =0 的时候,表示 FIFO 空,需要设置 empty=1;
fifo_cnt = fifo的深度 的时候,表示 FIFO 现在已经满,需要设置 full=1。

2.5 同步FIFO代码

//计数器法实现同步FIFO
module	sync_fifo_cnt
#(
	parameter   DATA_WIDTH = 'd8  ,							//FIFO位宽
    parameter   DATA_DEPTH = 'd16 							//FIFO深度
)
(
	input									clk		,		//系统时钟
	input									rst_n	,       //低电平有效的复位信号
	input	[DATA_WIDTH-1:0]				data_in	,       //写入的数据
	input									rd_en	,       //读使能信号,高电平有效
	input									wr_en	,       //写使能信号,高电平有效
															
	output	reg	[DATA_WIDTH-1:0]			data_out,	    //输出的数据
	output									empty	,	    //空标志,高电平表示当前FIFO已被写满
	output									full	,       //满标志,高电平表示当前FIFO已被读空
	output	reg	[$clog2(DATA_DEPTH) : 0]	fifo_cnt		//$clog2是以2为底取对数	
);
 
//reg define
reg [DATA_WIDTH - 1 : 0] fifo_buffer[DATA_DEPTH - 1 : 0];	//用二维数组实现RAM	
reg [$clog2(DATA_DEPTH) - 1 : 0]	wr_addr;				//写地址
reg [$clog2(DATA_DEPTH) - 1 : 0]	rd_addr;				//读地址
 
//读操作,更新读地址
always @ (posedge clk or negedge rst_n) begin
	if (!rst_n)
		rd_addr <= 0;
	else if (!empty && rd_en)begin							//读使能有效且非空
		rd_addr <= rd_addr + 1'd1;
		data_out <= fifo_buffer[rd_addr];
	end
end
//写操作,更新写地址
always @ (posedge clk or negedge rst_n) begin
	if (!rst_n)
		wr_addr <= 0;
	else if (!full && wr_en)begin							//写使能有效且非满
		wr_addr <= wr_addr + 1'd1;
		fifo_buffer[wr_addr]<=data_in;
	end
end
//更新计数器
always @ (posedge clk or negedge rst_n) begin
	if (!rst_n)
		fifo_cnt <= 0;
	else begin
		case({wr_en,rd_en})									//拼接读写使能信号进行判断
			2'b00:fifo_cnt <= fifo_cnt;						//不读不写
			2'b01:	                               			//仅仅读
				if(fifo_cnt != 0)				   			//fifo没有被读空
					fifo_cnt <= fifo_cnt - 1'b1;   			//fifo个数-1
			2'b10:                                 			//仅仅写
				if(fifo_cnt != DATA_DEPTH)         			//fifo没有被写满
					fifo_cnt <= fifo_cnt + 1'b1;   			//fifo个数+1
			2'b11:fifo_cnt <= fifo_cnt;	           			//读写同时
			default:;                              	
		endcase
	end
end
//依据计数器状态更新指示信号
//依据不同阈值还可以设计半空、半满 、几乎空、几乎满
assign full  = (fifo_cnt == DATA_DEPTH) ? 1'b1 : 1'b0;		//满信号
assign empty = (fifo_cnt == 0)? 1'b1 : 1'b0;				//空信号
 
endmodule
`timescale 1ns/1ns	//时间单位/精度
 
//------------<模块及端口声明>----------------------------------------
module tb_sync_fifo_cnt();
 
parameter   DATA_WIDTH = 8  ;			//FIFO位宽
parameter   DATA_DEPTH = 8 ;			//FIFO深度
 
reg									clk		;
reg									rst_n	;
reg		[DATA_WIDTH-1:0]			data_in	;
reg									rd_en	;
reg									wr_en	;
						
wire	[DATA_WIDTH-1:0]			data_out;	
wire								empty	;	
wire								full	;
wire	[$clog2(DATA_DEPTH) : 0]	fifo_cnt;
 
 
//------------<例化被测试模块>----------------------------------------
sync_fifo_cnt
#(
	.DATA_WIDTH	(DATA_WIDTH),			//FIFO位宽
    .DATA_DEPTH	(DATA_DEPTH)			//FIFO深度
)
sync_fifo_cnt_inst(
	.clk		(clk		),
	.rst_n		(rst_n		),
	.data_in	(data_in	),
	.rd_en		(rd_en		),
	.wr_en		(wr_en		),
                 
	.data_out	(data_out	),	
	.empty		(empty		),	
	.full		(full		),
	.fifo_cnt	(fifo_cnt	)			
);
 
//------------<设置初始测试条件>----------------------------------------
initial begin
	clk = 1'b0;							//初始时钟为0
	rst_n <= 1'b0;						//初始复位
	data_in <= 'd0;		
	wr_en <= 1'b0;		
	rd_en <= 1'b0;
//重复8次写操作,让FIFO写满 	
	repeat(8) begin		
		@(negedge clk)begin		
			rst_n <= 1'b1;				
			wr_en <= 1'b1;		
			data_in <= $random;			//生成8位随机数
		end
	end
//重复8次读操作,让FIFO读空	
	repeat(8) begin
		@(negedge clk)begin		
			wr_en <= 1'b0;
			rd_en <= 1'd1;
		end
	end
//重复4次写操作,写入4个随机数据	
	repeat(4) begin
		@(negedge clk)begin		
			wr_en <= 1'b1;
			data_in <= $random;	//生成8位随机数
			rd_en <= 1'b0;
		end
	end
//持续同时对FIFO读写,写入数据为随机数据	
	forever begin
		@(negedge clk)begin		
			wr_en <= 1'b1;
			data_in <= $random;	//生成8位随机数
			rd_en <= 1'b1;
		end
	end
end
 
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk;			//系统时钟周期20ns
 
endmodule

3、再实现一个同步握手

3.1 Valid-Ready简介

设计中经常会用到几个模块之间的数据准确无误的传输,那么我们就需要加上握手信号来控制信号的传输。通常它有两组接口:一个接上游、一个传下游。

3.2 Valid-Ready原理

datain_val用来指示上游数据输入data_in的有效性;
datain_rdy用来指示本模块是否准备好接收上游数据;
dataout_val用来指示往下游数据输出data_out的有效性;
dataout_rdy表示下游是否准备好接收本模块的输出数据;
clk是时钟信号;rst_n是异步复位信号。
其中,datain_ready,由dataout_rdy和data_val组合得到。

verilog握手协议经典代码,EDA学习,可综合 Verilog HDL,fpga开发,visual studio code

3.3 Valid-Ready三种情况

上下游各自的valid和ready信号都有三种情况,即Ready-Before-Valid,Valid-Before-Ready,Ready-With-Valid。这三种各自对应如下:

3.3.1 Ready-Before-Valid(输入)

Ready-Before-Valid是Ready信号在Valid信号之前有效。如下时序图:
verilog握手协议经典代码,EDA学习,可综合 Verilog HDL,fpga开发,visual studio code

先准备好,再来数据,输入端口适合采取这种情况。这种设计使得在上游数据来临之前,通道已经准备好接收数据了。

3.3.2 Valid-Before-Ready(输出)

Valid-Before-Ready是Valid信号在Ready信号之前有效。如下时序图:
verilog握手协议经典代码,EDA学习,可综合 Verilog HDL,fpga开发,visual studio code

先有数据,再看是否准备好往下传,输出端口采取这种情况。提前把数据给准备等待下游来取。这样可以避免数据已经好了但没人来取的情况。

3.3.3 Valid-With-Ready

Valid-With-Ready是Valid信号和Ready信号同时有效,同时到达就很简单,数据来了就被取走。

3.3.4 Stalemate(僵局)

输出端用Ready-Before-Valid,  输出端等待接受端给出的Ready来输出数据
接受端用Valid-before-Ready,  接收端也在等待输出端给出Valid信号来接受数据
两者都在等待却没有一方先给,  通道无效,被“锁住”了。

握手需要特别注意三件事:

  1. valid与ready不可过度依赖,他俩彼此可以互相独立发出请求拉高;
  2. 输如输出各自的valid与数据同步;
  3. 数据与valid一起拉高后,若无新的数据,valid要及时置0。

3.4 代码


//annotation one 
//datain_rdy
//何时准备好接收上游的输入数据?即 datain_rdy == 1?
//当输出下游的数据无效,即没有数据往下游传送,此时“管道为空”,等待数据来。即dataout_val=0;
//当输出下游的数据准备好时,即接下来一边往下游送数据,一边等待上游有效数据来。即dataout_rdy=1。

//annotation two 
//rst_n
//复位信号来时,输出数据和输出数据有效置0,输入数据准备不置0。

//annotation three
//dataout_val
//输出数据有效,当输入数据准备好后(即datain_rdy=1),输入数据有效即为输出数据有效。

//annotation three
//dataout
//输出数据,当输入数据准备好且有效后(即datain_rdy 、datain_val=1),输入数据即为输出数据。


module Valid_Ready #(parameter wd = 4)(
	input                   clk, 
	input                   rst_n,
	input      [wd-1:0]     datain,
	input                   datain_val,
    input                   dataout_rdy, 

	output                  datain_rdy, 
	output reg              dataout_val,
	output reg [wd-1:0]     dataout 
);


//annotation one
assign datain_rdy = dataout_rdy || !dataout_val;        
	
always @(posedge clk or negedge rst_n) 
begin
	if (!rst_n) 
		begin
			dataout     <= 0;                //annotation two                  
			dataout_val <= 0;
		end
	else 
		begin
			if (datain_rdy)
			dataout_val <= datain_val;      // annotation three
			else
			dataout_val <=dataout_val;

            if (datain_rdy && datain_val)
			dataout     <= datain;          // annotation three
			else
			dataout     <= dataout;
		end
end
endmodule

testbench如下:

`timescale 1ns/1ns
module Valid_Ready_tb #(parameter wd = 4);
	reg               clk;
	reg               rst_n;
	reg   [wd-1:0]    datain;
	reg               datain_val;
    reg               dataout_rdy; 

	wire              datain_rdy; 
	wire              dataout_val;
	wire  [wd-1:0]    dataout; 
	
	Valid_Ready r2 (.clk(clk), 
		    .rst_n(rst_n), 
		    .datain(datain), 
			.datain_val(datain_val), 
			.dataout_rdy(dataout_rdy), 
			.datain_rdy(datain_rdy), 
			.dataout_val(dataout_val),
			.dataout(dataout));			
	
always 
begin
	#2 clk = ~clk;
end
//  assign datain_rdy = dataout_rdy || !dataout_val;  
	
	initial begin
		clk          = 0;
		rst_n        = 1;
		datain       = 0;
		datain_val   = 0;                   // 输入数据无效
		dataout_rdy  = 0;                   // 准备输出置0。
	
		#5 rst_n = 0; datain = 5;
		#5 rst_n = 1;                         //此时复位,“管道为空”,dataout_val=0,则datain_rdy为1,准备接收上游数据
		#5 datain_val = 1;                  //输入数据有效,此时datain_rdy && datain_val都为1,数据存入dataout了
		                                    //握手已经完成
		#5 datain_val = 0;                  //由于datain寄存于dataout,发送端认为捕获端已获取数据,datain_val端要置0
		#5 dataout_rdy = 1;                 //slave端可以接受数据,将pipe中数据取走,此时pipe可以寄存下一个数据dataout_val=0,但为了避免bubble,dataout保持不变
		#5 dataout_rdy = 0;                 //slave端接收数据后,停止接收数据
		
		#5 datain = 15; datain_val = 1;     //master端发送数据,因为此时pipe可以寄存数据,由pipe寄存,dataout_val变为1
		#5 datain_val = 0;                  //后续分析过程与上类似
		#5 dataout_rdy = 1; 
		#5 dataout_rdy = 0; 
		
		#10 $stop;
	end
endmodule

4、最后整合为同步Vaild-Ready握手FIFO

4.1 思路原理

如何把valid-ready和握手联系起来?
模块外部是握手,内部是FIFO。
故模块整体的输入输出端口应和valid-read保持一致,在内部声明一个FIFO。如下:

verilog握手协议经典代码,EDA学习,可综合 Verilog HDL,fpga开发,visual studio code

4.2 具体操作

如何把模块外部变量和FIFO定义的变量联系起来?

1、读写使能:
当前reg准备好接收且输入数据有效,即可 使能 写信号;
当后reg准备好接收且当前reg输出数据有效,即可 使能 读信号;

2、FIFO自己写数据与写地址、读数据与读数据、计数器自增自减、空满标志判断不变;

   
3、把空满标志传出去:
没有空(有数据)则可以继续给下面传;     assign out_val = (!empty);
没有满(有地方可以接着写)则可以继续接受。assign in_rdy  = (!full); 

这样,就把一个Valid-Ready的外衣,套在了FIFO上。具体代码如下:

4.3 代码

模块代码:

module VR_FIFO (//外部Valid_Ready输入输出端口
    input                   clk, 
	input                   rst_n,
	input      [7:0]        data_in,
	input                   in_val,
    input                   out_rdy, 

	output                  in_rdy, 
	output                  out_val,
	output reg [7:0]        data_out 
);

//内部FIFO的输入输出端口,以下三组变量是FIFP的输入输出端口,故而要在内部定义。
reg          wr_en     ;                //FIFO 写使能
reg          rd_en     ;                //FIFO 读使能
wire         empty     ;                //FIFO 空信号
wire         full      ;                //FIFO 满信号
reg  [4:0]   fifo_cnt  ;                //FIFO 计数器

//FIFO内部自带的变量定义
reg [7:0]   fifo_buffer[15 : 0];	//用二维数组实现RAM	
reg [3:0]	wr_addr;				//写地址
reg [3:0]	rd_addr;				//读地址


//写使能,当前reg准备好接收且输入数据有效,即可 使能 写信号
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        wr_en <= 1'b0;
    else if(in_val && in_rdy)
        wr_en <= 1'b1;
    else
        wr_en <= 1'b0;
end 

//读使能,当后reg准备好接收且当前reg输出数据有效,即可 使能 读信号
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        rd_en <= 1'b0;
    else if(out_val && out_rdy)
        rd_en <= 1'b1;
    else
        rd_en <= 1'b0;
end 

//向FIFO写数据操作,并且更新写地址
always @ (posedge clk or negedge rst_n) 
begin
	if (!rst_n)
		wr_addr              <= 0;
	else if (!full && wr_en)
    begin							//写使能有效且没有写满
		wr_addr              <= wr_addr + 1'd1;
		fifo_buffer[wr_addr] <= data_in;
	end
end

//从FIFO读数据操作,并且更新读地址
always @ (posedge clk or negedge rst_n) 
begin
	if (!rst_n)
		rd_addr  <= 0;
	else if (!empty && rd_en)begin	//读使能有效且没有读空
		rd_addr  <= rd_addr + 1'd1;
		data_out <= fifo_buffer[rd_addr];
	end
end

//更新计数器,来判断空满信号
always @ (posedge clk or negedge rst_n) 
begin
	if (!rst_n)
		fifo_cnt <= 0;
	else begin
		case({wr_en,rd_en})									
			2'b00:  fifo_cnt <= fifo_cnt;						//不读不写
			2'b01:
                begin	                               			//仅仅读
				if(fifo_cnt != 0)				   			    //fifo没有被读空
					fifo_cnt <= fifo_cnt - 1'b1;                //fifo个数-1
                end   			
			2'b10:                                              //仅仅写
                begin                                 			
				if(fifo_cnt != 5'd16)         			        //fifo没有被写满
					fifo_cnt <= fifo_cnt + 1'b1;   			    //fifo个数+1
                end
            2'b11:  fifo_cnt <= fifo_cnt;	           			//读写同时
			default:;                              	
		endcase
	end
end

//依据计数器状态更新指示信号
//依据不同阈值还可以设计半空、半满 、几乎空、几乎满
assign full  = (fifo_cnt == 5'd16) ? 1'b1 : 1'b0;		    //满信号
assign empty = (fifo_cnt == 0)     ? 1'b1 : 1'b0;		    //空信号

assign in_rdy  = (!full);    
assign out_val = (!empty);
endmodule

testbench:

`timescale 1ns/1ns

module tb_VR_FIFO;

    reg                   clk;
	reg                   rst_n;
	reg      [7:0]        data_in;
	reg                   in_val;
    reg                   out_rdy; 
	wire                  in_rdy;
	wire                  out_val;
	wire     [7:0]        data_out; 

VR_FIFO VR_FIFO_u0 (
					.clk(clk), 
					.rst_n(rst_n),
					.data_in(data_in),
					.in_val(in_val),
					.out_rdy(out_rdy), 
					.in_rdy(in_rdy), 
					.out_val(out_val),
					.data_out(data_out));

initial begin
        clk      = 1'b0;
        rst_n    = 1'b0;
        data_in  = 8'd0;
        in_val   = 1'd0;
        out_rdy   = 1'b0;

#10     rst_n    = 1'b1;

#20     repeat(50)
    begin
    

/*
	//正常写一次读一次
    #20   w_data;
	#20   r_data;

	//只写不读,会满
    #20   w_data;

	//写多读少
    #20   w_data;
	#20   w_data
	#20   r_data;

	//写少读多
    #20   w_data;
	#20   r_data;
	#20   r_data;
*/
    end


#20000  $stop;
end

task w_data;
begin
	    data_in = $random;
	    in_val  = 1'b1;
#20     in_val  = 1'b0;

end
endtask

task r_data;
begin
	    out_rdy  = 1'b1; 
#20     out_rdy  = 1'b0;
end
endtask

always #10 clk =~ clk;
endmodule

至此就完了。
第一次写文章,有的地方写的很粗糙,有问题提出,欢迎大家讨论。
最后贴上邮箱:boyue8817505@163.com文章来源地址https://www.toymoban.com/news/detail-567121.html

到了这里,关于手把手Verilog HDL同步Vaild-Ready握手FIFO机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【算法】手把手学会二分查找

    目录 简介 基本步骤 第一种二分 第二种二分  例题 搜索插入位置 数的范围 总结  🥥二分查找,又叫折半查找,通过找到数据二段性每次都能将原来的数据筛选掉一半,通过这个算法我们能够将一个一个查找的  O(n)  的时间复杂度优化到  O(logn)  ,极大地提升了查找的效率

    2023年04月08日
    浏览(42)
  • 【算法】手把手学会前缀和

    目录 前缀和 前缀和的好处 公式的推导 例题:前缀和 二维前缀和 推导公式  例题: 子矩阵的和 🎵前缀和算法可以理解为是一种 以空间换时间的方式 ,通过建立一个新的数组来 存储从头到当前位置的数据的总和 。 初始化数组  🎵前缀和数组的初始化就是将前  i  个数存

    2024年01月17日
    浏览(41)
  • 手把手实现一个lombok

    什么是JSR ? JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。 有超过300的JSR。一些更为明显的JSRs包括: 的JSR# 规格或技术 1 实时规范为Jav

    2023年04月23日
    浏览(40)
  • tps5430手把手教学

    TPS5430手把手教学 目录 一、buck电路原理 二、tps5430芯片介绍 1.1芯片引脚图 1.2芯片引脚说明 三、tps5430参考电路讲解以及PCB布局 1.正压降压(15V转12V) 1.1原理图 1.2器件选择 1.3PCB布局 2.正压降负压 2.1原理图 2.2PCB布局 2.3注意事项 BUCK电路原理: BUCK电路,又称降压式变换电路,

    2023年04月20日
    浏览(54)
  • 手把手pip安装教程

    在Python中,pip是最常用的包管理工具之一。它可以用于安装、卸载和管理Python包。在本文中,我们将手把手教你如何安装pip,以便能够更方便地安装和管理Python包。 在安装pip之前,我们需要确认已经正确安装了Python,并确定其版本。在命令行中输入以下命令,确认Python版本:

    2024年02月11日
    浏览(62)
  • 【算法】手把手学会BFS

    目录 简介 层序遍历 例题 献给阿尔吉侬的花束 全球变暖 🍦宽度优先搜索算法(又称广度优先搜索)是 最简便的图的搜索算法之一 ,之前我们在实现对树的层序遍历时就使用过它。不仅如此它还在求最短路径,找连通块时具有奇效。 🍦层序遍历基本上借助于队列,将队头

    2023年04月09日
    浏览(98)
  • 手把手教你SHA-256

    SHA-256是SHA-2协议簇的一部分,也是当前最流行的协议算法之一。在本篇文章中,我们会了解这个密码学算法的每一个步骤,并且通过实例演示。SHA-2因它的安全性(比SHA-1强很多)和速度为人所知。在没有键(keys)生成的情况下,例如挖掘比特币,像SHA-2这样的快速哈希算法很

    2024年02月13日
    浏览(75)
  • 手把手教你暴力破解

    暴力破解是一种攻击手段,使用大量的认证信息在认证接口尝试登录,直到得到正确的结果。 2.1标题基于表单的暴力破解 2.1.1 第一步:打开burpsuite拦截 2.1.2 第二步:将拦截到的包右击发送到intruder模块 (其中简单介绍一下intruder模块) Target主要是设置暴力破解访问的host地址

    2024年02月07日
    浏览(57)
  • 【Kali】手把手配置网络方法

    emm,因为花了好多天配置网络,尝试了网上各种方法,都没配置成功,问了老师,看过老师的文档,仍然懵懵懂懂,又看了两篇超长的博客,配置好了一部分,碰巧配好了可以连通外网,却又不能连通物理机了,有时候可以连通物理机,却又不能连通外网,然后在机缘巧合下

    2024年02月03日
    浏览(42)
  • WebSocket---搭建与使用(手把手)

    WebSocket是一种在客户端和服务器之间进行实时双向通信的协议。与传统的HTTP请求-响应模式不同,WebSocket允许 服务器主动向客户端发送消息 ,而不需要客户端发起请求。这种实时通信的特性使得WebSocket非常适合于需要实时更新数据的应用,如聊天室、实时游戏、股票市场等。

    2024年02月02日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包