OFDM接收机学习-第一章 分组检测模块FPGA的实现

系列文章目录

第一章 分组检测模块的实现

第二章 符号同步模块FPGA的实现


目录


前言

        ofdm发射机信号最终是发出来了2路8位的时域信号,分别是8位实部和虚部。最终的话通过板子验证发射机与接收机之间的正确通信,因此涉及到不同时钟域作用下的信号首先就要考虑信号的同步问题。如何在有噪声的情况下基本正确找到帧头也就是前导码,正确找到前导码也就意味着正确找到了数据域,才能完成两个时钟域之间的正常通信。

上板实测环境:两块开发板分别作为发射机和接收机。通过AD/DA模块传输进行简单实验

内部逻辑分析仪抓取波形:

各项标志基本正常,与仿真结果基本相同。

一、分组检测目的

        分组检测是找到数据分组起始的近似运算,注意是近似运算,这是接收机同步的第一步。通俗的讲,分组检测就是检测突发传输方式的信道上是否有新的数据到达,其算法的好坏直接影响着判断的精度以及准度。

二、分组检测算法描述

1.接收能量检测

m_{n}=\sum_{k=0}^{L-1}r_{n-k}r_{n-k}^{*}   (1)  

         m代表接收能量在窗口长度为L下的累计和,r代表当下点的信号,r*是其信号的共轭

        通过简化(1)公式可以变成:

m_{n+1}=m_{n}+\left | r_{n+1} \right |^{2}-\left | r_{n-L+1} \right |^{2}   (2)

        通过滑动窗口在每一个时刻n,求和m会不断加入一个新的数值,同时减去一个过去的数值,通过移动递归计算,避免了乘法器的使用,使用加减法就可以完全实现。如图所示,在n=500的时候能量出现了较大波动,因此找到合适的阈值就能够判断出新的数据到来的时候,但是没有信号的时刻的噪声功率不可控,因此这种方法实际应用效果不太好。比如万一在新数据到来之前有一段噪声功率比较大,那么mn也会突然变得特别大,因此会造成误判。

2.双滑动窗口分组检测

        双窗口分组检测就完美的解决了1分组算法的问题,在空闲的时候,两个窗口里都是相同的噪声能量,因此两者之间的比值基本一直是1,完美的避免了噪声功率过大影响阈值判断的问题。随着新分组数据的到来,当窗口B完全充满新数据后,而窗口A恰恰正好完全充满着噪声的时刻,就是两者比值最大的峰值,随着窗口A也进入了新的数据分组,窗口A的能量不断增加,因此两者的比值也就慢慢回落。

        其中两个窗口能量的计算依然是算法1的计算公式,计算各自的能量,只不过两者能量就是一个延时的关系,比如窗口的长度是32,则a窗口的能量就一直落后于b窗口32个点。通过公式(3)的比值的最高值就能检测到新分组的到来。

m_n=\frac{a_n}{b_n} (3)

        第二种算法最起码是比第一种算法要好的,但是这本教材的作者仍然没有使用这种算法,所以直接推这种算法不如第三种算法好用。其实应该就是要充分利用前导码的结构的存在,如果没有前导码帧头这种结构,这个算法不失为一个较好的解决方案。

3.采用前导结构进行分组检测

        抛砖引玉,第一个算法和第二个算法纯纯大冤种,充分利用信号本身结构才是最贴合工程的解决方案。前导结构是由10个重复性周期性的短序列和2个长序列构成的,其中这个短序列就是为了分组检测而存在的,同时还可以完成载波同步和符号同步作用。

        前导结构实现了接收机采用了一种非常简单有效的分组检测算法,充分利用短序列的周期性,称为延时相关算法。流程如图所示,信号rn进来之后一路直接去乘法器,同时另一路直接去延时电路后进行共轭对称进入到乘法器的另一端,进行乘法计算。

        乘法器计算得到的延时相关的值Cn如下,其中D就是延时长度,一般就是短序列的点数,周期数。计算公式本身原理跟第二个算法有点类似,其中主要就是Cn计算的是信号的互相关,就是将信号与信号延时后的共轭进行计算窗口能量。

C_n=\sum_{k=0}^{L-1}r_{n-k}*r_{n-k-D}^{*} (1)

        而流程图中下面这一路Pn信号能量的公式为:

P_n=\sum_{k=0}^{L-1}r_{n-k-D}*r_{n-k-D}^{*} (2)

        通过两个能量的比值,就能得到新数据到来时刻。将窗口Cn取绝对值作为分子,将Pn信号能量作为分母,得到判决变量mn:

