vivado仿真读取txt文件数据方法整理

描述

vivado仿真读取txt文件数据方法整理

在信号处理或者一些功能仿真中,很多场景下都需要将txt文件中的数据批量导入到vivado中进行仿真测试,在vivado里提供了一些常用的文件处理函数,例如fcanf,sscanf,readmemh等,但是应用过程中有时候txt文件数据格式不一样,这时候直接使用这些函数就不太适用了,通常需要对txt数据格式进行处理,一般情况下原始数据转成带符号的16进制定点数后再用vivado去读取。本文经过各种探索和测试,整理了两种在vivado里读取txt文件的方式。

数据格式说明

数据最好是通过python或者MATLAB转成十六进制数据之后再写入txt文件,如图:

文件


图中是每行32个位宽为16bit的十六进制数据,txt文件一共2048行,需要讲这些数据导入到vivado里进行仿真测试,为了方便,可以将每行32个数据拼成一个512bit的数据,像这样:

文件


其实就是把数据中间的空格去掉就可以了,但前提是原本的数据一定是十六进制的,要不然拼起来到vivado里还要进行额外处理。
到这里就可以在vivado里使用函数读取txt文件了,这里提供两种方法。

方法一

在vivado里的仿真文件里添加下面语句:

parameter FILE_PATH_A = "E:/vivado_work/data.txt ";

(* ram_style = "block" *) reg [511:0] data[2047:0]; // 数据存放位置

integer file_r,i;    

initial begin

file_r = $fopen(FILE_PATH_A,"r");//r:以读形式打开

for(i=0;i<2048;i=i+1)  //一共2048行数据

$fscanf(file_r,"%h",data[i]);

$fclose(file_r);

end

reg clk = 0 ;

always #2.5 clk = ~clk ;

reg rst ;

initial begin

rst = 1 ;

#100

rst = 0 ;

end

//将数据从数据存储块内按时钟读取出来

reg [511:0]  data_chan = 0 ;

reg [11:0] j =0;

reg data_chan_vld = 0 ;

always @(posedge clk) begin

if(rst) begin

data_chan <= 0 ;

data_chan_vld <= 1'b0 ;

end

else if(j<2048) begin

data_chan <= data[j] ;

data_chan_vld <= 1'b1 ;

j <= j + 1 ;

end

else begin

data_chan <= data_chan ;

data_chan_vld <= 1'b0 ;

end

end

这种方法需要先将数据放到一块内存里,后续再按照时钟周期一个个读出来,不太灵活。作为对比,下面提供另一中方法。

方法二

parameter FILE_PATH_A = "E:/vivado_work/data.txt ";

(* ram_style = "block" *) reg [511:0] data; // 32个8位数据

reg clk = 0 ;

always #2.5 clk = ~clk ;

reg rst ;

initial begin

rst = 1 ;

#100

rst = 0 ;

end

reg [511:0]  data_chan = 0 ;

reg [11:0] j =0;

reg data_chan_vld = 0 ;

integer file_r,i;    

initial begin

file_r = $fopen(FILE_PATH_A,"r");//r:以读形式打开

end

always @(posedge clk) begin

if(rst) begin

data_chan <= 0 ;

data_chan_vld <= 1'b0 ;

end

else if(j<2048) begin

$fscanf(file_r,"%h",data);

data_chan <= data ;

data_chan_vld <= 1'b1 ;

j <= j + 1 ;

end

else begin

$fclose(file_r);

data_chan <= data_chan ;

data_chan_vld <= 1'b0 ;

end

end

在方法二里如果不想再txt文件里拼接数据,也可以修改代码为这样:

parameter FILE_PATH_A = "E:/vivado_work/.txt ";

(* ram_style = "block" *) reg [511:0] data_out; // 32个8位数据

reg clk = 0 ;

always #2.5 clk = ~clk ;

reg rst ;

initial begin

rst = 1 ;

#100

rst = 0 ;

end

reg [511:0]  data_chan = 0 ;

reg [11:0] j =0;

reg data_chan_vld = 0 ;

integer file_r,i;    

initial begin

file_r = $fopen(FILE_PATH_A,"r");//r:以读形式打开

end

always @(posedge clk) begin

if(rst) begin

data_chan <= 0 ;

data_chan_vld <= 1'b0 ;

end

else if(j<2048) begin

$fscanf(file_r, "%h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h",

data_out[496+:16], data_out[480+:16], data_out[464+:16], data_out[448+:16],

data_out[432+:16], data_out[416+:16], data_out[400+:16], data_out[384+:16],

data_out[368+:16], data_out[352+:16], data_out[336+:16], data_out[320+:16],

data_out[304+:16], data_out[288+:16], data_out[272+:16], data_out[256+:16],

data_out[240+:16], data_out[224+:16], data_out[208+:16], data_out[192+:16],

data_out[176+:16], data_out[160+:16], data_out[144+:16], data_out[128+:16],

data_out[112+:16], data_out[96+:16], data_out[80+:16], data_out[64+:16],

data_out[48+:16], data_out[32+:16], data_out[16+:16], data_out[0+:16]);

data_chan <= data_out ;

data_chan_vld <= 1'b1 ;

j <= j + 1 ;

end

else begin

$fclose(file_r);

data_chan <= data_chan ;

data_chan_vld <= 1'b0 ;

end

end

效果其实是一样的,只不过一个是在txt文件里拼接数据,一个是在vivado拼接数据。
到这里就可以直接按照我们提供的时钟周期来读取txt文件里的数据,并输出到后续其它模块,相比第一种方法这种方式可以更灵活的读取。

文件


仿真结果可以看到数据可以正确的读到vivado里了。

其它方法

在测试过程中其实也试过其它方法,例如对图1里的数据可以直接用readmemh函数来读取数据,然后将数据存放在一个三维数组里,但是这种方法在后边按时钟周期去读取数据时会比较麻烦,需要自己去控制读取的行数和列数。推荐文中所用的两种方法。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分