欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > OFDM接收机学习-第二章 符号同步模块FPGA的实现

OFDM接收机学习-第二章 符号同步模块FPGA的实现

2025/9/20 3:46:27 来源:https://blog.csdn.net/g_125487/article/details/145091350  浏览:    关键词:OFDM接收机学习-第二章 符号同步模块FPGA的实现

系列文章目录

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

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


文章目录

前言

一、符号同步的目的

二、符号同步算法描述

2.1符号同步原理

2.2符号同步算法简化 

2.3符号同步偏移的影响

2.4符号同步的硬件结构 

三、符号同步算法在FPGA上的实现

3.1量化模块

3.2匹配滤波模块

3.2.1 相关累加计算

3.2.2幅值简化计算

3.2.3峰值寻找

3.3符号输出模块

总结


前言

        第一章根据短序列的周期性以及延迟相关并长度保持算法进行了判断新数据分组到来的判断。输出的结果就是根据输入给与一个大概位置的有效标志,之后更加精确的判断交给后面的其他模块。因为本实验只使用了一个载波,所以不需要进行载波同步,直接进入符号同步,符号同步会充分利用短序列,燃烧最后价值。消除空闲间隔,输出长序列以及有效数据。

上板环境:

ILA抓取波形:可以看到短序列消失,只输出了长序列和数据域的有效值。3.2us


一、符号同步的目的

        符号同步是对细节的打磨,是求得单个OFDM符号开始以及结束的精确时刻。

二、符号同步算法描述

2.1符号同步原理

        充分利用已知的前导结构,也就是短序列。对于发射机和接收机来讲,短序列的数值本身就是固定的,即使通过传输也不会发生太大改变。将接受到的实际信号与已知的短序列进行互相关计算,进而进一步定位符号开始和结束的准备时刻。

        将接受的数据与本地已知的段训练序列进行互相关计算,可依据公式1,D毋庸置疑就是窗口的长度,也就是短序列的点数,16点。其他的参数跟第一章基本一致。

        C_k=\sum_{m=0}^{D-1}r_{k-m}*S_m^{*}     (1)

        当新的数据来到时,最前面的10个段训练符号依次进行互相关计算,结合第一章的计算过程可以想到,由于数值的相关性,理论情况下,在每个段训练符号的结束时刻就是相关数值的峰值,因此10个段训练符号会得到10个峰值。因此我们只需要判断这个峰值大于某个阈值然后进行累加10次,就可以判断出每个符号的结束时刻。

2.2符号同步算法简化 

        关于寻找峰值的优化,设定一个阈值,超过这个阈值就是出现了峰,即找到了峰值。

        短训练序列为16点,每一个都是复数的数据类型,消耗的乘法器资源过多。因此采用持续累加短序列符号的方法降低噪声的影响,并且将接收到的信号量化为{-1,+1},大大节省了硬件资源并提高了运算速度。

        简化完的效果也可以实现预想的效果,win。

        

2.3符号同步偏移的影响

        由于多径效应的影响,可能造成符号同步估计的时刻不准,可能正好,可能提前,可能落后。一旦偏了就会对后面数据域的取值造成偏移,进而fft计算结果出现错误。

        分析一下危害:正好不多说了,理想状态。提前就是会多一点循环前缀,这个对结果影响不是很大。如果落后了,会包括下一个符号的循环前缀,这样影响比较大。所以取点的时候,一般直接前移一些点。教材给出的经验值是4-6点,这个具体的值还要根据你自己的实际情况进行更改。

2.4符号同步的硬件结构 

        三步走,量化,匹配滤波,符号输出。

        

        当分组检测模块的输出数据到达符号同步模块时,为了降低运算复杂度及对资源的需求,首先通过量化器把接收到的信号量化为(-1,1)。量化后的接收信号在接下来的匹配滤波器中进行与本地短训练符号的相关计算、相关值累加、幅值计算及峰值的寻找,最后确定短训练符号的结束位置。符号输出模块负责在找到短训练符号的结束点后,按后续处理要求去除循环前缀,输出长训练符号与数据符号:且当接收数据不是symbol长度的整数倍时,在其后补零以满足整数倍条件。由于短训练符号在后续模块均不再使用,故此模块不再输出短训练符号。

三、符号同步算法在FPGA上的实现

3.1量化模块

        短序列符号16点,持续累加后,分别将16个最高位缓存下来,正为0,负为1。     先把传过来的实部和虚部缓存下来。

reg [7:0]BufferDataR;
reg [7:0]BufferDataI;always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginBufferEnable <= 0;BufferDataR <= 0;BufferDataI <= 0;endelsebeginif(inEn)beginBufferEnable <= 1;BufferDataR <= bitInR;BufferDataI <= bitInI;endelsebeginBufferEnable <= 0;BufferDataR <= 0;BufferDataI <= 0;endendend

        进行扩展累加缓存

reg [191:0] Continual_Accumulation_Real;		  
reg [191:0] Continual_Accumulation_Imag;
/*持续累加有效信号 *//
reg AddEnable;	
//********************************取得量化结果********************************//
always @ (posedge Clk or negedge Rst_n)beginif (!Rst_n)beginContinual_Accumulation_Real <= 0;	Continual_Accumulation_Imag <= 0;AddEnable <= 0;endelsebeginif(BufferEnable)begin/*持续累加移位寄存器左移一个单元*****//Continual_Accumulation_Real[191:12] <= Continual_Accumulation_Real[179:0];	  Continual_Accumulation_Imag[191:12] <= Continual_Accumulation_Imag[179:0];/*最高一个单元与输入数据的12位扩展相加赋值给最低一个单元****//Continual_Accumulation_Real[11:0] <= {{4{BufferDataR[7]}},BufferDataR} + Continual_Accumulation_Real[191:180]; Continual_Accumulation_Imag[11:0] <= {{4{BufferDataI[7]}},BufferDataI} + Continual_Accumulation_Imag[191:180];AddEnable <= 1;endelsebeginContinual_Accumulation_Real <= 0;Continual_Accumulation_Imag <= 0;AddEnable <= 0;endendend

        将最低位12位的最高位缓存到量化数组中

always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginQuantization_Result_Real <= 0;Quantization_Result_Imag <= 0;	QuantizationEnable <= 0;endelsebeginif(AddEnable)beginQuantizationEnable <= 1;/*量化结果移位******//Quantization_Result_Real[14:0] <= Quantization_Result_Real[15:1];			Quantization_Result_Imag[14:0] <= Quantization_Result_Imag[15:1];/*最高位为0,表正,量化为+1, 在此用0代替,下面语句只是用于判断******//Quantization_Result_Real[15] <= Continual_Accumulation_Real[11];/*最高位为1,表负,量化为-1,在此用1表示******//Quantization_Result_Imag[15] <= Continual_Accumulation_Imag[11];	 endelsebeginQuantization_Result_Real <= 0;Quantization_Result_Imag <= 0;	QuantizationEnable <= 0;endendend

3.2匹配滤波模块

        匹配滤波模块主要负责寻找各个短训练符号的结束点。经过量化处理后,接收信号送入匹配滤波单元,首先与本地16个短训练符号取样进行相关计算,并将相关值累加求和,然后通过寻找其幅值的峰值来确定各个短训练符号的结束点,其实现结构如图所示,可分为相关及累加计算、幅值简化计算和峰值寻找三部分。

                                                        C_k=\sum_{m=0}^{D-1}r_{k-m}*S_m^{*} 

      

3.2.1 相关累加计算

        将量化后的数据与本地的短序列共轭进行相关计算。

        由于量化的存在,所以共轭乘积就可以简化成了4中加减法运算:

        先把传过来的量化数据存下来:

//the enable signal Buffer
reg BufferEnable;
//the input datas buffer
reg [15:0]BufferDataR;
reg [15:0]BufferDataI;always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginBufferEnable <= 0;BufferDataR <= 0;BufferDataI <= 0;endelsebeginif(QuanEnable)beginBufferEnable <= 1;BufferDataR <= QuanDataR;BufferDataI <= QuanDataI;endelsebeginBufferEnable <= 0;BufferDataR <= 0;BufferDataI <= 0;endendend

         进行16点的计数,因为STS16点