m_n=\frac{C_n}{P_n}=\frac{\sum_{k=0}^{L-1}r_{n-k}*r_{n-k-D}^{*}}{\sum_{k=0}^{L-1}r_{n-k-D}*r_{n-k-D}^{*}} (3)

        因为Cn算的是互相关性,什么是互相关性?怎么利用这一个特点算出来噪声和信号的区别呢?正是因为短序列是周期性的,所以10个短序列本身的互相关性是非常大的,而噪声本身的产生是随机的,理论上噪声的互相关性基本为0或者是很小。就利用这个特点进行判断!

        同时考虑到万一信道中会产生偶尔个别的大能量噪声,这个能量没准也能超过门限值,所以在同时对这个门限值保持一定的采样周期,即有一定长度的门限值后判断为新分组数据的到来。所以这个算法最终就叫做延时相关加长度保持算法。

        到目前为止,基本上对我们想要实现的算法原理有了一定的清楚的认识,最起码我们知道要做什么运算,是对什么信号做运算。其次如何在FPGA上实现,要就要考虑两个方面,一个是数据通路,就是实现你要对数据进行的互相关运算、信号能量计算等过程。另一个是控制通路,就是你控制数据什么时候进行什么运算,在合适的时候传到下一个模块等等。

三、延时相关加长度保持算法的硬件结构优化

        基本原理上一节已经进行了大概的分析,主要思想还是通过判断互相关窗口能量跟信号能量的比值与设定的阈值进行比大小,大于设定阈值且维持一定时间后仍大于设定阈值则判断新分组数据确实到来。其中一定时间暂定为32点。

m_n=\frac{\left |C_n \right |}{P_n}>T_{n} (1)

        其中Cn需要计算绝对值也就是幅值,进行以下方式的近似能够大大简化计算过程:

           \left |C_n \right |=\sqrt{a_n^{2}+b_n^{2}}\approx \left |a_n \right |+ \left |b_n \right | (2)

        这样进行近似估计带来的后果就是算出来Cn数值偏大,因此mn偏大,因此对应的阈值要进行相应的调整。

P_n=\sum_{k=0}^{L-1}r_{n-k-D}*r_{n-k-D}^{*} (3)

        目前pn和cn的计算公式都确定了,由于阈值Tn是一个确定的数值,根据教材的经验值,Th取0.5,因此就变成了Cn>Pn>>1。当满足这个条件就说明mn到达了最大值,也就是说明新分组数据已经到来。

        框图结构其实就是根据上面流程图进行配置的,整体我们可以分为两部分,一部分是控制,一部分是数据计算。首先需要对数据进行缓存,对需要进行延时的数据进行延时,将延时完毕的数据送进延时相关计算模块,在合适的时机将数据送进信号能量计算模块,最后根据长度保持以及mn的公式进行判断即可。

四、分组检测算法在FPGA上的实现

1、数据缓存模块

        C_n=\sum_{k=0}^{L-1}r_{n-k}*r_{n-k-D}^{*} (1)第一部分延时相关计算,是需要当前数据与一个周期之前的数据进行互相关计算。因此数据缓存模块,要具备一个数据延时功能。

        这一段代码现将输入进来的实部和虚部信号进行缓存,就是打了一拍。同时TempInputEnable标志拉高。

reg TempInputEnable;
/*输入数据的缓存******//
reg [7:0] TempDataInRe, TempDataInIm;
always@(posedge Clk or negedge Rst_n)
begin
	if (!Rst_n)
   	begin
	   	TempInputEnable <= 0;
	   	TempDataInRe <= 8'b00000000;
	   	TempDataInIm <= 8'b00000000;
		end
	else
		begin
			if (InputEnable)
				begin
		     	/*在输入数据有效下 把输入数据有效和数据缓存******//
					TempInputEnable <= 1;
					TempDataInRe <= DataInRe;
					TempDataInIm <= DataInIm;
		  		end
	    	else
	       	begin
	         	TempInputEnable <= 0;
	         	TempDataInRe <= 8'b00000000;
	          	TempDataInIm <= 8'b00000000;		  		  
		  		end	 
	 	end
end

        这一段代码就是将缓存完的数据进行16点的延时打拍,得到对应的标志Buffer_Enable和对应的延时数据DATAA和DATAB,两个数据之间相差16点,用于后面模块的计算输入。

wire [7:0] BufferDataRe;
wire [7:0] BufferDataIm;
shiftramlength16width8 DataRe_shiftramlength16 (
    .CLK(Clk),
    .D(TempDataInRe),
    .Q(BufferDataRe),
    .CE(TempInputEnable));

shiftramlength16width8 DataIm_shiftramlength16 (
    .CLK(Clk),
    .D(TempDataInIm),
    .Q(BufferDataIm),
    .CE(TempInputEnable));


