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];
/
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];
/
Quantization_Result_Real[15] <= Continual_Accumulation_Real[11];
/
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 比對濾波
相關累加計算的實作結構框圖:
相關累加計算子產品中: 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;
//
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子產品中,重點是門限值的選取(仿真可得):
由于分組檢測子產品輸出的第一組短訓練符号是不完整的,是以峰值尋找隻能連續檢測到9個峰值點,是以STS_end_counter < 9即可。
如果有條件可以用 modelsim 仿真或者VCS,可以看到 模拟波形 ,明顯的9個峰值。
符号輸出
- 送入的資料是16個循環字首+64個有效資料,除去字首CP。
- 後期不使用短訓練符号,是以這裡一并除去。
- 長訓符号是32bit的字首+2個64bit的樣值,資料則是16個字首+64個有效資料,是以在處理上,先輸出第一個長訓符号,然後第二個長訓符号和16級的移位寄存器後輸出,以保證,資料之間相隔16個clk的間隙。
- 如果接受資料不為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