【FPGA/IC】CRC电路的Verilog实现

前言

在通信过程中由于存在各种各样的干扰因素,可能会导致发送的信息与接收的信息不一致,比如发送数据为 1010_1010,传输过程中由于某些干扰,导致接收方接收的数据却成了0110_1010。为了保证数据传输的正确性,工程师们发明了一些检错方法,比如奇偶校验和CRC校验。

CRC校验(Cyclic Redundancy Check,循环冗余校验)是数据传输过程中常用的一种检错方法,针对要发送的数据,其使用一些特定的多项式可以计算出CRC检验结果,CRC校验结果与原始数据一起传输到接收端。

image-20240301220815500

接收端在接收数据的同时按照相同的多项式对接收数据进行校验预算,并将校验结果和接收的结果进行对比,如果二者相同则认为没有发生传输错误;如果不同则认为发生了传输错误。如果发生了错误,接收端可以舍弃该帧数据并通知发送端重新传输数据。

尽管理论上仍然可能存在传输数据有误,但确无法被CRC校验出来的情况,但是这个概率极低,实际应用过程中基本可以忽略。

简单来讲,CRC校验,就是通信双方事先约定好一个CRC模型(一般来讲这个模型最重要的就是多项式),假如发送的数据除以多项式后得到的余数是X,那么接收方接收到的数据除以同样的多项式后,其得到的余数也应该为A。若二者得到的余数不同,则可认为是传输过程中发生了错误。

CRC参数模型

不同的协议在传输数据时采用了不同的CRC参数模型,模型由以下参数来定义。

  • NAME:模型名称,比如CRC-8,CRC-16/USB,CRC-32等。

  • WIDTH:宽度,即生成的CRC校验位宽,如CRC-8生成的结果为8位。

  • POLY:生成多项式的简写(16进制表示)。省略最高位1,如CRC-8的多项式为 x8 + x2 + x + 1,则二进制为1_0000_0111,省略最高位1,二进制0000_0111转换为十六进制为0x07。

  • INIT:这是算法开始时寄存器的初始化值,十六进制表示。

  • REFIN:true或false,在进行计算之前,原始数据是否翻转。原始数据:0xAA = 1010_1010,如果REFIN为true,则翻转后为0101_0101 = 0x55。

  • XOROUT:计算结果与此参数进行异或运算后得到的CRC值,和WIDTH位宽一致。

  • REFOUT:true或false,运算完成之后,得到的CRC值是否进行翻转,方法同上。

下面是一些常见的CRC参数模型:

image-20240301223516679

CRC算法的完整过程

假设通信双方约定的CRC模型为CRC-5/USB,发送的数据为8bits数据0xAA,即1010_1010。

  1. CRC对应的多项式为0x05,补上省略的高位的1,则为10_0101。

  2. REFIN为ture,所以需要翻转数据,即1010_1010 -> 0101_0101。

  3. 多项式的最高项为5,所以在发送数据末端补5个0,即0101_0101_00000

  4. 发送数据除以多项式,即二者进行模2除法,过程如下(注意需要先异或一次初始值,由于很多模型的初始值为0,因为任何数异或0都等于它本身,所以这一步被省略掉了)。得到结果为00011

  5. 将该结果与XOROUT值做异或运算,即 00011 ^ 11111 = 11100

  6. REFOUT为ture,所以需要翻转数据,即11100 -> 00111。即最终的CRC校验值为00111

image-20240302001850633

CRC算法的Verilog实现

一般有两种电路可以用来实现CRC算法,串行CRC电路和并行CRC电路。

串行CRC

串行CRC电路以LFSR为基础,每个时钟周期输入一个数据的单bit,在数据宽度个周期后移位寄存器的值即为CRC校验值。下图是CRC8-CCITT模型的电路示意图。

image-20240302002435666

接下来仍然以CRC-8模型为例,编写RTL代码(CRC-8的模型比较简单,没有反转那些步骤):

image-20240302014411091

//串行CRC-8:宽度8,多项式0x07(x^8+x^2+x+1),初始值00,XOROUT00,REFIN/REFOUT均为FALSE
module test(
	input			clk,			//时钟
	input			rst,			//异步复位
	input			ser_in,			//串行输入数据
	input			ser_in_val,		//串行输入数据有效
	output	[7:0] 	crc_data,		//CRC校验数据
	output 			crc_data_val	//CRC校验数据有效
);

//定义寄存器变量
reg [7:0] 	crc;		//LFSR寄存器实现移位、异或操作
reg	[2:0] 	cnt;		//串行输入数据计数
reg			data_val;	//数据输出有效信号

//连接端口
assign crc_data = crc;
assign crc_data_val = data_val;

//构建串行输入LFSR
always @(posedge clk or posedge rst)begin
	if(rst)
		crc <= 8'd0;			//复位载入初始值
	else if(data_val)		
		crc <= 8'd0;			//校验完成后恢复初始值
	else if(ser_in_val) begin
		crc[0] <= crc[7] ^ ser_in;
		crc[1] <= crc[0] ^ crc[7] ^ ser_in;
		crc[2] <= crc[1] ^ crc[7] ^ ser_in;
		crc[3] <= crc[2];
		crc[4] <= crc[3];
		crc[5] <= crc[4];
		crc[6] <= crc[5];
		crc[7] <= crc[6];
	end
	
end

//串行输入数据计数,0~7共8个周期
always @(posedge clk or posedge rst)begin
	if(rst)
		cnt <= 0;		
	else if(ser_in_val) begin
		cnt <= cnt + 1;
	end
end

//输出8个数据后,拉高校验完成信号
always @(posedge clk or posedge rst)begin
	if(rst)
		data_val <= 0;		
	else if(ser_in_val && (cnt == 7))	
		data_val <= 1;			//8位串行输入传输完成,则拉高该信号
	else
		data_val <= 0;			//其他时间均为低电平	
end

endmodule

因为8位输入数据一共只有256个,所以我们可以用穷举法来进行测试,编写TB:依次产生0~255这256个数据并串行输入,CRC转换完成后在窗口打印信息。

