1. 程式人生 > >4.4.3 符號同步(二)

4.4.3 符號同步(二)

4.4.3 符號同步(二)  

基本上 《XILINX FPGA的OFDM通訊系統基帶設計》一書已經帶有各部分的程式碼,我做的工作就是將程式碼整合到一起,並按照模擬修改,讓其能正常工作。本文將對實現中的重點部分做解釋,並指出需要修改的地方。

 

time_sync 頂層

 

`timescale 1ns / 10ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 11:41:18 10/30/2014
// Design Name: OFDM_rx_sync_top
// Module Name: Time_Syncronization
// Project Name: OFDM base on Xilinx KC705


// Description: OFDM 接收部分同步模組中【符號同步】子模組,用於接收OFDM符號的同步。
// 找到OFDM資料的起始點,然後除去CP。
// -------------------------------------------------------------
// 輸入資料:補碼格式 8位位寬 1位符號位 1位整數位 6位小數位
// 輸出資料:補碼格式 8位位寬 1位符號位 1位整數位 6位小數位
// -------------------------------------------------------------
// Revision: 1.0
// Copyright: 《基於xlinx FPGA的OFDM通訊系統基帶設計》

//////////////////////////////////////////////////////////////////////////////////
module Time_Syncronization(Clk, Rst_n, DataInEnable, DataInRe, DataInIm,
DataOutEnable, DataOutRe, DataOutIm, DataSymbol);
input Clk;
input Rst_n;
input DataInEnable;
input [7:0] DataInRe;
input [7:0] DataInIm;
output DataOutEnable;
output [7:0] DataOutRe;
output [7:0] DataOutIm;
output [7:0] DataSymbol; //the symbol counter

wire QuantizationEnable;
//the quantization results
wire [15:0] Quantization_Result_Real;
wire [15:0] Quantization_Result_Imag;
// Quantization Module 量化,為了簡化計算,節省乘法器
Quantization Quantization ( .Clk(Clk),
.Rst_n(Rst_n),
.inEn(DataInEnable),
.bitInR(DataInRe),
.bitInI(DataInIm),
.QuantizationEnable(QuantizationEnable),
.Quantization_Result_Real(Quantization_Result_Real),
.Quantization_Result_Imag(Quantization_Result_Imag));
//the endness of the STS
wire PeakFinded;
// Mathc filter Module 匹配濾波,找到各個短訓符號的結束點
Match_Filtering MatchFiltering ( .Clk(Clk),
.Rst_n(Rst_n),
.QuanEnable(QuantizationEnable),
.QuanDataRe(Quantization_Result_Real),
.QuanDataIm(Quantization_Result_Imag),
.PeakFinded(PeakFinded));
//Symbol Output Module OFDM 符號輸出
Symbol_Output SymbolOutput ( .Clk(Clk),
.Rst_n(Rst_n),
.PeakFinded(PeakFinded),
.DataInRe(DataInRe),
.DataInIm(DataInIm),
.DataOutEnable(DataOutEnable),
.DataOutRe(DataOutRe),
.DataOutIm(DataOutIm),
.DataSymbol(DataSymbol));
endmodule

 

 


 

Quantization 量化

 

`timescale 1ns / 10ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 13:32:27 10/30/2014
// Design Name: Time_Syncronization
// Module Name: Quantization
// Project Name: OFDM base on Xilinx KC705
// Description: OFDM 符號同步中 【量化】子模組。
// -------------------------------------------------------------
// 1、將接收到的短訓符號的16個取樣是複數型別,量化為{-1,1},
// 以節省複數乘法所需要的較多器件資源。
// 2、大於0的量化為1,小於0的量化為-1。
// 3、為降低高斯白噪聲,在量化前持續累加接收到的短訓取樣。
// -------------------------------------------------------------
// 輸入資料:補碼格式 8位位寬 1位符號位 1位整數位 6位小數位
// -------------------------------------------------------------
// Revision: 1.0
// Copyright: 《基於xlinx FPGA的OFDM通訊系統基帶設計》
//////////////////////////////////////////////////////////////////////////////////
module Quantization(Clk, Rst_n, inEn, bitInR, bitInI, QuantizationEnable,
Quantization_Result_Real, Quantization_Result_Imag);

input Clk;
input Rst_n;
input inEn;
input [7:0] bitInR;
input [7:0] bitInI;
output QuantizationEnable;
output [15:0] Quantization_Result_Real;
output [15:0] Quantization_Result_Imag;
reg QuantizationEnable;
reg [15:0] Quantization_Result_Real;
reg [15:0] Quantization_Result_Imag;
//the enable signal buffer
reg BufferEnable;
//the input datas buffer
reg [7:0] BufferDataR;
reg [7:0] BufferDataI;
//*****************************保證輸入資料同步*****************************//
always @(posedge Clk or negedge Rst_n) begin
if(!Rst_n)begin
BufferEnable <= 0;
BufferDataR <= 0;
BufferDataI <= 0;
end
else begin
if(inEn) begin
BufferEnable <= 1;
BufferDataR <= bitInR;
BufferDataI <= bitInI;
end
else begin
BufferEnable <= 0;
BufferDataR <= 0;
BufferDataI <= 0;
end
end
end
//持續累加用暫存器
reg [191:0] Continual_Accumulation_Real;
reg [191:0] Continual_Accumulation_Imag;
//持續累加有效訊號/
reg AddEnable;
//********************************取得量化結果********************************//
always @ (posedge Clk or negedge Rst_n) begin
if (!Rst_n)
begin
Continual_Accumulation_Real <= 0;
Continual_Accumulation_Imag <= 0;
AddEnable <= 0;
end
else
begin
if(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;
end
else
begin
Continual_Accumulation_Real <= 0;
Continual_Accumulation_Imag <= 0;
AddEnable <= 0;
end
end
end
always @(posedge Clk or negedge Rst_n)
begin
if(!Rst_n)
begin
Quantization_Result_Real <= 0;
Quantization_Result_Imag <= 0;
QuantizationEnable <= 0;
end
else
begin
if(AddEnable)
begin
QuantizationEnable <= 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];
end
else
begin
Quantization_Result_Real <= 0;
Quantization_Result_Imag <= 0;
QuantizationEnable <= 0;
end
end
end
endmodule

 


 

MatchFiltering 匹配濾波

相關累加計算的實現結構框圖:

4.4.3 符號同步(二) - fantasy - 南山悠然望夕陽

相關累加計算模組中: Simple_Correlating模組

將複數的乘法,直接轉化為加減運算,大大的簡化了計算量!

 