reg [4:0]Counter;
reg TempEnable;
always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginCounter <= 0;TempEnable <= 0;endelsebeginif(BufferEnable)beginif(Counter < 15)  //when the counter is 16, the enable of correlation is set high, beacuse the lenght of the STS is 16 Counter <= Counter + 1;elseTempEnable <= 1;endelsebeginCounter <= 0;TempEnable <= 0;endendend

        进行计算,调用模块,改变对应的输入即可,4种情况

 always @ (posedge Clk or negedge Rst_n)	beginif (!Rst_n)beginoutput_Real <= 0;output_Imag <= 0;OutputEnable <= 0;endelse if (inEn)beginOutputEnable <= 1;		  								              if (multiplier_Real == 0 && multiplier_Imag == 0)			 beginoutput_Real <= {{1{known_Real[15]}},known_Real} + {{1{known_Imag[15]}},known_Imag};output_Imag <= {{1{known_Real[15]}},known_Real} - {{1{known_Imag[15]}},known_Imag};endelse if (multiplier_Real == 0 && multiplier_Imag == 1)beginoutput_Real <= {{1{known_Real[15]}},known_Real} - {{1{known_Imag[15]}},known_Imag};output_Imag <= - {{1{known_Real[15]}},known_Real} - {{1{known_Imag[15]}},known_Imag};endelse if (multiplier_Real == 1 && multiplier_Imag == 0)beginoutput_Real <= - {{1{known_Real[15]}},known_Real} + {{1{known_Imag[15]}},known_Imag};output_Imag <= {{1{known_Real[15]}},known_Real} + {{1{known_Imag[15]}},known_Imag};endelse  //(buffer_multiplier_Real==1 && buffer_multiplier_Imag==1)beginoutput_Real <= - {{1{known_Real[15]}},known_Real} - {{1{known_Imag[15]}},known_Imag};output_Imag <= - {{1{known_Real[15]}},known_Real} + {{1{known_Imag[15]}},known_Imag};endendelse		 beginoutput_Real <= 0;output_Imag <= 0;OutputEnable <= 0;end            end

        都算完了,进行累加

always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginCorrelationEnable <= 0;CorrelationSumR <= 0;CorrelationSumI <= 0;endelsebeginif(TempEnable&CorrelationEn0&CorrelationEn1&CorrelationEn2&CorrelationEn3&CorrelationEn4&CorrelationEn5&CorrelationEn6&CorrelationEn7&CorrelationEn8&CorrelationEn9&CorrelationEn10&CorrelationEn11&CorrelationEn12&CorrelationEn13&CorrelationEn14&CorrelationEn15)begin/*赋值语句右边的操作数位宽已扩展为21位,跟左边的结果位宽一致,保证带符号位二进制加法运算的正确性*******//CorrelationSumR <= ((({{4{CorrelationR0[16]}},CorrelationR0} + {{4{CorrelationR1[16]}},CorrelationR1}) + ({{4{CorrelationR2[16]}},CorrelationR2} + {{4{CorrelationR3[16]}},CorrelationR3})) + (({{4{CorrelationR4[16]}},CorrelationR4} + {{4{CorrelationR5[16]}},CorrelationR5})+ ({{4{CorrelationR6[16]}},CorrelationR6} + {{4{CorrelationR7[16]}},CorrelationR7}))) + ((({{4{CorrelationR8[16]}},CorrelationR8} + {{4{CorrelationR9[16]}},CorrelationR9})+ ({{4{CorrelationR10[16]}},CorrelationR10} + {{4{CorrelationR11[16]}},CorrelationR11})) + (({{4{CorrelationR12[16]}},CorrelationR12} + {{4{CorrelationR13[16]}},CorrelationR13})+ ({{4{CorrelationR14[16]}},CorrelationR14} + {{4{CorrelationR15[16]}},CorrelationR15})));CorrelationSumI <= ((({{4{CorrelationI0[16]}},CorrelationI0} + {{4{CorrelationI1[16]}},CorrelationI1}) + ({{4{CorrelationI2[16]}},CorrelationI2} + {{4{CorrelationI3[16]}},CorrelationI3})) + (({{4{CorrelationI4[16]}},CorrelationI4} + {{4{CorrelationI5[16]}},CorrelationI5})+ ({{4{CorrelationI6[16]}},CorrelationI6} + {{4{CorrelationI7[16]}},CorrelationI7}))) + ((({{4{CorrelationI8[16]}},CorrelationI8} + {{4{CorrelationI9[16]}},CorrelationI9})+ ({{4{CorrelationI10[16]}},CorrelationI10} + {{4{CorrelationI11[16]}},CorrelationI11})) + (({{4{CorrelationI12[16]}},CorrelationI12} + {{4{CorrelationI13[16]}},CorrelationI13})+ ({{4{CorrelationI14[16]}},CorrelationI14} + {{4{CorrelationI15[16]}},CorrelationI15})));CorrelationEnable <= 1;endelsebeginCorrelationEnable <= 0;CorrelationSumR <= 0;CorrelationSumI <= 0;endendend

3.2.2幅值简化计算

        在得到相关值累加和后,需要计算其幅值,用于峰值判断。显然如果直接计算幅值,不仅需要乘法操作还要开方运算,非常不利于硬件实现。硬件实现上进行式(5-10)简化,即计算输入数据的实部和虚部的绝对值之和,近似其幅值,结构如图所示。首先分别判断实部和虚部是否为正数,若为正数则保持不变,若为负数则其相反数,然后相加。        

        

 always @ (posedge Clk or negedge Rst_n)				    /*输入增加一级缓存,延迟一个时钟周期******//beginif (!Rst_n)beginBufferEnable <= 0;BufferDataRe <= 0;BufferDataIm <= 0;			      endelsebegin					         	                /*缓存的数据为输入数据的绝对值******//if(DataEnable)beginBufferEnable <= 1;if(DataInRe[20] == 0)                /*符号位为0,表示为正数,绝对值即为输入数******//beginBufferDataRe <= DataInRe;endelse								          /*符号位为1,表示为负数,绝对值为输入数取反加1******//beginBufferDataRe <= ~ DataInRe + 1;endif (DataInIm[20] == 0)			       /*虚部运算同实部******//beginBufferDataIm <= DataInIm;endelsebeginBufferDataIm <= ~ DataInIm + 1;endendelsebeginBufferEnable <= 0;BufferDataRe <= 0;BufferDataIm <= 0;endendendalways @ (posedge Clk or negedge Rst_n) beginif (!Rst_n)beginAbsolute <= 0;AbsoluteEnable <= 0;endelsebegin						 if(BufferEnable)begin/*求取实部与虚部的绝对值之和******//Absolute <= {BufferDataRe[20],BufferDataRe} + {BufferDataIm[20],BufferDataIm};    AbsoluteEnable <= 1;endelsebeginAbsolute <= 0;AbsoluteEnable <= 0;endendend							 

3.2.3峰值寻找

        峰值寻找单元主要负责搜索接收的短训练符号取样与本地短训练符号相关累加和幅值的峰值,即短训练符号的结束点。考虑到硬件实现的复杂度,实现上不采用搜寻最大值的方法。而是采用制定门限值的方法来代替。即当累加值超过了预先设定的门限值时,即认为找到峰值。理论上在每一组短训练符号16个取样的结束点,都将产生一个峰值。但由于分组检测模块输出的第一组短训练符号是不完整的,所以本模块只能连续检测到9个峰值点。当检测到第9个峰值时,意味着短训练符号已经结束。

        先缓存下来累加值

reg BufferEnable;
//the input data buffer
reg [21:0]BufferData;always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginBufferEnable <= 0;BufferData <= 0;endelsebeginif(DataEnable)beginBufferEnable <= 1;BufferData <= AbsoluteData;endelsebeginBufferEnable <= 0;BufferData <= 0;endendend

        判断,计数峰值,判断的具体值根据实际结果进行修改