/*//用经过缓存的分组检测有效信号******//
always@(posedge Clk or negedge Rst_n)
begin
	if (!Rst_n)
   	begin
	   	Buffer_Enable <= 0;
	    	DataARe <= 8'b0;
	    	DataAIm <= 8'b0;
	    	DataBRe <= 8'b0;
	    	DataBIm <= 8'b0;
	 	end
	else
      begin
	   	if (TempInputEnable)	/*在分组检测有效下 ******//
				begin
		  			Buffer_Enable <= 1;                  
				 	/*当前输入数据的缓存******//
				 	DataARe <= TempDataInRe;
				 	DataAIm <= TempDataInIm;
				 	/*移位寄存器的输出******//				 
				 	DataBRe <= BufferDataRe;
				 	DataBIm <= BufferDataIm;
			   end
			else
			   begin
	            Buffer_Enable <= 0;
	            DataARe <= 8'b00000000;
	            DataAIm <= 8'b00000000;
	            DataBRe <= 8'b00000000;
	            DataBIm <= 8'b00000000;			   
			   end
		end
end

        这一段代码是将原本16个延时的数据进行了48点的延时,是因为如果找到新的分组数据后,前面数据计算已经消耗了最起码32个时间,若不对数据进行延时,会造成部分数据的丢失。因此对16位的延时数据进行48位的延时,当确定找到新数据后进行数据延时16+48的数据流。

wire [7:0] ReceiveDataRe;
wire [7:0] ReceiveDataIm;

shiftramlength48width8 DataRe_shiftramlength48 (
    .CLK(Clk),
    .D(BufferDataRe),
    .Q(ReceiveDataRe),
    .CE(TempInputEnable));

shiftramlength48width8 DataIm_shiftramlength48 (
    .CLK(Clk),
    .D(BufferDataIm),
    .Q(ReceiveDataIm),
    .CE(TempInputEnable));
/*************************************************************************************************/

/*************************************************************************************************/
/*****************************在分组检测完成后 从移位寄存器中输出数据*****************************/
always@(posedge Clk or negedge Rst_n)
begin
   if (!Rst_n)
   	begin
	    	OutputEnable <= 0;
	    	DataOutRe <= 8'b00000000;
	    	DataOutIm <= 8'b00000000;
	 	end
   else
      begin
	    	if (FrameFinded) /*在分组检测完成下******//
	       	begin
					OutputEnable <= 1;
					DataOutRe <= ReceiveDataRe;
				 	DataOutIm <= ReceiveDataIm;
			   end
			else
			   begin
	            OutputEnable <= 0;
	            DataOutRe <= 8'b00000000;
	            DataOutIm <= 8'b00000000;			   
			   end
		end
end
/*************************************************************************************************/

2.延时相关能量计算模块

        这个模块就是计算前面公式mn的分子的模块,输入我们已经通过上一个模块得到了,当前数据A和前16点数据B。接下来就是进行数据的计算以及公式的实现了。

         C_n=\sum_{k=0}^{L-1}r_{n-k}*r_{n-k-D}^{*} 公式贴这,先算乘积,再算累加求和,再算幅值。

2.1延迟相关计算

        首先对公式进行了化简:通过化简将乘法器降成了2个,这公式里面A、B数据就对应着当前数据个前16点数据。

        因此化简完之后的公式流程就变成了,先算加减,再算乘除,再算加减。

        这一段代码是缓存进来的AB数据,同时B数据注意共轭变换一下。

//the input datas buffer
reg signed[7:0] BufferDataARe;
reg signed[7:0] BufferDataAIm;
reg signed[7:0] BufferDataBRe;
reg signed[7:0] BufferDataBIm;
//the enable singal buffer
reg BufferEnable;

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				BufferEnable <= 0;
				BufferDataARe <= 0;
				BufferDataAIm <= 0;
				BufferDataBRe <= 0;
				BufferDataBIm <= 0;
			end
		else
			begin
				if(InputEnable)
					begin
						BufferEnable <= 1;
						BufferDataARe <= DataInARe;
						BufferDataAIm <= DataInAIm;
						BufferDataBRe <= DataInBRe;
						BufferDataBIm <= -DataInBIm;
					end
				else
					begin
						BufferEnable <= 0;
						BufferDataARe <= 0;
						BufferDataAIm <= 0;
						BufferDataBRe <= 0;
						BufferDataBIm <= 0;
					end
			end
	end

        这一段代码是计算加减的

reg signed[8:0] TempSumA;
reg signed[8:0] TempDifferenceA;
reg signed[8:0] TempSumB;
reg signed[7:0] TempARe;
reg signed[7:0] TempBRe;
reg signed[7:0] TempBIm;
reg Temp_En;
//compute Ar+Ai,Ar-Ai, and Br+Bi
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				Temp_En <= 0;
				TempSumA <= 0;
				TempDifferenceA <= 0;
				TempSumB <= 0;
				TempARe <= 0;
				TempBRe <= 0;
				TempBIm <= 0;
			end
		else
			begin
				if(BufferEnable)
					begin
						Temp_En <= 1;
						TempSumA <= {BufferDataARe[7],BufferDataARe} + {BufferDataAIm[7],BufferDataAIm};
						TempDifferenceA <= {BufferDataARe[7],BufferDataARe} - {BufferDataAIm[7],BufferDataAIm};
						TempSumB <= {BufferDataBRe[7],BufferDataBRe} + {BufferDataBIm[7],BufferDataBIm};
						TempARe <= BufferDataARe;
						TempBRe <= BufferDataBRe;
						TempBIm <= BufferDataBIm;
					end
				else
					begin
						Temp_En <= 0;
						TempSumA <= 0;
						TempDifferenceA <= 0;
						TempSumB <= 0;
						TempARe <= 0;
						TempBRe <= 0;
						TempBIm <= 0;
					end
			end
	end

        这一段算的是乘积

wire [16:0] SumA_mult_Bi;
wire [16:0] DifferenceA_mult_Br;
wire [16:0] SumB_mult_Ar;
reg rdy;
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
			 rdy<=1'b0;
			end
		else begin
		    rdy<=Temp_En;
		end
	end


//compute Bi*(Ar+Ai)
width9_multiply_width8 SumAmultiplyBr (
    .CLK(Clk),
    .A(TempSumA),
    .B(TempBIm),
    .P(SumA_mult_Bi)
    );
	 
//compute Ar*(Br+Bi)
width9_multiply_width8 SumBmultiplyAr (
    .CLK(Clk),
    .A(TempSumB),
    .B(TempARe),
    .P(SumB_mult_Ar)
    );

//compute Bi*(Ar-Ai)
width9_multiply_width8 DifferenceAmultiplyBi (
    .CLK(Clk),
    .A(TempDifferenceA),
    .B(TempBRe),
    .P(DifferenceA_mult_Br)
    );

        这一段是将上面算出来的加减乘除结合在一起

reg [17:0] TempRe;
reg [17:0] TempIm;
reg TempEnable;
//compute Ar*(Br+Bi)- Bi*(Ar-Ai) and Br*(Ar+Ai) - Ar*(Br+Bi)
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				TempEnable <= 1'b0;
				TempRe <= 0;
				TempIm <= 0;
			end
		else
			begin
				if(rdy)
					begin//Ar*(Br+Bi)-Bi*(Ar+Ai)
						TempRe <= {SumB_mult_Ar[16],SumB_mult_Ar} - {SumA_mult_Bi[16],SumA_mult_Bi};
						//Ar*(Br+Bi)-Br*(Ar-Ai)
						TempIm <= {SumB_mult_Ar[16],SumB_mult_Ar} - {DifferenceA_mult_Br[16],DifferenceA_mult_Br};
						TempEnable <= 1'b1;
					end
				else
					begin
						TempRe <= 0;
						TempIm <= 0;
						TempEnable <= 1'b0;
					end
			end
	end

        这一段代码是将计算出的相关数据变为16位,并输出

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				OutputEnable <= 0;
				DataOutRe <= 0;
				DataOutIm <= 0;
			end
		else
			begin
				if(TempEnable)
					begin
						OutputEnable <= 1;
						DataOutRe <= {TempRe[17],TempRe[14:0]};
						DataOutIm <= {TempIm[17],TempIm[14:0]};
					end
				else
					begin
						OutputEnable <= 0;
						DataOutRe <= 0;
						DataOutIm <= 0;
					end
			end
	end

2.2相关累加计算

        上一个模块算完了,信号相关性的计算,这个模块将信号相关性进行累加和。

        先把上个模块输出的相关计算实部和虚部缓存下来:

reg signed[15:0] BufferDataRe;
reg signed[15:0] BufferDataIm;

always@(posedge Clk or negedge Rst_n)
	begin
   	if (!Rst_n)
      	begin
	    		BufferInputEnable <= 0;
	    		BufferDataRe <= 16'b0;
	    		BufferDataIm <= 16'b0;
	 		end
   	else
      	begin
	    		if (InputEnable)
	       		begin
		  				BufferInputEnable <= 1;
						BufferDataRe <= DelayCorrelationRe;
						BufferDataIm <= DelayCorrelationIm;
		  			end
	    		else
	       		begin
	          		BufferInputEnable <= 0;
	          		BufferDataRe <= 16'b00000000_00000000;
	          		BufferDataIm <= 16'b00000000_00000000;		  		  
		  			end
	 		end
	end

        然后计算累加和的本质就是,加进来当前时刻的相关,并减去16点前的同步输出

