頻譜搬移的過程如下,輸入信號Data_in,與NCO產生的單音信號進行復乘得到Data_out;
將Data_in與Data_out的頻譜放到一起如下,可以看到頻譜搬移的過程。
頻譜搬移在計算上就是復乘:(i+q*j)*(cos+sin*j)=(cos*i-sin*q)+(sin*i+cos*q)*j,用xilinx片子實現的話我們還是選擇DSP48,其結構如下:
其中用到了dsp的級聯,可以參考之前dsp48e1詳細講解的文章:FPGA的底層資源之DSP48E1和Xilinx DSP48E1仿真。這里不再詳細描述。
代碼實現如下:
首先的端口聲明:
// ============================================================
// File Name: cm_mix
// VERSION : V1.0
// DATA : 2022/11/6
// Author : FPGA干貨分享
// ============================================================
// 功能:數字混頻器 (i+q*j)*(cos+sin*j) = (cos*i - sin*q) + (sin*i + cos*q)*j
// delay
// ============================================================
`timescale 1ns/1ps
module cm_mix
parameter C_DATA_WITH = 16 ) //
(
input wire I_sys_clk , // 輸入時鐘
input wire I_rst_in , // 輸入復位 高有效
input wire [6:0] I_phase , // 初始相位
input wire [7:0] I_freq , // 頻率,步進,1代表1M
input wire [C_DATA_WITH-1:0] I_data_in_i , // 輸入數據 實部I
input wire [C_DATA_WITH-1:0] I_data_in_q , // 輸入除數 虛部Q
output reg [C_DATA_WITH-1:0] O_data_out_i , // 輸出數據 實部I
output reg [C_DATA_WITH-1:0] O_data_out_q );// 輸出除數 虛部Q
// ============================================================
// 內部參數
// ============================================================
// ============================================================
// 變量
// ============================================================
wire [10:0] S_sin_out ;
wire [10:0] S_cos_out ;
reg [C_DATA_WITH-1:0] S_data_in_q ;
reg [10:0] S_sin_out_d ;
reg [10:0] S_cos_out_d ;
wire [47:0] S_pcout_cos_i ;
wire [47:0] S_dsp_out_i ;
wire [47:0] S_pcout_sin_i ;
wire [47:0] S_dsp_out_q ;
然后調用上一篇文章中的NCO模塊FPGA數字信號處理之verilog實現NCO(代碼及仿真):
cm_nco_100 cm_nco_100 (
.I_sys_clk (I_sys_clk ) , /// 工作時鐘 100M
.I_rst_n (!I_rst_in ) , /// 復位信號,用來清相位
.I_phase (I_phase ) , /// 初始相位
.I_freq (I_freq ) , /// 頻率,步進,1代表1M
.O_sin_out (S_sin_out ) , /// 輸出正弦值
.O_cos_out (S_cos_out ) /// 輸出余弦值
);
接著打拍并調用乘法器:
always @(posedge I_sys_clk )
if(I_rst_in)
begin
S_data_in_q <= 'd0 ;
S_sin_out_d <= 'd0 ;
S_cos_out_d <= 'd0 ;
end
else
begin
S_data_in_q <= I_data_in_q ;
S_sin_out_d <= S_sin_out ;
S_cos_out_d <= S_cos_out ;
end
// ============================================================
// (cos*i - sin*q)
// ============================================================
//cos*i
cm_dsp48e1 #(
.C_DATA_WITH_A (C_DATA_WITH ),
.C_DATA_WITH_B (11 ),
.C_DATA_WITH_C (48 ),
.C_DATA_WITH_D (25 )
)
U0_cm_dsp48e1(
.I_CLK (I_sys_clk ) , // clk
.I_RST (I_rst_in ) , // RST
.I_A (I_data_in_i ) , // [29:0]
.I_B (S_cos_out ) , // [17:0]
.I_C (48'd0 ) , // [47:0]
.I_D (25'd0 ) , // [24:0]
.I_PCIN (48'd0 ) , // [47:0] 只能直連PCOUT
.I_ALUMODE (4'd0 ) , // [3:0]
.I_INMODE (5'b00101 ) , // [4:0]
.I_OPMODE (7'b0000101 ) , // [6:0]
.O_P ( ) , // [47:0]
.O_PCOUT (S_pcout_cos_i ) // [47:0] 只能直連PCIN
);
//Pcin - sin*q
cm_dsp48e1 #(
.C_DATA_WITH_A (C_DATA_WITH ),
.C_DATA_WITH_B (11 ),
.C_DATA_WITH_C (48 ),
.C_DATA_WITH_D (25 )
)
U1_cm_dsp48e1(
.I_CLK (I_sys_clk ) , // clk
.I_RST (I_rst_in ) , // RST
.I_A (S_data_in_q ) , // [29:0]
.I_B (S_sin_out_d ) , // [17:0]
.I_C (48'd0 ) , // [47:0]
.I_D (25'd0 ) , // [24:0]
.I_PCIN (S_pcout_cos_i ) , // [47:0] 只能直連PCOUT
.I_ALUMODE (4'b0011 ) , // [3:0]
.I_INMODE (5'b00101 ) , // [4:0]
.I_OPMODE (7'b0010101 ) , // [6:0]
.O_P (S_dsp_out_i ) , // [47:0]
.O_PCOUT ( ) // [47:0] 只能直連PCIN
);
// ============================================================
// (sin*i + cos*q)
// ============================================================
//sin*i
cm_dsp48e1 #(
.C_DATA_WITH_A (C_DATA_WITH ),
.C_DATA_WITH_B (11 ),
.C_DATA_WITH_C (48 ),
.C_DATA_WITH_D (25 )
)
U2_cm_dsp48e1(
.I_CLK (I_sys_clk ) , // clk
.I_RST (I_rst_in ) , // RST
.I_A (I_data_in_i ) , // [29:0]
.I_B (S_sin_out ) , // [17:0]
.I_C (48'd0 ) , // [47:0]
.I_D (25'd0 ) , // [24:0]
.I_PCIN (48'd0 ) , // [47:0] 只能直連PCOUT
.I_ALUMODE (4'd0 ) , // [3:0]
.I_INMODE (5'b00101 ) , // [4:0]
.I_OPMODE (7'b0000101 ) , // [6:0]
.O_P ( ) , // [47:0]
.O_PCOUT (S_pcout_sin_i ) // [47:0] 只能直連PCIN
);
//Pcin + cos*q
cm_dsp48e1 #(
.C_DATA_WITH_A (C_DATA_WITH ),
.C_DATA_WITH_B (11 ),
.C_DATA_WITH_C (48 ),
.C_DATA_WITH_D (25 )
)
U3_cm_dsp48e1(
.I_CLK (I_sys_clk ) , // clk
.I_RST (I_rst_in ) , // RST
.I_A (S_data_in_q ) , // [29:0]
.I_B (S_cos_out_d ) , // [17:0]
.I_C (48'd0 ) , // [47:0]
.I_D (25'd0 ) , // [24:0]
.I_PCIN (S_pcout_sin_i ) , // [47:0] 只能直連PCOUT
.I_ALUMODE (4'b0000 ) , // [3:0]
.I_INMODE (5'b00101 ) , // [4:0]
.I_OPMODE (7'b0010101 ) , // [6:0]
.O_P (S_dsp_out_q ) , // [47:0]
.O_PCOUT ( ) // [47:0] 只能直連PCIN
);
最后四舍五入后輸出:
/// 四合五入輸出
always @(posedge I_sys_clk )
if(I_rst_in)
begin
O_data_out_i <= 'd0;
O_data_out_q <= 'd0;
end
else
begin
O_data_out_i <= S_dsp_out_i[10+:C_DATA_WITH] + S_dsp_out_i[9];
O_data_out_q <= S_dsp_out_q[10+:C_DATA_WITH] + S_dsp_out_q[9];
end
endmodule
對代碼的詳細講解參考B站視頻:
【FPGA數字信號處理之verilog實現數字混頻器】 https://www.bilibili.com/video/BV1hg411B7Rb/?share_source=copy_web&vd_source=9736f43bc2eebc284f4fbbe5805247a7
審核編輯 :李倩
-
FPGA
+關注
關注
1629文章
21748瀏覽量
603853 -
數字信號處理
+關注
關注
15文章
560瀏覽量
45878 -
混頻器
+關注
關注
10文章
680瀏覽量
45707
原文標題:FPGA數字信號處理之verilog實現混頻器
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論