`timescale 1ns/1ns
module tb_test();

//信号声明
reg			clk;
reg			rst;
reg			ser_in;	
reg			ser_in_val;	

wire[7:0]	crc_data;
wire		crc_data_val;

//被测模块实例化
test	inst_test(
	.clk			(clk		),		//时钟信号
	.rst			(rst		),		//时钟信号
	.ser_in			(ser_in		),		//串行输入数据
	.ser_in_val		(ser_in_val	),		//串行输入数据有效信号
	.crc_data		(crc_data	),
	.crc_data_val	(crc_data_val)
);	

//生成时钟信号
initial begin
    clk	= 1'b0;
	forever #5 clk = ~clk;
end

//生成复位信号
initial begin
		rst = 1'b1;	//复位
    #40 rst = 1'b0; //取消复位
end 

//构建一个生成串行数据的任务
task data_gen(
	input	[7:0] 	data
);begin
	for(integer i=0;i<=7;i=i+1)begin
		@(posedge clk) ser_in_val <= 1;
		ser_in <= data[7-i];		
		#10;
	end
	ser_in_val <= 0;	
	@(posedge crc_data_val);	//当输出数据有效时,打印到窗口
		$display("data = %h,crc = %h",data,crc_data);
	#10;
end	
endtask 

//仿真过程
initial begin
 	ser_in = 0;
	ser_in_val = 0;
	@(negedge rst);	//等待复位完成

    //依次产生0-255这256个8bits数据,通过任务data_gen转换成串行输入
	for(integer j=0;j<=255;j=j+1)begin
		data_gen(j);
	end 
	#10 $stop;		//关闭仿真	
end

endmodule 

部分仿真波形如下:

image-20240302142933756

可以看到数据00、01、02、04分别产生的CRC-8校验结果为00、07、0E、09。与这个网站产生的正确结果(CRC(循环冗余校验)在线计算)比对,发现测试结果正确。

同时,Tcl窗口也打印了全部的校验结果(截图只有部分):

image-20240302143420471

并行CRC

了解了串行CRC的结构,实现并行CRC就比较简单了,因为串行CRC是每个时钟周期都寄存了输入数据,然后在各个周期进行计算,那么并行CRC无非就是将电路展开,把所有的运算都放到一个时钟周期来实现。这是一种典型的“面积换时间”,通过增大电路面积来实现低延时latency(即高速率)。

为了说明方便一点,这里选取多项式为 x^4 + x^1 + 1 的CRC4校验来说明,它的串行电路生成部分是这样的:

crc[0] <= crc[3] ^ data ;
crc[1] <= crc[0] ^ crc[3] ^ data;
crc[2] <= crc[1];
crc[3] <= crc[2];

这是时序逻辑,转换成组合逻辑就是当前寄存器的值等于之前寄存器的值和当前输入做运算,用变量init来表示寄存器初始值,然后做8次迭代,

crc[0] = init[3] ^ data ;
crc[1] = init[0] ^ init[3] ^ data;
crc[2] = init[1];
crc[3] = init[2];

为了方便,在crc后面用迭代次数-1表示,那么第1次迭代:输入数据的最高位data[7]和上一轮的LFSR寄存器值(因为才开始,所以是初始值)做异或运算。

data[7]:
	crc7[0] = init[3] ^ data[7] ;
	crc7[1] = init[0] ^ init[3] ^ data[7];
	crc7[2] = init[1];
	crc7[3] = init[2];

同理,有第2次迭代:输入数据的次高位data[6]和上一轮的LFSR寄存器值(即crc7变量)做异或运算。

data[6]:
	crc6[0] = crc7[3] ^ data[6] = init[2] ^ data[6];
	crc6[1] = crc7[0] ^ crc7[3] ^ data[6] = init[3] ^ data[7] ^ init[2] ^ data[6];
	crc6[2] = crc7[1] = init[0] ^ init[3] ^ data[7];
	crc6[3] = crc7[2] = init[1];

直到第8次迭代,输入最后一个数据:

data[5]:
	crc5[0] = crc6[3] ^ data[5] = init[1] ^ data[5];
	crc5[1] = crc6[0] ^ crc6[3] ^ data[5] = init[2] ^ data[6] ^ init[1] ^ data[5];
	crc5[2] = crc6[1] = init[3] ^ data[7] ^ init[2] ^ data[6];
	crc5[3] = crc6[2] = init[0] ^ init[3] ^ data[7];	
data[4]:
	crc4[0] = crc5[3] ^ data[4] = init[0] ^ init[3] ^ data[7] ^ data[4]
	crc4[1] = crc5[0] ^ crc5[3] ^ data[4] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4];
	crc4[2] = crc5[1] = init[2] ^ data[6] ^ init[1] ^ data[5];
	crc4[3] = crc5[2] = init[3] ^ data[7] ^ init[2] ^ data[6];
data[3]:
	crc3[0] = crc4[3] ^ data[3] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
	crc3[1] = crc4[0] ^ crc4[3] ^ data[3] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
	crc3[2] = crc4[1] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4];
	crc3[3] = crc4[2] = init[2] ^ data[6] ^ init[1] ^ data[5];
data[2]:
	crc2[0] = crc3[3] ^ data[2] = init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
	crc2[1] = crc3[0] ^ crc3[3] ^ data[2] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
	crc2[2] = crc3[1] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]
	crc2[3] = crc3[2] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4]
data[1]:
	crc1[0] = crc2[3] ^ data[1] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1]
	crc1[1] = crc2[0] ^ crc2[3] ^ data[1] = init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2] ^ init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1]
	crc1[2] = crc2[1] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]
	crc1[3] = crc2[2] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3]	
data[0]:
	crc0[0] = crc1[3] ^ data[0] = init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ data[0]	
			= init[0] ^ data[4] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
	crc0[1] = crc1[0] ^ crc1[3] ^ data[0] = init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
			= init[1] ^ data[5]^ init[3] ^ data[4] ^ data[1]^ data[7] ^ data[4] ^ init[2] ^ data[6] ^ data[3] ^ data[0]
	crc0[2] = crc1[1] = init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2] ^ init[1] ^ data[5] ^ init[0] ^ init[3] ^ data[7] ^ data[4] ^ data[1]
	crc0[3] = crc1[2] = init[3] ^ data[7] ^ init[2] ^ data[6] ^ data[3] ^ init[2] ^ data[6] ^ init[1] ^ data[5] ^ data[2]

把crc0的表达式整理一下:

crc0[0] = data[6] ^ data[4] ^ data[3] ^ data[0]	^ init[0] ^ init[2];   
crc0[1]	= data[7] ^ data[6] ^ data[5] ^ data[1] ^ data[3] ^ data[0] ^ init[1] ^ init[2] ^ init[3];
crc0[2] = data[7] ^ data[6] ^ data[4] ^ data[2] ^ data[1] ^ init[0] ^ init[2] ^ init[3];
crc0[3] = data[7] ^ data[5] ^ data[3] ^ data[2] ^ init[1] ^ init[3];

和这个网站http://crctool.easics.be/用工具生成的代码(核心部分)做对比,二者结果一致。

newcrc[0] = data[6] ^ data[4] ^ data[3] ^ data[0] ^ crc[0] ^ crc[2];
newcrc[1] = data[7] ^ data[6] ^ data[5] ^ data[3] ^ data[1] ^ data[0] ^ crc[1] ^ crc[2] ^ crc[3];
newcrc[2] = data[7] ^ data[6] ^ data[4] ^ data[2] ^ data[1] ^ crc[0] ^ crc[2] ^ crc[3];
newcrc[3] = data[7] ^ data[5] ^ data[3] ^ data[2] ^ crc[1] ^ crc[3];

接着编写并行CRC-8的代码:

//并行CRC-8:宽度8,多项式0x07(x^8+x^2+x+1),初始值00,XOROUT00,REFIN/REFOUT均为FALSE
module test(
	input			clk,			//时钟
	input			rst,			//异步复位
	input	[7:0]	pal_in,			//并行8位输入数据
	input			pal_in_val,		//并行输入数据有效
	output	[7:0] 	crc_data,		//CRC校验数据
	output 			crc_data_val	//CRC校验数据有效
);

//定义寄存器变量
reg [7:0] 	crc;					//CRC校验数据
reg			data_val;				//CRC校验数据输出有效信号

localparam	CRC_INIT = 8'd0;		//LFSR寄存器初始值

//连接端口
assign crc_data = crc;
assign crc_data_val = data_val;

//并行电路使用函数来构造
function [7:0] CRC8;
	input [7:0] data;				//被校验数据
	input [7:0] crc_init;			//寄存器初值
	begin
		CRC8[0] = data[7] ^ data[6] ^ data[0] ^ crc_init[0] ^ crc_init[6] ^ crc_init[7];
		CRC8[1] = data[6] ^ data[1] ^ data[0] ^ crc_init[0] ^ crc_init[1] ^ crc_init[6];
		CRC8[2] = data[6] ^ data[2] ^ data[1] ^ data[0] ^ crc_init[0] ^ crc_init[1] ^ crc_init[2] ^ crc_init[6];
		CRC8[3] = data[7] ^ data[3] ^ data[2] ^ data[1] ^ crc_init[1] ^ crc_init[2] ^ crc_init[3] ^ crc_init[7];
		CRC8[4] = data[4] ^ data[3] ^ data[2] ^ crc_init[2] ^ crc_init[3] ^ crc_init[4];
		CRC8[5] = data[5] ^ data[4] ^ data[3] ^ crc_init[3] ^ crc_init[4] ^ crc_init[5];
		CRC8[6] = data[6] ^ data[5] ^ data[4] ^ crc_init[4] ^ crc_init[5] ^ crc_init[6];
		CRC8[7] = data[7] ^ data[6] ^ data[5] ^ crc_init[5] ^ crc_init[6] ^ crc_init[7];
	end
endfunction

//当输入有效时进行CRC校验
always @(posedge clk or posedge rst)begin
	if(rst)
		crc <= 8'd0;			
	else if(pal_in_val) 				//输入有效时
		crc <= CRC8(pal_in,CRC_INIT);	//校验结果落后一拍
end

//在输入数据有效的下一个周期输出有效
always @(posedge clk or posedge rst)begin
	if(rst)
		data_val <= 0;		
	else if(pal_in_val)	
		data_val <= 1;			
	else
		data_val <= 0;					//其他时间均为低电平	
end

endmodule 

测试逻辑和上面的串行CRC一样:依次输入0~255这256个数据,观察CRC校验结果:

`timescale 1ns/1ns
module tb_test();

