从零在FPGA上实现OFDM(二)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目的

产生测试数据,并产生CRC32循环冗余校验,由于在 802.11a 协议中规定了使用 CRC32 作为循环冗余校验。

一、数据模块产生

通过在一定时间周期内,产生一定包长度的的递加数据给后续的模块提供测试数据

1.数据模块说明:

首先数据产生模块通过输入接口收到的数据包的循环周期,宝开头的位置,以及包的长度实现数据的生成,并输出生成的数据,即数据有效信号,包的长度。

实现过程:我们只需要根据输入接口的数据,进行缓存,然后用一个计数器一直累加就行,然后最后注意同步输出数据有效标志,还有数据长度,注意最后的数据长度要加4,因为最后要在输出的数据要加上CRC32校验字。

二、32CRC校验

1.校验原理

CRC即循环冗余校验(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。

CRC校验实用程序库:在数据存储和数据通讯领域,为了保证数据的正确性,就不得不采用检错的手段。

CRC码校验原理:

发送端:发送端根据信息字段与生成多项式生产呢个CRC码,CRC码作为数据发送给接收端,同时也会把计算出的校验字段的数据一同发送(注:目的是如果接受端检测到发送的数据是正确的,接收端能够从CRC码中提取出信息字段的数据)。

接收端:接收到CRC码数据后,检测接收到的数据是否正确,方法:将CRC码数据与生成多项式进行模2除(异或),如果余数为0,则说明接收到的数据是正确的。然后,从CRC码中提取出信息字段的数据。

CRC码是由两部分组成的,前部分是信息字段,就是需要校验的信息,后部分是校验字段,如果CRC码共长n个bit,信息字段长k个bit,就称为(n,k)码。它的编码规则是:

  • 首先将信息字段值(k bit)左移r位(k+r=n)
  • 运用一个生成多项式g(x) (也可看成二进制数) 模2除上面的式子,得到的余数就是校验字段值。
  • 生成的CRC码值为:信息字段值+校验字段值(单位:位bit,次序:高位到低位),例如字段值为1001,校验字段值为110,则CRC码为1001110。

2.实现方法

这里推荐两个网站直接可以生成verilog代码,也可以自己去推导,然后得出。

CRC校验工具-ME2在线工具

https://www.easics.com/crctool/

3.数据输出

802.11要求我们发送端把求得得余数求补再输出,也就是求得的CRC检验码要求补数,而我们可以异或全1,求得补数(不懂可以百度一下)

实现代码如下:

module crc32 (
	//systeam signals
	input	wire 			clk_User,
	input	wire 			reset, //1 reset
	//input signals
	input 	wire			crc_en,
	input 	wire	[7:0]	data_in,

	//ouput signals
	output 	reg 			crc_data_valid,
	output	reg	[7:0]		crc_data

);
reg  [31:0] lfsr_c ,lfsr_q;
wire [7:0]	d;
reg crc_en_dly;
wire  data_in_end_flag;
reg [2:0] cnt4;
reg state;
wire [31:0] crc_out;

assign  crc_out = lfsr_q^32'hffffffff ;
always@(posedge clk_User) begin
	if(reset == 1'b1) begin
		lfsr_q <= {32{1'b1}};
	end else if (cnt4 == 'd3  && state == 1'b1) begin
		lfsr_q <=  {32{1'b1}}; //一次crc计算完成恢复初始值
	end
	else if(crc_en == 1'b1) begin
		lfsr_q <= lfsr_c;
	end
end
//组合逻辑
assign d = data_in;
always @(*) begin
	lfsr_c[0] = d[6] ^ d[0] ^ lfsr_q[24] ^ lfsr_q[30];
    lfsr_c[1] = d[7] ^ d[6] ^ d[1] ^ d[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[2] = d[7] ^ d[6] ^ d[2] ^ d[1] ^ d[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[3] = d[7] ^ d[3] ^ d[2] ^ d[1] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[31];
    lfsr_c[4] = d[6] ^ d[4] ^ d[3] ^ d[2] ^ d[0] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30];
    lfsr_c[5] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[1] ^ d[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[6] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[7] = d[7] ^ d[5] ^ d[3] ^ d[2] ^ d[0] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[29] ^ lfsr_q[31];
    lfsr_c[8] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ lfsr_q[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28];
    lfsr_c[9] = d[5] ^ d[4] ^ d[2] ^ d[1] ^ lfsr_q[1] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ lfsr_q[29];
    lfsr_c[10] = d[5] ^ d[3] ^ d[2] ^ d[0] ^ lfsr_q[2] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[29];
    lfsr_c[11] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ lfsr_q[3] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28];
    lfsr_c[12] = d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ d[0] ^ lfsr_q[4] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[30];
    lfsr_c[13] = d[7] ^ d[6] ^ d[5] ^ d[3] ^ d[2] ^ d[1] ^ lfsr_q[5] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[29] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[14] = d[7] ^ d[6] ^ d[4] ^ d[3] ^ d[2] ^ lfsr_q[6] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[15] = d[7] ^ d[5] ^ d[4] ^ d[3] ^ lfsr_q[7] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[31];
    lfsr_c[16] = d[5] ^ d[4] ^ d[0] ^ lfsr_q[8] ^ lfsr_q[24] ^ lfsr_q[28] ^ lfsr_q[29];
    lfsr_c[17] = d[6] ^ d[5] ^ d[1] ^ lfsr_q[9] ^ lfsr_q[25] ^ lfsr_q[29] ^ lfsr_q[30];
    lfsr_c[18] = d[7] ^ d[6] ^ d[2] ^ lfsr_q[10] ^ lfsr_q[26] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[19] = d[7] ^ d[3] ^ lfsr_q[11] ^ lfsr_q[27] ^ lfsr_q[31];
    lfsr_c[20] = d[4] ^ lfsr_q[12] ^ lfsr_q[28];
    lfsr_c[21] = d[5] ^ lfsr_q[13] ^ lfsr_q[29];
    lfsr_c[22] = d[0] ^ lfsr_q[14] ^ lfsr_q[24];
    lfsr_c[23] = d[6] ^ d[1] ^ d[0] ^ lfsr_q[15] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[30];
    lfsr_c[24] = d[7] ^ d[2] ^ d[1] ^ lfsr_q[16] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[31];
    lfsr_c[25] = d[3] ^ d[2] ^ lfsr_q[17] ^ lfsr_q[26] ^ lfsr_q[27];
    lfsr_c[26] = d[6] ^ d[4] ^ d[3] ^ d[0] ^ lfsr_q[18] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30];
    lfsr_c[27] = d[7] ^ d[5] ^ d[4] ^ d[1] ^ lfsr_q[19] ^ lfsr_q[25] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[31];
    lfsr_c[28] = d[6] ^ d[5] ^ d[2] ^ lfsr_q[20] ^ lfsr_q[26] ^ lfsr_q[29] ^ lfsr_q[30];
    lfsr_c[29] = d[7] ^ d[6] ^ d[3] ^ lfsr_q[21] ^ lfsr_q[27] ^ lfsr_q[30] ^ lfsr_q[31];
    lfsr_c[30] = d[7] ^ d[4] ^ lfsr_q[22] ^ lfsr_q[28] ^ lfsr_q[31];
    lfsr_c[31] = d[5] ^ lfsr_q[23] ^ lfsr_q[29];
end

//delay crc_en_dly
always@(posedge clk_User)begin
	crc_en_dly <= crc_en;
end
//data_in_end_flag
/*
always@(posedge clk_User)begin
	if(reset ==1'b1) begin
		data_in_end_flag <= 1'b0;
	end else if(crc_en == 1'b0 && crc_en_dly ==1'b1)begin
		data_in_end_flag <= 1'b1;
	end else begin
		data_in_end_flag <= 1'b0;
	end
end
*/
assign data_in_end_flag = (~crc_en)&(crc_en_dly);
// state
always@(posedge clk_User) begin
	if(reset ==1'b1) begin
		state <= 1'b0;
	end  else if(cnt4 == 'd3)begin
		state <= 1'b0;
	end else if(data_in_end_flag == 1'b1) begin
		state <= 1'b1;
	end
end

//cnt4
always@(posedge clk_User)begin
	if(reset ==1'b1) begin
		cnt4 <= 'd0;
	end else if(cnt4 =='d3) begin
		cnt4 <= 'd0;
	end
	else if(data_in_end_flag || state)begin
		cnt4 <= cnt4 + 1'b1;
	end else begin 
		cnt4 <= 'd0;
	end
end
//crc_out
always@(posedge clk_User)begin
	if(reset == 1'b1)begin
		crc_data <= 'd0;
	end  else if(data_in_end_flag || state)begin
		if(cnt4 == 'd0) begin
			crc_data <= crc_out[31:24];
		end else if(cnt4 == 'd1)begin
			crc_data <= crc_out[23:16];
		end else if(cnt4 == 'd2)begin
			crc_data <= crc_out[15:8];
		end else if(cnt4 == 'd3)begin
			crc_data <= crc_out[7:0];
		end
	end else begin
			crc_data <= data_in;
	end
end	
//crc_data_valid 
always@(posedge clk_User) begin
	if(reset == 1'b1) begin
		crc_data_valid <= 1'b0;
	end else begin
		crc_data_valid <= (crc_en|data_in_end_flag|state);
		//crc_data_valid <= (crc_en|data_in_end_flag|state);
	end
end

endmodule


<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值