FPGA实现信号的正交调制与解调
有具体实验需求可私聊定制
实验目的
- 了解正交调制解调的原理和实现方法
- 学会 I P IP IP核的使用
- 学会利用 m o d e s i m modesim modesim进行仿真
实验要求
- 相关参数:
(1)直线阵通道数: 96 96 96
(2)信号频率: 10 k H z 10kHz 10kHz
(3)采样率: 400 k H z 400kHz 400kHz
(4)低通滤波器阶数: 64 64 64
(5)低通滤波器截止频率: 20 k H z 20kHz 20kHz - 技术要求:
(1)结合上述参数完成正交变换(混频+低通滤波),其中混频通过 V e r i l o g Verilog Verilog逻辑代码实现,低通滤波通过 I P IP IP核实现
(2)低通滤波器参数结合上述参数采用 M a t l a b Matlab Matlab计算
(3)通道信号可以采用正弦波,结合上述参数及参考 M a t l a b Matlab Matlab程序仿真生成
(4)仿真生成的通道数据使用方式参考测试平台参考程序 - 提交成果:
(1) M o d e l s i m Modelsim Modelsim仿真结果
(2) M a t l a b Matlab Matlab计算结果与 M o d e l s i m Modelsim Modelsim仿真结果的对比结果
实验环境
- Q u a r t u s 18.0 Quartus18.0 Quartus18.0
- M o d e l S i m − I n t e l F P G A S t a r t e r E d i t i o n 10.5 b ( Q u a r t u s P r i m e 18.0 ) ModelSim - Intel FPGA Starter Edition 10.5b (Quartus Prime 18.0) ModelSim−IntelFPGAStarterEdition10.5b(QuartusPrime18.0)
实验原理
为了提高频谱利用率,通信系统通常采用正交调制解调,如下图所示分别为正交调制解调的原理的实现方法:
在调制端,分别输入信号的实部和虚部,实部和虚部信号分别与 c o s ω 0 t cos\omega_{0}t cosω0t和 − s i n ω 0 t -sin\omega_{0}t −sinω0t相乘,再将两路信号相加后可以得到调制信号。
在解调端,将经过信号的调制信号分为两路,在分别与两路互相正交的信号 c o s ω 0 t cos\omega_{0}t cosω0t和 − s i n ω 0 t -sin\omega_{0}t −sinω0t相乘,再分别经过低通滤波器,可以得出解调信号。
实验结果与分析
本次试验中并非严格按照正交调制解调的的原理进行实验,试验中的两路基带信号为 96 96 96路 C W CW CW信号,而非信号实部和虚部,载波频率为 400 k H z 400kHz 400kHz, C W CW CW信号频率为 10 k H z 10kHz 10kHz,系统时钟频率为 100 M H z 100MHz 100MHz
整个工程主要分为四个部分:顶层模块,混频模块, F I R FIR FIR滤波器模块,锁相环模块
顶层模块
对各模块进行例化
混频模块
输入信号处理
assign signal = data-14'd8192;
在实际情况中,处理数据应为 A D AD AD模块量化后的读取信号,所得到的数据为整数,因此需要先对输入数据进行第一步处理,根据 A D AD AD量化精度将信号恢复为有符号数值,本次实验输入数据幅值为 1 − 16384 1-16384 1−16384,即 14 b i t 14bit 14bit数据,因此需对原始数据减去 8192 8192 8192。
调制
两路信号分别与正弦和余弦载波相乘,然后相加得到调制信号
signal_1 <= signal*carrier_cos; // 中间变量,用来debug和调整时序
signal_2 <= signal*carrier_sin;
signal_output <= signal*carrier_cos+signal*carrier_sin;
载波控制模块
载波幅值
载波频率为 100 k H z 100kHz 100kHz,采样频率为 400 k H z 400kHz 400kHz,因此可认为在载波的一个周期内,只采集到四个数据,可以将四个数据特殊化为 1 , 0 , − 1 , 0 1, 0, -1, 0 1,0,−1,0,并采用一个 400 k H z 400kHz 400kHz时钟作为触发时钟,每到时钟上升沿触发,载波数据改变到下一个点,调制解调时需要同步载波,因此将载波生成放入另一模块中
always @(posedge clk_400K) begin
if (!rst_n) begin
cnt_4_sin <= 3'd0;
cnt_4_cos <= 3'd0;
end
else begin
cnt_4_cos <= cnt_4_cos+1'b1;
cnt_4_sin <= cnt_4_sin+1'b1;
if(cnt_4_cos==3)begin
cnt_4_cos <= 3'd0;
end
if(cnt_4_sin==3)begin
cnt_4_sin <= 3'd0;
end
end
end
状态机
根据计数器数值确定载波下一个的状态
always @(posedge clk) begin
if(!rst_n)begin
carrier_cos <= 2'd0;
carrier_sin <= 2'd0;
end
else begin
case(cnt_4_cos)
3'd0: carrier_cos <= 2'b1;
3'd1: carrier_cos <= 2'b0;
3'd2: carrier_cos <= -2'b1;
3'd3: carrier_cos <= 2'b0;
endcase
case(cnt_4_sin)
3'd0: carrier_sin <= 2'b0;
3'd1: carrier_sin <= 2'b1;
3'd2: carrier_sin <= 2'b0;
3'd3: carrier_sin <= -2'b1;
endcase
end
end
下图所示三个信号分别为读入信号和分别与两路正交信号相乘得出的信号
解调模块
解调应分为两部分:与同相载波相乘;过低通滤波器
解调模块中只负责将调制信号分别与两路同相正交载波相乘,本次实验在同一工程下实现调制解调,不需要考虑载波相位问题,实际工程中需要加入valid
信号控制保证载波同相问题
signal_r <= signal_input*carrier_cos;
signal_i <= signal_input*carrier_sin;
滤波器模块
实验采用 96 96 96路滤波器,读入的前 96 96 96个数据分别划为 96 96 96个滤波器的第一个数据,读入的下一组 96 96 96个数据分别划为 96 96 96个滤波器的第二个数据,每个滤波器共需读入 400 400 400个数据
滤波器参数通过 M A T L A B MATLAB MATLAB的滤波器设计工具生成
滤波器
例化信号
fir fir_1(
.clk (sys_clk ),
.reset_n (sys_rst_n ),
.ast_sink_data (signal1 ),
.ast_sink_valid (data_valid ),
.ast_sink_error (2'b00 ),
.ast_sink_sop (ast_sink_sop ),
.ast_sink_eop (ast_sink_eop ),
.ast_source_data (ast_source_data_1 ),
.ast_source_valid (ast_source_valid_1 ),
.ast_source_error (ast_source_error_1 ),
.ast_source_sop ( ),
.ast_source_eop ( ),
.ast_source_channel ( )
F I R FIR FIR I P IP IP核需要输入和输出信号线如上
ast_sink_valid
为输入数据有效信号,滤波器采样频率为
400
k
H
z
400kHz
400kHz,因此每
250
250
250个时钟周期进行一次采样,因此在这
250
250
250个时钟周期中,前
96
96
96个时钟周期为多通道滤波器的连续采样时刻,此时valid
信号拉高,当一组数据采集完成后,信号拉低,工程中用到两个valid
信号,fir_valid
落后于data_valid
一个时钟周期,因此fir_valid
信号在仿真文件中定义如下:
// wire fir_valid;
assign fir_valid = (((cnt_valid >= 2)&&(cnt_valid <= 97)) ?1 : 0);
ast_sink_sop
和ast_sink_eop
分别为输入数据起始和结束标记脉冲,通过对valid
信号上升沿和下降沿的捕获实现 ,基本思路为对valid
信号延时并取反相与实现,具体实现方法如下:
// 捕获valid信号上升沿和下降沿
reg en_d0, en_d1;
//捕获valid上升沿,得到一个时钟周期的脉冲信号
assign sink_sop = (~en_d1) & en_d0;
//捕获valid下降沿,得到一个时钟周期的脉冲信号
assign sink_eop = (~en_d0) & en_d1;
//对valid信号延迟两个时钟周期
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
en_d0 <= 1'b0;
en_d1 <= 1'b0;
end
else begin
en_d0 <= fir_valid;
en_d1 <= en_d0;
end
end
锁相环模块
试验中需要一个
400
k
H
z
400kHz
400kHz的时钟控制载波信号取值,因此用到了锁相环
锁相环的使用是存在延时的,而非reset
信号拉高后就会输出
400
k
H
z
400kHz
400kHz时钟,如图所示:
因此在定义data_valid
信号时,需要延时一定时间至度过锁相环延时周期,才能保证正常运行
initial begin
# 60000; // 锁相环有延时
forever begin
@(posedge sys_clk);
begin
if(cnt_valid == 250)
仿真文件
系统时钟
每隔 5000 p s 5000ps 5000ps翻转一次
// 100MHz sys_clk generating
localparam TCLK_HALF = 5_000;
initial begin
sys_clk = 1'b0 ;
forever begin
# TCLK_HALF sys_clk = ~sys_clk ;
end
end
定义复位和停止时刻
总时间尺度约为 2500000 ∗ 400 + 60000 2500000*400+60000 2500000∗400+60000
initial begin
sys_rst_n = 1'b0 ;
# 30 ;
sys_rst_n = 1'b1 ;
# 1_000_060_000
$finish ;
end
读取数据
readmemh
可读取十六进制数,将读取数据存放到 16 ∗ 38400 16*38400 16∗38400为寄存器中共后续使用
reg [15:0] stimulus [0:38399] ;
integer i ;
initial begin
$readmemh("data_cw_38400.txt", stimulus) ;
i = 1 ;
data = stimulus[0] ;
forever begin
@(negedge sys_clk) ;
if(data_valid && i<38400)begin
data = stimulus[i] ;
i=i+1;
end
end
end
设定读取使能信号,确定何时读取何时停止
// wire data_valid;
assign data_valid = (((cnt_valid >= 1)&&(cnt_valid <= 96)) ?1 : 0);
存放数据
保存数据供后续比对
integer fir1_file, fir2_file;
initial fir1_file = $fopen("data_out_1.txt");
initial fir2_file = $fopen("data_out_2.txt");
always @(posedge sys_clk) begin
if (!sys_rst_n) begin
// reset
end
else if (ast_source_valid_1) begin
$fwrite(fir1_file,"%f\n",$signed(ast_source_data_1));// %f 有符号数保存,\n:换行符
$fwrite(fir2_file,"%f\n",$signed(ast_source_data_2));// %f 有符号数保存,\n:换行符
end
end
数据对比
为验证 V e r i l o g Verilog Verilog程序是否正确,将通过 M o d e l s i m Modelsim Modelsim仿真得出数据与通过 M a t l a b Matlab Matlab仿真得出数据进行对比
原始数据
解调波形
根据观察发现,通过 V e r i l o g Verilog Verilog得出数据与对应位置的通过 M a t l a b Matlab Matlab得出的数据幅值相差三倍,根据分析可能是由于输出数据位宽定义不一致导致的,因此先对通过两种方法得出的数据进行归一化,归一化范围为 2 − 2 20 2-2^{20} 2−220
最后得出误差约为万分之七左右:
实验总结
以前写 V e r i l o g Verilog Verilog都很简单,都是直接写在板子上跑,对于仿真文件了解也很少,时序也都乱写,这次写完这个工程对于仿真文件和时序也算有了一点新的理解
附录
V e r i l o g Verilog Verilog部分
顶层模块
//===============================
// 正交调制解调仿真实验
// 顶层模块
// 作者:何一飞
// 时间:2022-6-28
//===============================
module FIR_top(
input sys_clk,
input sys_rst_n,
input data_valid,
input fir_valid,
input ast_sink_sop,
input ast_sink_eop,
input [15: 0] data,
output locked,
output clk_400K,
output wire signed [15: 0] signal1,
output wire signed [15: 0] signal2,
output wire signed [15: 0] signal_output,
output wire signed [15: 0] signal_r,
output wire signed [15: 0] signal_i,
output wire ast_source_valid_1,
output wire signed [ 1: 0] ast_source_error_1,
output wire signed [ 1: 0] ast_source_error_2,
output wire signed [18: 0] ast_source_data_1,
output wire signed [18: 0] ast_source_data_2
);
wire signed [ 1: 0] carrier_cos;
wire signed [ 1: 0] carrier_sin;
mixed umixed(
.clk (sys_clk ),
.clk_400K (clk_400K ),
.rst_n (sys_rst_n ),
.data (data ),
.data_valid (data_valid ),
.carrier_cos (carrier_cos ),
.carrier_sin (carrier_sin ),
.signal_1 (signal1 ),
.signal_2 (signal2 ),
.signal_output (signal_output )
);
decode udecode(
.clk (sys_clk ),
.clk_400K (clk_400K ),
.rst_n (sys_rst_n ),
.signal_r (signal_r ),
.signal_i (signal_i ),
.carrier_cos (carrier_cos ),
.carrier_sin (carrier_sin ),
.signal_input (signal_output )
);
carrier ucarrier(
.clk (sys_clk ),
.clk_400K (clk_400K ),
.rst_n (sys_rst_n ),
.carrier_cos (carrier_cos ),
.carrier_sin (carrier_sin )
);
PLL uPLL(
.inclk0 (sys_clk ),
.areset (~sys_rst_n ),
.c0 (clk_400K ),
.locked (locked )
);
fir fir_1(
.clk (sys_clk ),
.reset_n (sys_rst_n ),
.ast_sink_data (signal_r ),
.ast_sink_valid (fir_valid ),
.ast_sink_error (2'b00 ),
.ast_sink_sop (ast_sink_sop ),
.ast_sink_eop (ast_sink_eop ),
.ast_source_data (ast_source_data_1 ),
.ast_source_valid (ast_source_valid_1 ),
.ast_source_error (ast_source_error_1 ),
.ast_source_sop ( ),
.ast_source_eop ( ),
.ast_source_channel ( )
);
fir fir_2(
.clk (sys_clk ),
.reset_n (sys_rst_n ),
.ast_sink_data (signal_i ),
.ast_sink_valid (fir_valid ),
.ast_sink_error (2'b00 ),
.ast_sink_sop (ast_sink_sop ),
.ast_sink_eop (ast_sink_eop ),
.ast_source_data (ast_source_data_2 ),
.ast_source_valid ( ),
.ast_source_error (ast_source_error_2 ),
.ast_source_sop ( ),
.ast_source_eop ( ),
.ast_source_channel ( )
);
endmodule
混频模块
//===============================
// 正交调制解调仿真实验
// 混频模块
// 作者:何一飞
// 时间:2022-6-28
// 时钟频率100MHz
// 正交载波频率400kHz
//===============================
module mixed(
input clk,
input clk_400K,
input rst_n,
input signed [15: 0] data,
input data_valid,
input signed [ 1: 0] carrier_cos, carrier_sin,
output reg signed [15: 0] signal_1,
output reg signed [15: 0] signal_2,
output reg signed [15: 0] signal_output
);
wire signed [15: 0] signal;
initial signal_1 = 0;
initial signal_2 = 0;
assign signal = (data-14'd8192);
always @(posedge clk) begin
if (!rst_n) begin
signal_1 <= 16'd0;
signal_2 <= 16'd0;
end
else begin
signal_1 <= signal*carrier_cos;
signal_2 <= signal*carrier_sin;
signal_output <= signal*carrier_cos+signal*carrier_sin;
end
end
endmodule
载波控制模块
//===============================
// 正交调制解调仿真实验
// 载波控制模块
// 作者:何一飞
// 时间:2022-6-28
// 四个状态,特殊化为1,0,-1,0
// 400KHz时钟控制
//===============================
module carrier(
input clk,
input clk_400K,
input rst_n,
output reg signed [ 1: 0] carrier_cos, carrier_sin
);
reg [ 2: 0] cnt_4_cos, cnt_4_sin;
initial cnt_4_cos = 0;
initial cnt_4_sin = 0;
initial carrier_cos = 0;
initial carrier_sin = 0;
always @(posedge clk_400K) begin
if (!rst_n) begin
cnt_4_sin <= 3'd0;
cnt_4_cos <= 3'd0;
end
else begin
cnt_4_cos <= cnt_4_cos+1'b1;
cnt_4_sin <= cnt_4_sin+1'b1;
if(cnt_4_cos==3)begin
cnt_4_cos <= 3'd0;
end
if(cnt_4_sin==3)begin
cnt_4_sin <= 3'd0;
end
end
end
always @(posedge clk) begin
if(!rst_n)begin
carrier_cos <= 2'd0;
carrier_sin <= 2'd0;
end
else begin
case(cnt_4_cos)
3'd0: carrier_cos <= 2'b1;
3'd1: carrier_cos <= 2'b0;
3'd2: carrier_cos <= -2'b1;
3'd3: carrier_cos <= 2'b0;
endcase
case(cnt_4_sin)
3'd0: carrier_sin <= 2'b0;
3'd1: carrier_sin <= 2'b1;
3'd2: carrier_sin <= 2'b0;
3'd3: carrier_sin <= -2'b1;
endcase
end
end
endmodule
解调模块
//===============================
// 正交调制解调仿真实验
// 解调模块
// 作者:何一飞
// 时间:2022-6-28
// 调制信号分别与两路同相载波相乘
//===============================
module decode(
input clk,
input clk_400K,
input rst_n,
input signed [ 1: 0] carrier_cos, carrier_sin,
input signed [15: 0] signal_input,
output reg signed [15: 0] signal_r,
output reg signed [15: 0] signal_i
);
always @(posedge clk) begin
if (!rst_n) begin
signal_r <= 16'd0;
signal_i <= 16'd0;
end
else begin
signal_r <= signal_input*carrier_cos;
signal_i <= signal_input*carrier_sin;
end
end
endmodule
T e s t b e n c h Testbench Testbench
//===============================
// 正交调制解调仿真实验
// 仿真文件
// 作者:何一飞
// 时间:2022-6-29
//===============================
`timescale 1 ps/ 1 ps
module FIR_top_vlg_tst();
reg eachvec;
reg [15:0] data;
reg sys_rst_n;
reg sys_clk;
// wires
wire data_valid;
wire fir_valid;
wire clk_400K;
wire sink_sop;
wire sink_eop;
wire locked;
wire ast_source_valid_1;
wire [ 1: 0] ast_source_error_1;
wire [ 1: 0] ast_source_error_2;
wire [15: 0] signal1;
wire [15: 0] signal2;
wire [18: 0] ast_source_data_1;
wire [18: 0] ast_source_data_2;
wire signed [15: 0] signal_output;
wire signed [15: 0] signal_r;
wire signed [15: 0] signal_i;
// assign statements (if any)
FIR_top i1 (
// port map - connection between master ports and signals/registers
.signal1 (signal1 ),
.signal2 (signal2 ),
.signal_r (signal_r ),
.signal_i (signal_i ),
.signal_output (signal_output ),
.ast_sink_sop (sink_sop ),
.ast_sink_eop (sink_eop ),
.clk_400K (clk_400K ),
.locked (locked ),
.ast_source_valid_1 (ast_source_valid_1 ),
.ast_source_data_1 (ast_source_data_1 ),
.ast_source_data_2 (ast_source_data_2 ),
.data (data ),
.data_valid (data_valid ),
.fir_valid (fir_valid ),
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n )
);
//=====================================
// 100MHz sys_clk generating
localparam TCLK_HALF = 5_000;
initial begin
sys_clk = 1'b0 ;
forever begin
# TCLK_HALF sys_clk = ~sys_clk ;
end
end
//=====================================
// reset and finish
initial begin
sys_rst_n = 1'b0 ;
# 30 ;
sys_rst_n = 1'b1 ;
//# (TCLK_HALF * 2 * 8 * SIMU_CYCLE) ;
//$finish ;
# 1_000_060_000
$finish ;
end
//=======================================
//================read data==============
reg [15:0] stimulus [0:38399] ;
integer i ;
initial begin
$readmemh("data_cw_38400.txt", stimulus) ;
i = 1 ;
data = stimulus[0] ;
forever begin
@(negedge sys_clk) ;
if(data_valid && i<38400)begin
data = stimulus[i] ;
i=i+1;
end
end // forever begin
end // initial begin
//=====================================
// valid
reg [ 7: 0]cnt_valid;
initial cnt_valid <= 8'd0;
initial begin
# 60000; // PLL Delay
forever begin
@(posedge sys_clk);
begin
if(cnt_valid == 250)
cnt_valid <= 8'd1;
else
cnt_valid <= cnt_valid + 1;
end
end
end
// wire data_valid && fir_valid;
assign data_valid = (((cnt_valid >= 1)&&(cnt_valid <= 96)) ?1 : 0);
assign fir_valid = (((cnt_valid >= 2)&&(cnt_valid <= 97)) ?1 : 0);
//=====================================
// 捕获valid信号上升沿和下降沿
reg en_d0, en_d1;
//reg en_d2, en_d3;
// 捕获valid上升沿,得到一个时钟周期的脉冲信号
assign sink_sop = (~en_d1) & en_d0;
// 捕获valid下降沿,得到一个时钟周期的脉冲信号
assign sink_eop = (~en_d0) & en_d1;
// 对valid信号延迟两个时钟周期
always @(posedge sys_clk) begin
if (!sys_rst_n) begin
en_d0 <= 1'b0;
en_d1 <= 1'b0;
end
else begin
en_d0 <= fir_valid;
en_d1 <= en_d0;
end
end
//===========================================
// write wave data to fir1res.txt, fir2res.txt
integer fir1_file, fir2_file;
initial fir1_file = $fopen("data_out_1.txt");
initial fir2_file = $fopen("data_out_2.txt");
always @(posedge sys_clk) begin
if (!sys_rst_n) begin
// reset
end
else if (ast_source_valid_1) begin
$fwrite(fir1_file,"%f\n",$signed(ast_source_data_1));// %f 十进制保存,\n:换行符
$fwrite(fir2_file,"%f\n",$signed(ast_source_data_2));// %f 十进制保存,\n:换行符
end
end
endmodule
M a t l a b Matlab Matlab部分文章来源:https://www.toymoban.com/news/detail-414424.html
生成原始信号数据
clear all; close all; clc
channel = 96;
f = 100e3
fs = 400e3
T_ca = 1/fs
t = (0:fs-1)*T_ca
t = t(1:400)
t2 = (0:96*fs-1)*T_ca/96
carrier1 = sin(2*pi*f*t);
carrier1 = carrier1(1: 400)
carrier2 = cos(2*pi*f*t);
carrier2 = carrier2(1: 400)
%% FIR
B=20000;
filter_order = 64;
filter_f=fir1(filter_order,B/(fs/2),'low');
%% CW
T = 1e-3;
fs = 400e3;
f0 = 10e3;%50e3;
Ts = 1/fs;
N = T/Ts;
fai = rand(1,channel)*pi;
for kk = 1:channel
s(:,kk) = round((16384/2-1)*(cos(2*pi*f0*t+fai(kk))+0));
end
plot(t,s)
title('原始波形')
%% Decode
% carrier2 = repmat(carrier2, channel, 1);
result1 = s'.*repmat(carrier1, channel, 1).^2;
result2 = s'.*repmat(carrier2, channel, 1).^2;
% out1 = LPF(result1);
out1 = filter(LPF, result1');
out2 = filter(LPF, result2');
subplot(211)
plot(t, out1); axis([0 100*T_ca -8000 8000])
subplot(212)
plot(t, out2); axis([0 100*T_ca -8000 8000])
new = (reshape((s+8191)', 1, []))';
fir_out1 = (reshape(out1', 1, []))';
fir_out2 = (reshape(out2', 1, []))';
fid = fopen('data_cw_38400.txt', 'wt') ; %写数据文件
fprintf(fid, '%x\n', new) ;
fclose(fid) ;
fid_2 = fopen('out1_38400.txt', 'wt') ; %写数据文件
fprintf(fid_2, '%f\n', fir_out1) ;
fclose(fid_2) ;
fid_3 = fopen('out2_38400.txt', 'wt') ; %写数据文件
fprintf(fid_3, '%f\n', fir_out2) ;
fclose(fid_3) ;
save fir_data.txt -ascii new
save fir_out1.txt -ascii fir_out1
save fir_out2.txt -ascii fir_out2
function Hd = LPF
Fs = 400; % Sampling Frequency
N = 64; % Order
Fpass = 20; % Passband Frequency
Fstop = 25; % Stopband Frequency
Wpass = 1; % Passband Weight
Wstop = 1; % Stopband Weight
dens = 20; % Density Factor
% Calculate the coefficients using the FIRPM function.
b = firpm(N, [0 Fpass Fstop Fs/2]/(Fs/2), [1 1 0 0], [Wpass Wstop], ...
{dens});
Hd = dfilt.dffir(b);
end
数据验证
square_ = [38400 1]
fid_F1 = fopen('data_out_1.txt','r');
[f_F1, count_F1]=fscanf(fid_F1, '%f %f', square_);
fclose(fid_F1);
fid_F2 = fopen('data_out_2.txt','r');
[f_F2, count_F2]=fscanf(fid_F2, '%f %f', square_);
fclose(fid_F1);
fid_M1 = fopen('out1_38400.txt','r');
[f_M1, count_M1]=fscanf(fid_M1, '%f %f', square_);
fclose(fid_F1);
fid_M2 = fopen('out2_38400.txt','r');
[f_M2, count_M2]=fscanf(fid_M2, '%f %f', square_);
fclose(fid_F1);
d_max = 2^20;
d_min = 2;
data_F1 = mapminmax(f_F1', d_min, d_max)
data_F2 = mapminmax(f_F2', d_min, d_max)
data_M1 = mapminmax(f_M1', d_min, d_max)
data_M2 = mapminmax(f_M2', d_min, d_max)
rate_1 = error(data_F1, data_M2)
rate_2 = error(data_F2, data_M1)
function rate = error(a, b)
rate = mean(abs(a-b)./abs(b));
end
完整工程链接在这里:https://download.csdn.net/download/m0_51077616/85826926文章来源地址https://www.toymoban.com/news/detail-414424.html
到了这里,关于Verilog正交调制解调的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!