`timescale 1ns / 10ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 14:25:50 10/30/2014
// Design Name: Correlating_and_Accumulating
// Module Name: Simple_Correlation
// Project Name: OFDM base on Xilinx KC705
// Description: OFDM 【單個數據相關係數的運算】模組。
// -------------------------------------------------------------
// Example:conjugate{(a + i*b)}= (a - i*b) conj是共軛的意思
// conj{(a+i*b)}*(1+i) = (a+b)+i*(a-b)
// conj{(a+i*b)}*(1-i) = (a-b)+i*(-a-b)
// conj{(a+i*b)}*(-1+i)= (-a+b)+i*(a+b)
// conj{(a+i*b)}*(-1-i)= (-a-b)+i*(-a+b)
// -------------------------------------------------------------
// Revision: 1.0
// Copyright: 《基於xlinx FPGA的OFDM通訊系統基帶設計》
// 參考《中山大學論文》,得將已知STS取共軛之後再與量化結果相乘
//////////////////////////////////////////////////////////////////////////////////
module Simple_Correlation(Clk, Rst_n, inEn, multiplier_Real, multiplier_Imag,
known_Real, known_Imag, output_Real, output_Imag, outputEnable);

input Clk;
input Rst_n;
input inEn;
input multiplier_Real; //移位暫存器實部
input multiplier_Imag; //移位暫存器虛部
input [15:0] known_Real; //本地已知短訓練序列實部,二進位制補碼錶示
input [15:0] known_Imag; //短訓練序列虛部
output [16:0] output_Real; //輸出實部,擴充套件為17位輸出,輸出為二進位制補碼錶示
output [16:0] output_Imag; //輸出虛部
output outputEnable;
reg [16:0] output_Real;
reg [16:0] output_Imag;
reg outputEnable;
//**********************輸入的multiplier等於0表示正數,等於1表示負數**************************//
always @ (posedge Clk or negedge Rst_n)
begin
if (!Rst_n)
begin
output_Real <= 0;
output_Imag <= 0;
outputEnable <= 0;
end
else if (inEn)
begin
outputEnable <= 1;
if(multiplier_Real == 0 && multiplier_Imag == 0)
begin
output_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};
end
else if (multiplier_Real == 0 && multiplier_Imag == 1)
begin
output_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};
end
else if (multiplier_Real == 1 && multiplier_Imag == 0)
begin
output_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};
end
else //(buffer_multiplier_Real==1 && buffer_multiplier_Imag==1)
begin
output_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};
end
end
else
begin
output_Real <= 0;
output_Imag <= 0;
outputEnable <= 0;
end
end

endmodule

 

累加結果的幅值計算模組(Magnitude_Simplified_Computing):

 

`timescale 1ns / 10ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 14:42:15 10/30/2014
// Design Name: Match_Filtering
// Module Name: Magnitude_Simplified_Computing
// Project Name: OFDM base on Xilinx KC705
// Description: OFDM 符號同步中 【相關累加計算】子模組。
// -------------------------------------------------------------
// 計算相關累加後的幅值,用以下一步的峰值判斷。
// 如果直接計算幅值,需要乘法和開方運算,不利於硬體實現。
// 簡化實現:c=a+jb (|C| ≈ |a| + |b|)
// 計算輸入資料的實部和虛部之和,近似其幅值。
// 近似簡化後的|C|比實際值要稍大,因此門限值必須要稍作調整
// -------------------------------------------------------------
// Revision: 1.0
// Copyright: 《基於xlinx FPGA的OFDM通訊系統基帶設計》
//////////////////////////////////////////////////////////////////////////////////
module Magnitude_Simplified_Computing(Clk, Rst_n, DataEnable, DataInRe, DataInIm, AbsoluteEnable, Absolute);
input Clk;
input Rst_n;
input DataEnable;
input [20:0] DataInRe; //輸入實部,位寬21位,二進位制補碼錶示
input [20:0] DataInIm; //輸入虛部
output AbsoluteEnable;
output [21:0] Absolute; //絕對值輸出,經一次加法後,位寬變為22位,絕對值為正數
reg [21:0] Absolute; //輸出結果為22位位寬,運算元首先擴充套件為22位位寬
reg AbsoluteEnable;
reg BufferEnable;
reg [20:0] BufferDataRe;
reg [20:0] BufferDataIm;
//********************輸入增加一級快取,延遲一個時鐘週期************************//
always @ (posedge Clk or negedge Rst_n) begin
if (!Rst_n)
begin
BufferEnable <= 0;
BufferDataRe <= 0;
BufferDataIm <= 0;
end
else
begin //快取的資料為輸入資料的絕對值
if(DataEnable) begin
BufferEnable <= 1;
if(DataInRe[20] == 0) //符號位為0,表示為正數,絕對值即為輸入數
begin
BufferDataRe <= DataInRe;
end
else //符號位為1,表示為負數,絕對值為輸入數取反加1
begin
BufferDataRe <= ~ DataInRe + 1;
end
if (DataInIm[20] == 0) //虛部運算同實部
begin
BufferDataIm <= DataInIm;
end
else
begin
BufferDataIm <= ~ DataInIm + 1;
end
end
else
begin
BufferEnable <= 0;
BufferDataRe <= 0;
BufferDataIm <= 0;
end
end
end
//************************幅值取實部與虛部的絕對值之和******************************//
always @ (posedge Clk or negedge Rst_n) begin
if (!Rst_n)
begin
Absolute <= 0;
AbsoluteEnable <= 0;
end
else
begin
if(BufferEnable)
begin
Absolute <= {BufferDataRe[20],BufferDataRe} + {BufferDataIm[20],BufferDataIm};
AbsoluteEnable <= 1;
end
else
begin
Absolute <= 0;
AbsoluteEnable <= 0;
end
end
end