//信号声明
reg			clk;
reg			rst;
reg	[7:0]	pal_in;	
reg			pal_in_val;	

wire[7:0]	crc_data;
wire		crc_data_val;

//被测模块实例化
test	inst_test(
	.clk			(clk		),		//时钟信号
	.rst			(rst		),		//时钟信号
	.pal_in			(pal_in		),		//串行输入数据
	.pal_in_val		(pal_in_val	),		//串行输入数据有效信号
	.crc_data		(crc_data	),
	.crc_data_val	(crc_data_val)
);	

//生成时钟信号
initial begin
    clk	= 1'b0;
	forever #5 clk = ~clk;
end

//生成复位信号
initial begin
		rst = 1'b1;	//复位
    #40 rst = 1'b0; //取消复位
end 

//生成输入数据与时钟使能信号
always @(posedge clk or posedge rst)begin
	if(rst)begin
		pal_in <= 255;
		pal_in_val <= 0;
	end
	else begin 
		pal_in <= pal_in + 1;
		pal_in_val <= 1;
	end
end   

//仿真过程
initial begin
	#1000 $stop;	//关闭仿真	
end

endmodule 

仿真结果如下,CRC校验结果依次输出00-07-0e-09······,与正确结果对比后,发现仿真无误。

image-20240302161000934

initial begin
		rst = 1'b1;	//复位
    #40 rst = 1'b0; //取消复位
end 

//生成输入数据与时钟使能信号
always @(posedge clk or posedge rst)begin
	if(rst)begin
		pal_in <= 255;
		pal_in_val <= 0;
	end
	else begin 
		pal_in <= pal_in + 1;
		pal_in_val <= 1;
	end
end   

//仿真过程
initial begin
	#1000 $stop;	//关闭仿真	
end

endmodule 

仿真结果如下,CRC校验结果依次输出00-07-0e-09······,与正确结果对比后,发现仿真无误。

在这里插入图片描述


  • 📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

30天JS挑战(第十五天)------本地存储菜谱

第十五天挑战(本地存储菜谱) 地址&#xff1a;https://javascript30.com/ 所有内容均上传至gitee&#xff0c;答案不唯一&#xff0c;仅代表本人思路 中文详解&#xff1a;https://github.com/soyaine/JavaScript30 该详解是Soyaine及其团队整理编撰的&#xff0c;是对源代…

【数据结构】B树

1 B树介绍 B树&#xff08;英语&#xff1a;B-tree&#xff09;&#xff0c;是一种在计算机科学自平衡的树&#xff0c;能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除的动作&#xff0c;都在对数时间内完成。B树&#xff0c;概括来说是一个一般化的…

CAS外部云迁移vmware虚拟机兼容性问题处理

CAS外部云迁移vmware虚拟机兼容性问题处理 1、迁移过程中报错实图 2、问题原因 打开虚拟机存储的位置&#xff0c;发现文件夹下存在ctk.vmdk的文件 3、在vmware右键虚拟机编辑设置 注&#xff1a;虚拟机需要先关机 点击虚拟机选项——高级——编辑设置 将ctk.ENABLED改为…

第五套CCF信息学奥赛c++练习题 CSP-J认证初级组 中小学信奥赛入门组初赛考前模拟冲刺题(选择题)

第五套中小学信息学奥赛CSP-J考前冲刺题 1、不同类型的存储器组成了多层次结构的存储器体系,按存取速度从快到慢排列的是 A、快存/辅存/主存 B、外存/主存/辅存 C、快存/主存/辅存 D、主存/辅存/外存 答案&#xff1a;C 考点分析&#xff1a;主要考查计算机相关知识&…

在ubuntu上安装hadoop完分布式

准备工作 Xshell安装包 Xftp7安装包 虚拟机安装包 Ubuntu镜像源文件 Hadoop包 Java包 一、安装虚拟机 创建ubuntu系统 完成之后会弹出一个新的窗口 跑完之后会重启一下 按住首先用ctrlaltf3进入命令界面&#xff0c;输入root&#xff0c;密码登录管理员账号 按Esc 然后输入 …

蓝牙BLE 5.0、5.1、5.2和5.3区别

随着科技的不断发展&#xff0c;蓝牙技术也在不断进步&#xff0c;其中蓝牙BLE&#xff08;Bluetooth Low Energy&#xff09;是目前应用广泛的一种蓝牙技术&#xff0c;而BLE 5.0、5.1、5.2和5.3则是其不断升级的版本。本文将对这四个版本的区别进行详细的比较。 一、BLE 5.0…

为啥要用C艹不用C?

在很多时候&#xff0c;有人会有这样的疑问 ——为什么要用C&#xff1f;C相对于C优势是什么&#xff1f; 最近两年一直在做Linux应用&#xff0c;能明显的感受到C带来到帮助以及快感 之前&#xff0c;我在文章里面提到环形队列 C语言&#xff0c;环形队列 环形队列到底是怎么回…

FPGA高端项目:FPGA基于GS2971的SDI视频接收+纯verilog图像缩放+多路视频拼接,提供8套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收转HDMI输出应用本方案的SDI接收图像缩放应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI接收HLS动态字符叠加输出应用本方案的SDI接收HLS多路视频融合叠加应用本方案的SDI接收GTX…