reg [3:0] STS_end_counter;  /*峰值数目计数器******//
always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginSTS_end_counter <= 0;PeakFinded <= 0;endelsebeginif(BufferEnable)begin      /*absolute_sum位宽22位(1位符号位 + 7位整数位 + 14位小数位)******//if(STS_end_counter < 9)beginif (BufferData > 22'b0000_0001_10_0000_0000_0000)//1.5beginSTS_end_counter <= STS_end_counter + 1;  /*大于阈值,计数器加1******//endPeakFinded <= 0;endelsebeginPeakFinded <= 1;  /*当找到9个峰值,即短训练序列的结束位置,把信号拉高******//endendelsebegin                      /*帧结束时,把寄存器赋予初始值******//STS_end_counter <= 0;PeakFinded <= 0;endendend

3.3符号输出模块

        由于数据符号均为16个循环前缀加64个有效数据,在去除循环前缀后数据格式为每64个有效数据之间间隔16个空数据(即这16个时钟没有数据),硬件实现上由一个同步使能信号有效来表示有效数据。而长训练为32个循环前缀加连续两个64样值的格式,为了使长训练符号在去除循环前缀后也保持统一的数据格式,操作上首先输出第一个长训练符号,而第二个长训练符号及后续的数据符号经过深度为16级的移位寄存器输出,如图5-37所示。此外,如果接收数据不为symbol长度的整数倍时,在其后补零以满足整数倍条件。

  就是长序列是挨着的,先输出第一个,然后后面的数据统一延时16点

always @(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginCounter1 <= 0;Counter2 <= 0;DataOutEnable <= 0;DataOutRe <= 0;DataOutIm <= 0;DataSymbol <= 0;BufferOutEnable <= 0;BufferDataSymbol <= 0;BufferDataOutRe <= 0;BufferDataOutIm <= 0;TempSymbol <= 0;endelsebeginif(PeakFinded)beginif(Counter1 <= 85)  //the counter is set by 85, because the processing (quantization,correlation,and so on) delay is 10 clockbeginCounter2 <= 0;Counter1 <= Counter1 + 1;if(Counter1 >= 22 && Counter1 <= 85)//the cyclix prefix of the LTS is 32, and the delay is 10, thus 32-10=22beginDataOutEnable <= 1;DataOutRe <= DataInRe;DataOutIm <= DataInIm;endelsebeginDataOutEnable <= 0;DataOutRe <= 0;DataOutIm <= 0;endif(Counter1 == 22)beginDataSymbol <= DataSymbol + 1;TempSymbol <= DataSymbol + 1;endendelsebegin//when the value of counter2 is between 0 and 63, the input datas are the datas we need//and when the valus of counter2 is between 64 and 79, the input datas are the cyclic prefix of the next symbolif(Counter2 == 79)beginCounter2 <= 0;TempSymbol <= TempSymbol + 1;endelsebeginCounter2 <= Counter2 + 1;endif(Counter2 >= 0 && Counter2 <= 63)beginBufferOutEnable[15] <= 1;BufferDataOutRe[127:120] <= DataInRe; BufferDataOutIm[127:120] <= DataInIm;BufferDataSymbol[127:120] <= TempSymbol + 1;endelsebeginBufferOutEnable[15] <= 0;BufferDataOutRe[127:120] <= 0; BufferDataOutIm[127:120] <= 0;BufferDataSymbol[127:120] <= 0;endBufferOutEnable[14:0] <= BufferOutEnable[15:1];BufferDataOutRe[119:0] <= BufferDataOutRe[127:8];BufferDataOutIm[119:0] <= BufferDataOutIm[127:8];DataOutEnable <= BufferOutEnable[0];DataOutRe <= BufferDataOutRe[7:0];DataOutIm <= BufferDataOutIm[7:0];BufferDataSymbol[119:0] <= BufferDataSymbol[127:8];DataSymbol <= BufferDataSymbol[7:0];endendelsebeginif(Counter2 == 0)   //the length of the input datas is an integral multiple of the length of symbol (64)  begin					BufferOutEnable <= 0;BufferDataOutRe <= 0;BufferDataOutIm <= 0;BufferDataSymbol <= 0;DataOutEnable <= 0;DataOutRe <= 0;DataOutIm <= 0;DataSymbol <= 0;endelse     //if not, keeping output until it satifies (the values of counter2 is 79)beginif(Counter2 == 79)    Counter2 <= 0;elseCounter2 <= Counter2 + 1;BufferDataSymbol[127:120] <= TempSymbol+1;BufferDataSymbol[119:0] <= BufferDataSymbol[127:8];DataSymbol <= BufferDataSymbol[7:0];BufferOutEnable[14:0] <= BufferOutEnable[15:1];BufferDataOutRe[119:0] <= BufferDataOutRe[127:8];BufferDataOutIm[119:0] <= BufferDataOutIm[127:8];DataOutEnable <= BufferOutEnable[0];DataOutRe <= BufferDataOutRe[7:0];DataOutIm <= BufferDataOutIm[7:0];BufferOutEnable[15] <= 1;BufferDataOutRe[127:120] <= DataInRe; BufferDataOutIm[127:120] <= DataInIm;end										Counter1 <= 0;endend

        前面确定短序列的结束位置,这部分一个是要控制延时多少输出,一个是做好计数就可以了 


总结

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

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

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词