endmodule

重點在於:簡化實現:c=a+jb   (|C| ≈ |a| + |b|)

 

在Peak_Finding模組中,重點是門限值的選取(模擬可得):

4.4.3 符號同步(二) - fantasy - 南山悠然望夕陽

 

由於分組檢測模組輸出的第一組短訓練符號是不完整的,所以峰值尋找只能連續檢測到9個峰值點,所以STS_end_counter < 9即可。

4.4.3 符號同步(二) - fantasy - 南山悠然望夕陽

 

如果有條件可以用 modelsim 模擬或者VCS,可以看到 模擬波形 ,明顯的9個峰值。

 

 


 

符號輸出

  1. 送入的資料是16個迴圈字首+64個有效資料,除去字首CP。

  2. 後期不使用短訓練符號,所以這裡一併除去。

  3. 長訓符號是32bit的字首+2個64bit的樣值,資料則是16個字首+64個有效資料,所以在處理上,先輸出第一個長訓符號,然後第二個長訓符號和16級的移位暫存器後輸出,以保證,資料之間相隔16個clk的間隙。

  4. 如果接受資料不為OFDM符號長度的整數倍,在其後補零以滿足整數倍條件。

 

 

程式碼的下列部分,是整個符號輸出模組的核心:

 

if(PeakFinded)
begin
if(Counter1 <= 85) //鑑於量化、相關等處理需要延遲10個週期(可以數出來的),故32+64-10 = 86
begin
Counter2 <= 0;
Counter1 <= Counter1 + 1;
if(Counter1 >= 22 && Counter1 <= 85)//LTS的字首長度32,延遲10個週期,故32-10 = 22開始
begin
DataOutEnable <= 1; //將第一個LTS直接輸出
DataOutRe <= DataInRe;
DataOutIm <= DataInIm;
end
else
begin
DataOutEnable <= 0;
DataOutRe <= 0;
DataOutIm <= 0;
end
if(Counter1 == 22)
begin
DataSymbol <= DataSymbol + 1;
TempSymbol <= DataSymbol + 1;
end
end
else
begin//由於第一個LTS後面緊跟著第二個LTS,所以當count2值為0~63時,輸入資料為所需資料;
//當count2值為64~79時,輸入資料為下一個符號的迴圈字首。
if(Counter2 == 79) //count2 64~79時,輸入資料為signal域的迴圈字首
begin
Counter2 <= 0;
TempSymbol <= TempSymbol + 1;
end
else
begin
Counter2 <= Counter2 + 1;
end
if(Counter2 >= 0 && Counter2 <= 63) //輸入資料為第二個LTS
begin
BufferOutEnable[15] <= 1;
BufferDataOutRe[127:120] <= DataInRe;
BufferDataOutIm[127:120] <= DataInIm;
BufferDataSymbol[127:120] <= TempSymbol + 1;
end
else //迴圈字首期間,送入0,也就是每個OFDM符號之間相隔16個0
begin
BufferOutEnable[15] <= 0;
BufferDataOutRe[127:120] <= 0;
BufferDataOutIm[127:120] <= 0;
BufferDataSymbol[127:120] <= 0;
end

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];
BufferDataSymbol[119:0] <= BufferDataSymbol[127:8];
DataSymbol <= BufferDataSymbol[7:0];
end