【代码】Android|获取压力传感器、屏幕压感数据(大气压、原生和Processing)

首先需要分清自己需要的是大气压还是触摸压力&#xff0c;如果是大气压那么就是TYPE_PRESSURE&#xff0c;可以参考https://source.android.google.cn/docs/core/interaction/sensors/sensor-types?hlzh-cn。如果是触摸压力就是另一回事&#xff0c;我需要的是触摸压力。 不过…

【算法沉淀】刷题笔记:并查集 带权并查集+实战讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

Windows Server 各版本搭建文件服务器实现共享文件(03~19)

一、Windows Server 2003 打开服务器&#xff0c;点击左下角开始➡管理工具➡管理您的服务器➡添加或删除角色 点击下一步等待测试 勾选自定义配置&#xff0c;点击下一步 选择文件服务器&#xff0c;点击下一步 勾选设置默认磁盘空间&#xff0c;数据自己更改&#xff0c;最…

Onenote软件新建笔记本时报错:无法在以下位置新建笔记本

报错现象&#xff1a; 当在OneNote软件上&#xff0c;新建笔记本时&#xff1a; 然后&#xff0c;尝试重新登录微软账户&#xff0c;也不行&#xff0c;提示报错&#xff1a; 解决办法&#xff1a; 打开一个新的记事本&#xff0c;复制粘贴以下内容&#xff1a; C:\Users\Adm…

如何防御跨站请求伪造(CSRF)攻击?

CSRF 英文全称是 Cross-site request forgery&#xff0c;所以又称为“跨站请求伪造”&#xff0c;是指恶意诱导用户打开被精心构造的网站&#xff0c;在该网站中&#xff0c;利用用户的登录状态发起的跨站请求。简单来讲&#xff0c;CSRF 就是利用了用户的登录状态&#xff0c…

WordPress建站入门教程:如何在本地电脑搭建WordPress网站?

前面跟大家分享了『WordPress建站入门教程&#xff1a;如何安装本地WordPress网站运行环境&#xff1f;』&#xff0c;接下来boke112百科就继续跟大家分享本地电脑如何搭建WordPress网站。 小皮面板&#xff08;phpstudy&#xff09;的“软件管理 – 网站程序”虽然可以一键部…

excel统计分析——拉丁方设计

参考资料&#xff1a;生物统计学 拉丁方设计也是随机区组设计&#xff0c;是对随机区组设计的一种改进。它在行的方向和列的方向都可以看成区组&#xff0c;因此能实现双向误差的控制。在一般的试验设计中&#xff0c;拉丁方常被看作双区组设计&#xff0c;用于提高发现处理效应…

身份证识别系统(安卓)

设计内容与要求&#xff1a; 通过手机摄像头捕获身份证信息&#xff0c;将身份证上的姓名、性别、出生年月、身份证号码保存在数据库中。1&#xff09;所开发Apps软件至少需由3-5个以上功能性界面组成。要求&#xff1a;界面美观整洁、方便应用&#xff1b;可以使用Android原生…

徽标键锁定问题

徽标键锁定问题 1. 锁定徽标键2. 解锁徽标键 无意中发现键盘除了左右徽标键&#xff0c;其余键都正常。相关的组合键也都失效。 自己的键盘是ikbc w210款的键盘。一直使用都没有任何问题。 搜索发现使用 Fn和 徽标键组合就能锁定和解锁 徽标键。 1. 锁定徽标键 左徽标键Fn …

[项目设计] 从零实现的高并发内存池(一)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 前言 项目介绍 1.内存池 1.1 什么是内存池 池化技术 内存池 1.2 为什…

思科网络设备监控

思科是 IT 行业的先驱之一&#xff0c;提供从交换机到刀片服务器的各种设备&#xff0c;以满足中小企业和企业的各种 IT 管理需求。管理充满思科的 IT 车间涉及许多管理挑战&#xff0c;例如监控可用性和性能、管理配置更改、存档防火墙日志、排除带宽问题等等&#xff0c;这需…

区块链媒体发布推广10个热门案例解析-华媒舍

区块链技术的发展已经引起了媒体的广泛关注&#xff0c;越来越多的区块链媒体纷纷发布推广相关的热门案例。本文将介绍10个成功的区块链媒体推广案例&#xff0c;并分享它们的成功秘诀&#xff0c;帮助读者更好地了解区块链媒体推广的方法与技巧。 随着区块链技术的成熟和应用场…
最新文章