reg TempEnable;
reg signed[16:0] TempDataRe;
reg signed[16:0] TempDataIm;
//compute MagnituderBuffer[0]-MagnituderBuffer[16]
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				TempEnable <= 0;
				TempDataRe <= 0;
				TempDataIm <= 0;
			end
		else
			begin
				if(BufferInputEnable)
					begin
						TempEnable <= 1;
						TempDataRe <= {BufferDataRe[15],BufferDataRe} - {ShiftDataRe[15],ShiftDataRe};
						TempDataIm <= {BufferDataIm[15],BufferDataIm} - {ShiftDataIm[15],ShiftDataIm};
					end
				else
					begin
						TempEnable <= 0;
						TempDataRe <= 0;
						TempDataIm <= 0;
					end
			end
	end
always@(posedge Clk or negedge Rst_n)
begin
   if (!Rst_n)
      begin
			OutputEnable <= 0;
			Sum16DelayCorrelationRe <= 0;
			Sum16DelayCorrelationIm	<= 0;
		end
	else
		begin
			if(TempEnable)
				begin
					OutputEnable <= 1;
					Sum16DelayCorrelationRe <= Sum16DelayCorrelationRe + {{3{TempDataRe[16]}},TempDataRe};
					Sum16DelayCorrelationIm	<= Sum16DelayCorrelationIm + {{3{TempDataIm[16]}},TempDataIm};
				end
			else
				begin
					OutputEnable <= 0;
					Sum16DelayCorrelationRe <= 0;
					Sum16DelayCorrelationIm	<= 0;
				end
		end
end

 2.3赋值简化计算

        完成了共轭乘积和累加,然后就剩最后一步算幅值,这一步完成整个分子的计算就完成了。

        这一步比较简单,参考上面说的简化公式,就是直接将实部和虚部相加即可。

reg signed[19:0] TempDataRe;
reg signed[19:0] TempDataIm;
reg TempEnable;
//Compute |SumDelayCorrelationDataInRe| and |SumDelayCorrelationDataInIm|
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				TempEnable <= 0;
				TempDataRe <= 0;
				TempDataIm <= 0;
			end
		else
			begin
				if(InputEnable)
					begin
						TempEnable <= 1;
						if(SumDelayCorrelationDataInRe[19])
							TempDataRe <= ~SumDelayCorrelationDataInRe + 1;
						else
							TempDataRe <= SumDelayCorrelationDataInRe;
						if(SumDelayCorrelationDataInIm[19])
							TempDataIm <= ~SumDelayCorrelationDataInIm + 1;
						else
							TempDataIm <= SumDelayCorrelationDataInIm;
					end
				else
					begin
						TempEnable <= 0;
						TempDataRe <= 0;
						TempDataIm <= 0;
					end
			end
	end

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				OutputEnable <= 0;
				SumDelayCorrelationMagnituder <= 0;
			end
		else
			begin
				if(TempEnable)
					begin
						OutputEnable <= 1;
						SumDelayCorrelationMagnituder <= {TempDataRe[19],TempDataRe} + {TempDataIm[19],TempDataIm};
					end
				else
					begin
						OutputEnable <= 0;
						SumDelayCorrelationMagnituder <= 0;
					end
			end
	end

 

3.相关窗口能量计算

m_n=\frac{C_n}{P_n}=\frac{\sum_{k=0}^{L-1}r_{n-k}*r_{n-k-D}^{*}}{\sum_{k=0}^{L-1}r_{n-k-D}*r_{n-k-D}^{*}} 

        上个模块算完了分子的幅值,这个模块就开始算分母了。分母化简后的流程就是先算幅值,然后求和即可。

        首先还是计算A的幅值。先缓存数据,然后各自相乘再相加就是幅值了。

reg BufferEnable;
reg signed[7:0]BufferDataRe;
reg signed[7:0]BufferDataIm;

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				BufferEnable <= 0;
				BufferDataRe <= 0;
				BufferDataIm <= 0;
			end
		else
			begin
				if(InputEnable)
					begin
						BufferEnable <= 1;
						BufferDataRe <= DataInARe;
						BufferDataIm <= DataInAIm;
					end
				else
					begin
						BufferEnable <= 0;
						BufferDataRe <= 0;
						BufferDataIm <= 0;
					end
			end
	end	
wire signed[15:0] TempSumA;
wire signed[15:0] TempSumB;
reg rdy;
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
			 rdy<=1'b0;
			end
		else begin
		    rdy<=BufferEnable;
		end
	end

width8_multiply_width8 multiplierRe (
    .CLK(Clk),
    .A(BufferDataRe),
    .B(BufferDataRe),
    .P(TempSumA)
    );

