目录
- 1.前言
- 2.FPGA的testbench中如何读取数据文件
- 3.FPGA的testbench中如何将输出数据存储在文件中
- 4.Matlab去读取testbench存储的文件数据
- 4.1纯数字不带编码
- 4.2 带编码的数据,如定点数
微信公众号获取更多FPGA相关源码:
1.前言
前面一篇文章讲了,Matlab将调制映射后的数据转化为定点数,放入FPGA中进行处理。那么定点数,在FPGA中进行FFT过后,如何验证其正确性呢?这就需要将FFT的输出数据读取出来,在Matlab中转化为浮点数,然后与Matlab使用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)beginfor(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 begindata_out = $fopen({PATH,"data_out.txt"});
end //数据存储
always@(posedge clk)
beginif()begin$fdisplay(data_out,"%b",dout);end
end
4.Matlab去读取testbench存储的文件数据
4.1纯数字不带编码
如果文件里面的数据是像这样:
数据只是单纯表示数,不带有编码,直接使用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'])';
4.2 带编码的数据,如定点数
如果是带有编码的定点数(复数以8位定点数形式进行输出,格式为:1位符号位,一位整数位,6位小数位,负数以补码形式表示),比如这种定点数格式的FFT的输出,就需要转化为浮点数,再与Matlab中的仿真结果进行比较。
我们知道,Xilinx的FFT IP核,输入和输出实部和虚部是放一起的,高位为虚部,低位为实部,按照上面说的定点数格式,输出就是16bit。
我们使用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')';
然后还需要反量化,转化为浮点数,与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);
其中还使用到了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仿真结果进行比较了。
微信公众号获取更多FPGA相关源码: