FPGA定点数FFT过后转换为浮点数与Matlab计算的FFT结果进行比对

微信公众号获取更多FPGA相关源码:
在这里插入图片描述

1.前言

前面一篇文章讲了,Matlab将调制映射后的数据转化为定点数,放入FPGA中进行处理。那么定点数,在FPGA中进行FFT过后,如何验证其正确性呢?这就需要将FFT的输出数据读取出来,在Matlab中转化为浮点数,然后与Matlab使用FFT处理后的结果进行对比。

FFT

2.FPGA的testbench中如何读取数据文件

在verilog中可以使用系统函数readmemb和 readmemh从文件中读取数据到存储器中。

读取的内容只包括:空白位置(空格、换行、制表格(tab和form-feeds),注释行、二进制或十六进制的数字。

数字中不能包含位宽说明和格式说明,其中readmemb要求每个数字是二进制数,readmemh要求每个数字必须是十六进制数字。数字中不定值x或X,高阻值z或Z,和下划线(_)的使用方法和代表意义与一般Verilog HDL程序中的用法一致。

在Verilog语法中,一共有以下六种用法:

(1)$readmemb(“<数据文件名>”,<存储器名>);

(2)$readmemb(“<数据文件名>”,<存储器名>,<起始地址>);

(3)$readmemb(“<数据文件名>”,<存储器名>,<起始地址>,<终止地址>);

(4)$readmemh(“<数据文件名>”,<存储器名>);

(5)$readmemh(“<数据文件名>”,<存储器名>,<起始地址>);

(6)$readmemh(“<数据文件名>”,<存储器名>,<起始地址>,<终止地址>);

下面代码逻辑,展示了将NUM个数据读取到存储器中,并转化为WIDTH宽度的数据,供测试使用。verilog的语法中涉及到地址必须使用绝对路径,这里使用{},拼接语法将地址拼成{PATH,"test_data.txt"}样式,PATH路径设置为宏参,在有多个文件需要读取时,如果文件路径变动,仅仅需要改变路径宏参即可。

parameter		PATH 	= "D:/FPGA/OFDM_802.11a_my/TX/matlab/OFDM_802_11a_TX/";//地址
parameter		WIDTH 	= 4'd8	;
parameter		NUM 	= 720	;//需要根据输入测试数据长度更改此宏参
integer					i					;
integer					j					;
reg   					test_data [NUM-1:0]	;
reg   	[WIDTH - 1:0]	test_data_byte [NUM/WIDTH-1:0]	;
initial begin
	$readmemb({PATH,"test_data.txt"},test_data);
    	for(i=0;i<NUM/WIDTH;i=i+1)begin
		for(j=0;j<WIDTH;j=j+1)
			test_data_byte[i][j] = test_data[i*WIDTH+j];
	end
end

3.FPGA的testbench中如何将输出数据存储在文件中

以下代码逻辑展示了,FPGA的testbench中如何将输出数据存储在文件中:

integer 				data_out		;
wire       [:]             dout         ;
initial begin
	data_out  =  $fopen({PATH,"data_out.txt"});
end	

//数据存储
always@(posedge clk)
begin
  if()
    begin
      $fdisplay(data_out,"%b",dout);
    end
end

4.Matlab去读取testbench存储的文件数据

4.1纯数字不带编码

如果文件里面的数据是像这样:

image
数据只是单纯表示数,不带有编码,直接使用load函数,读取进行比较即可:

load函数:将文件变量加载到工作区中。

语法

load(filename)

load(filename,variables)

load(filename,"-ascii")

load(filename,"-mat")

load(filename,"-mat",variables)

S = load(___)

load filename

说明

load(filename) 将数据从 filename 加载到 MATLAB® 工作区。如果 filename 是 MAT 文件,则 load(filename) 从文件中加载变量;如果 filename 是 ASCII 文件,则 load(filename) 从该文件加载包含数据的双精度数组。

load(filename,variables) 加载 MAT 文件 filename 中的指定变量。
load(filename,“-ascii”) 将 filename 视为 ASCII 文件,而不管文件扩展名如何。

load(filename,“-mat”) 将 filename 视为 MAT 文件,而不管文件扩展名如何。

load(filename,“-mat”,variables) 加载 filename 中的指定变量。

S = load(___) 使用上述语法中的任何输入参量组合将数据加载到 S 中。如果 filename 是 MAT 文件,则 S 是结构体数组;如果 filename 是 ASCII 文件,则 S 是一个包含文件中数据的 m×n 双精度数组,其中 m 是文件中的行数,n 是每行上值的数目。

load filename 是该语法的命令形式。命令形式需要的特殊字符较少。您无需键入括号或者将输入括在单引号或双引号内。使用空格(而不是逗号)分隔各个输入项。如果任一输入包含空格,请用单引号将其引起来。

例如,要加载名为 test.mat 的文件,以下语句是等效的:

load test.mat % command form
load(“test.mat”) % function form
您可以包括上述语法中介绍的任何输入。例如,要从名为 my file.mat 的文件中加载变量 X,请执行以下命令:

load ‘my file.mat’ X % command form, using single quotes
load(“my file.mat”,“X”) % function form, using double quotes
当有任何输入(例如 filename)为变量时,请不要使用命令格式。

想了解更详细建议去官网:https://ww2.mathworks.cn/help/matlab/ref/load.html

读取代码和效果如下:

FPGA_conv_dout = load([PATH,'conv_data_out.txt'])';

image

4.2 带编码的数据,如定点数

如果是带有编码的定点数(复数以8位定点数形式进行输出,格式为:1位符号位,一位整数位,6位小数位,负数以补码形式表示),比如这种定点数格式的FFT的输出,就需要转化为浮点数,再与Matlab中的仿真结果进行比较。

我们知道,Xilinx的FFT IP核,输入和输出实部和虚部是放一起的,高位为虚部,低位为实部,按照上面说的定点数格式,输出就是16bit。

FFT输出

我们使用readlines,以字符串数组形式读取文件行。
语法

S = readlines(filename)
S = readlines(filename,Name,Value)

说明
S = readlines(filename) 通过读取一个包含 N 行的文件创建一个 N×1 字符串数组。
S = readlines(filename,Name,Value) 基于文件创建一个字符串数组,并通过一个或多个名称-值对组参量指定其他选项。例如,‘EmptyLineRule’,‘skip’ 跳过空行。

想了解更详细建议去官网:https://ww2.mathworks.cn/help/matlab/ref/readlines.html

读取代码和效果如下:

FPGA_dac_dout = readlines([PATH,'dac_data_out.txt'],'EmptyLineRule','skip')';

image

然后还需要反量化,转化为浮点数,与Matlab仿真结果进行比较,使用bin2num函数,配合使用 quantizer 对象将 2 的二进制补码字符串转换为数字。

语法

y = bin2num(q,b)

说明

y = bin2num(q,b) 使用 quantizer 对象的 q 属性将二进制字符向量 b 转换为数值数组 y。

如果 b 是包含二进制字符串的元胞数组,则 y 将是包含数值数组的相同维度的元胞数组。

[y1,y2,…] = bin2num(q,b1,b2,…) 将二进制字符向量 (b1, b2, …) 转换为数值数组 (y1, y2, …)。

想了解更详细建议去官网:https://ww2.mathworks.cn/help/fixedpoint/ref/bin2num.html

quantizer函数的相关参数和使用方法,请去翻公众号上一篇文章,这里不再赘述。

处理代码和效果如下:

FPGA_Im_dac_dout = extractBefore(FPGA_dac_dout,9);
FPGA_Re_dac_dout = extractAfter(FPGA_dac_dout,8);
FPGA_Re_dac_dout = bin2num(q,FPGA_Re_dac_dout);
FPGA_Im_dac_dout = bin2num(q,FPGA_Im_dac_dout);

image
其中还使用到了extractBefore,extractAfter函数,使用很简单,就是取字符串的前几位和后几位。bin2num之后数据类型为cell,还需要再转换一下,使用cell2mat函数,代码如下:

FPGA_Re_dac_dout = cell2mat(FPGA_Re_dac_dout);
FPGA_Im_dac_dout = cell2mat(FPGA_Im_dac_dout);
FPGA_dac_dout = FPGA_Re_dac_dout + 1j*FPGA_Im_dac_dout;

成功转换为浮点数,可以与Matlab仿真结果进行比较了。
image

实部

虚部
微信公众号获取更多FPGA相关源码:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值