width8_multiply_width8 multiplierIm (
    .CLK(Clk),
    .A(BufferDataIm),
    .B(BufferDataIm),
    .P(TempSumB)

    );

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				OutputEnable <= 0;
				DataMagnitude <= 0;
			end
		else
			begin
				if(rdy)
					begin
						OutputEnable <= 1;
						DataMagnitude <= {TempSumA[15],TempSumA} + {TempSumB[15],TempSumB};
					end
				else
					begin
						OutputEnable <= 0;
						DataMagnitude <= 0;
					end
			end
	end

        然后将算出的幅值进行累加:过程还是一样,先缓存,然后先算加减,再算累加。

reg BufferInputEnable;
reg signed[16:0] BufferMagnituder;

always@(posedge Clk or negedge Rst_n)
	begin
   	if (!Rst_n)
      	begin
	    		BufferInputEnable <= 0;
	    		BufferMagnituder <= 17'b0;
	 		end
   	else
      	begin
	    		if (InputEnable)
	       		begin
		  				BufferInputEnable <= 1;
						BufferMagnituder <= DataInMagnituder;
		  			end
	    		else
	       		begin
	          		BufferInputEnable <= 0;
	          		BufferMagnituder <= 17'b00000000_00000000;	  		  
		  			end
	 		end
	end
/******************************************************************************************/
wire signed[16:0]ShiftMagnituder;

shiftramlength16width17 ShiftRamLength16width16_DataRe (
    .CLK(Clk),
    .D(BufferMagnituder),
    .Q(ShiftMagnituder),
    .CE(BufferInputEnable));

/****************************把移位寄存器的输出缓存****************************************/
/*Compute Sum16Magnituder = Sum16Magnituder + MagnituderBuffer[0] ******//
/*                            - MagnituderBuffer[16]          ******//   
reg TempEnable;
reg signed[17:0]TempMagnituder;
//compute MagnituderBuffer[0]-MagnituderBuffer[16]
always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				TempEnable <= 0;
				TempMagnituder <= 0;
			end
		else
			begin
				if(BufferInputEnable)
					begin
						TempEnable <= 1;
						TempMagnituder <= {BufferMagnituder[16],BufferMagnituder} - {ShiftMagnituder[16],ShiftMagnituder};
					end
				else
					begin
						TempEnable <= 0;
						TempMagnituder <= 0;
					end
			end
	end

always@(posedge Clk or negedge Rst_n)
begin
   if (!Rst_n)
      begin
			OutputEnable <= 0;
			Sum16Magnituder <= 0;
		end
	else
		begin
			if(TempEnable)
				begin
					OutputEnable <= 1;
					Sum16Magnituder <= Sum16Magnituder + {{3{TempMagnituder[17]}},TempMagnituder};
				end
			else
				begin
					OutputEnable <= 0;
					Sum16Magnituder <= 0;
				end
		end
end

        最后结合公式,观察波形注意时序。 整个时序之间差了20个点,因此还要进行20点的延时,如果这个模块输入是B数据,那就是4个点的延时。

        如图是输出B数据的延时是4个点,代码是20点输入A数据的情况。

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				BufferEnable1 <= 0;
				BufferData1 <= 0;
				BufferEnable2 <= 0;
				BufferData2 <= 0;
				BufferEnable3 <= 0;
				BufferData3 <= 0;
                BufferEnable4 <= 0;
				BufferData4 <= 0;
				BufferEnable5 <= 0;
				BufferData5 <= 0;
				BufferEnable6 <= 0;
				BufferData6 <= 0;
                BufferEnable7 <= 0;
				BufferData7 <= 0;
				BufferEnable8 <= 0;
				BufferData8 <= 0;
				BufferEnable9 <= 0;
				BufferData9 <= 0;
                BufferEnable10 <= 0;
				BufferData10 <= 0;
				BufferEnable11 <= 0;
				BufferData11 <= 0;
				BufferEnable12 <= 0;
				BufferData12 <= 0;
                BufferEnable13 <= 0;
				BufferData13 <= 0;
				BufferEnable14 <= 0;
				BufferData14 <= 0;
				BufferEnable15 <= 0;
				BufferData15 <= 0;
                BufferEnable16 <= 0;
				BufferData16 <= 0;
				BufferEnable17 <= 0;
				BufferData17 <= 0;
				BufferEnable18 <= 0;
				BufferData18 <= 0;
                BufferEnable19 <= 0;
				BufferData19 <= 0;
				OutputEnable <= 0;
				DataOut <= 0;
			end
		else
			begin
				BufferEnable1 <= InputEnable;
				BufferData1 <= DataIn;
				BufferEnable2 <= BufferEnable1;
				BufferData2 <= BufferData1;
				BufferEnable3 <= BufferEnable2;
				BufferData3 <= BufferData2;
                BufferEnable4 <= BufferEnable3;
				BufferData4 <= BufferData3;
                BufferEnable5 <= BufferEnable4;
				BufferData5 <= BufferData4;
                BufferEnable6 <= BufferEnable5;
				BufferData6 <= BufferData5;
                BufferEnable7 <= BufferEnable6;
				BufferData7 <= BufferData6;
                BufferEnable8 <= BufferEnable7;
				BufferData8 <= BufferData7;
                BufferEnable9 <= BufferEnable8;
				BufferData9 <= BufferData8;
                BufferEnable10 <= BufferEnable9;
				BufferData10 <= BufferData9;
                BufferEnable11 <= BufferEnable10;
				BufferData11 <= BufferData10;
                BufferEnable12 <= BufferEnable11;
				BufferData12 <= BufferData11;
                BufferEnable13 <= BufferEnable12;
				BufferData13 <= BufferData12;
                BufferEnable14 <= BufferEnable13;
				BufferData14 <= BufferData13;
                BufferEnable15 <= BufferEnable14;
				BufferData15 <= BufferData14;
                BufferEnable16 <= BufferEnable15;
				BufferData16 <= BufferData15;
                BufferEnable17 <= BufferEnable16;
				BufferData17 <= BufferData16;
                BufferEnable18 <= BufferEnable17;
				BufferData18 <= BufferData17;
                BufferEnable19 <= BufferEnable18;
				BufferData19 <= BufferData18;
				OutputEnable <= BufferEnable19;
				DataOut <= BufferData19;
			end
	end

 4.帧检测模块

        算完了分子和分母,就可以开始对判决变量进行操作了。

        先缓存进来的窗口能量和延时相关能量:

