从零在FPGA上实现OFDM(二)

4 篇文章 9 订阅

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

目的

产生测试数据,并产生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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值