reg [20:0] BufferSumMagnituder;
reg [20:0] BufferSumDelayCorrelation;
reg BufferEnable;

always @(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				BufferEnable <= 0;
				BufferSumMagnituder <= 0;
				BufferSumDelayCorrelation <= 0;
			end
		else
			begin
				if((SumMagnituderEnable)&&(SumDelayCorrelationEnable) ) /*两路信号同时有效******//
					begin
						BufferEnable <= 1;
						BufferSumMagnituder <= SumMagnituder;
						BufferSumDelayCorrelation <= SumDelayCorrelation;
					end
				else
					begin
						BufferEnable <= 0;
						BufferSumMagnituder <= 0;
						BufferSumDelayCorrelation <= 0;
					end
			end
	end

        然后就要根据缓存的这两个数据找开头和结束,首先是开头,开头就是mn,也就是简化后的0.5pn>cn。结束的标志就是窗口能量小于某个阈值。 同时还要加上长度保持!

always@(posedge Clk or negedge Rst_n)
	begin
   	if (!Rst_n)	/*全局复位******//
	 		begin
	    		TempDetection <=0;
		 		frame_end_search <=0;
	 		end
   	else
      	begin
	    		if (BufferEnable)
	       		begin
		     			if ((BufferSumMagnituder>>1) < BufferSumDelayCorrelation)
							begin
			   	 			TempDetection <= 1;
							end
            		else
							begin
			   	 			TempDetection <= 0;
							end

			
						if (BufferSumMagnituder < 21'b0000001_0000_0000_0001)
							begin
								frame_end_search <= 1;
							end
						else
							begin
								frame_end_search <= 0;
							end
					end
			end
	end

        最后通过两个标志TEMPDETECETION和FRAME_END_SEARCH分别保持32点和48点决定最终输出有效标志的开始和结束。

always@(posedge Clk or negedge Rst_n)
	begin
		if(!Rst_n)
			begin
				BufferForDetection <= 32'b00000000_00000000_00000000_00000000;
 	    
				frame_end_buffer <= 48'b00000000_00000000_00000000_00000000_00000000_00000000;
			end
		else
			begin
				BufferForDetection[31] <= BufferForDetection[30];
				BufferForDetection[30] <= BufferForDetection[29];
			
				BufferForDetection[29] <= BufferForDetection[28];
				BufferForDetection[28] <= BufferForDetection[27];
				BufferForDetection[27] <= BufferForDetection[26];
				BufferForDetection[26] <= BufferForDetection[25];
				BufferForDetection[25] <= BufferForDetection[24];
				BufferForDetection[24] <= BufferForDetection[23];
				BufferForDetection[23] <= BufferForDetection[22];
				BufferForDetection[22] <= BufferForDetection[21];
         	    BufferForDetection[21] <= BufferForDetection[20];
				BufferForDetection[20] <= BufferForDetection[19];
			
				BufferForDetection[19] <= BufferForDetection[18];
				BufferForDetection[18] <= BufferForDetection[17];
				BufferForDetection[17] <= BufferForDetection[16];
				BufferForDetection[16] <= BufferForDetection[15];
				BufferForDetection[15] <= BufferForDetection[14];
				BufferForDetection[14] <= BufferForDetection[13];
				BufferForDetection[13] <= BufferForDetection[12];
				BufferForDetection[12] <= BufferForDetection[11];
            	BufferForDetection[11] <= BufferForDetection[10];
				BufferForDetection[10] <= BufferForDetection[9];
			
				BufferForDetection[9] <= BufferForDetection[8];
				BufferForDetection[8] <= BufferForDetection[7];
				BufferForDetection[7] <= BufferForDetection[6];
				BufferForDetection[6] <= BufferForDetection[5];
				BufferForDetection[5] <= BufferForDetection[4];
				BufferForDetection[4] <= BufferForDetection[3];
				BufferForDetection[3] <= BufferForDetection[2];
				BufferForDetection[2] <= BufferForDetection[1];
            	BufferForDetection[1] <= BufferForDetection[0];
				BufferForDetection[0] <= TempDetection;


				/*分组结束位置的寻找******//

				frame_end_buffer[47] <= frame_end_buffer[46];
				frame_end_buffer[46] <= frame_end_buffer[45];
				frame_end_buffer[45] <= frame_end_buffer[44];
				frame_end_buffer[44] <= frame_end_buffer[43];
				frame_end_buffer[43] <= frame_end_buffer[42];
				frame_end_buffer[42] <= frame_end_buffer[41];
				frame_end_buffer[41] <= frame_end_buffer[40];
				frame_end_buffer[40] <= frame_end_buffer[39];
			
				frame_end_buffer[39] <= frame_end_buffer[38];
				frame_end_buffer[38] <= frame_end_buffer[37];
				frame_end_buffer[37] <= frame_end_buffer[36];
				frame_end_buffer[36] <= frame_end_buffer[35];
				frame_end_buffer[35] <= frame_end_buffer[34];
				frame_end_buffer[34] <= frame_end_buffer[33];
				frame_end_buffer[33] <= frame_end_buffer[32];
				frame_end_buffer[32] <= frame_end_buffer[31];
				frame_end_buffer[31] <= frame_end_buffer[30];
				frame_end_buffer[30] <= frame_end_buffer[29];
			
				frame_end_buffer[29] <= frame_end_buffer[28];
				frame_end_buffer[28] <= frame_end_buffer[27];
				frame_end_buffer[27] <= frame_end_buffer[26];
				frame_end_buffer[26] <= frame_end_buffer[25];
				frame_end_buffer[25] <= frame_end_buffer[24];
				frame_end_buffer[24] <= frame_end_buffer[23];
				frame_end_buffer[23] <= frame_end_buffer[22];
				frame_end_buffer[22] <= frame_end_buffer[21];
         	frame_end_buffer[21] <= frame_end_buffer[20];
				frame_end_buffer[20] <= frame_end_buffer[19];
			
				frame_end_buffer[19] <= frame_end_buffer[18];
				frame_end_buffer[18] <= frame_end_buffer[17];
				frame_end_buffer[17] <= frame_end_buffer[16];
				frame_end_buffer[16] <= frame_end_buffer[15];
				frame_end_buffer[15] <= frame_end_buffer[14];
				frame_end_buffer[14] <= frame_end_buffer[13];
				frame_end_buffer[13] <= frame_end_buffer[12];
				frame_end_buffer[12] <= frame_end_buffer[11];
         	    frame_end_buffer[11] <= frame_end_buffer[10];
				frame_end_buffer[10] <= frame_end_buffer[9];
			
				frame_end_buffer[9] <= frame_end_buffer[8];
				frame_end_buffer[8] <= frame_end_buffer[7];
				frame_end_buffer[7] <= frame_end_buffer[6];
				frame_end_buffer[6] <= frame_end_buffer[5];
				frame_end_buffer[5] <= frame_end_buffer[4];
				frame_end_buffer[4] <= frame_end_buffer[3];
				frame_end_buffer[3] <= frame_end_buffer[2];
				frame_end_buffer[2] <= frame_end_buffer[1];
         	    frame_end_buffer[1] <= frame_end_buffer[0];
				frame_end_buffer[0] <= frame_end_search;
			end
	end


			
always@(posedge Clk or negedge Rst_n)
begin
	if(!Rst_n)
		begin
			FrameFind<=0;
		end
	else
		begin
			if (BufferEnable) /*两路信号同时有效******//
				begin
					if (BufferForDetection == 32'b11111111_11111111_11111111_11111111)
						begin
							FrameFind <= 1;
						end
					else 	if ( frame_end_buffer == 48'b11111111_11111111__11111111_11111111_11111111_11111111)
						begin
							FrameFind <= 0;
						end
				end
         else /*两路信号没有同时有效******//
	       begin
				FrameFind <= 0;
			 end
		end
end

总结

        理解教材公式,做好数据控制,验证数据计算。

        实际上板需要结合实际更新阈值等数据。

        代码参考教材:基于xilinx FPGA的OFDM通信系统基带设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值