ModelSim对.txt⽂件的读写——⼗进制格式
ModelSim和matlab同为两款强⼤的软件,前者⼯作的重⼼在于硬件设计的仿真,后者则是强⼤的数学分析,当硬件系统处理的信号⽐较复杂时,就可能会涉及到使⽤matlab来对ModelSim仿真输出的结果进⾏分析处理的情况,这是两款软件的联合仿真就显得尤为重要。
本⽂介绍⼀种以“⽂本⽂件”为媒介的联合仿真过程,即通过⽂件读写的⽅式实现⼆者的交互。⽐如通过matlab软件⽣成测试数据并写⼊.txt⽂件中,由ModelSim软件通过内部函数(如fscanf)将⽂件中的数据依次读⼊系统内模拟数字信号的采样值进⾏处理;ModelSim对数据完成处理后,将最终的结果再次通过系统函数(如fdisplay)将数据写⼊.txt⽂件中,由matlab软件读取进⾏后期信号分析处理。
本⽂重点介绍⼀种更实⽤的ModelSim读写.txt⽂件的⽅法。
读⽂件:
以待读取数据为16bit为例。
module rewr_test();
reg clk ;
reg rst_n ;
//-------------------------------------
//------write test---------------------
//-------------------------------------
integer j ;
integer fid ;
integer data_int ;
integer data ;
reg data_valid ;
//-------------------------------------
//------read test---------------------
/
/-------------------------------------
integer fid_in ;
integer data_in_int ;
integer rc_x ; //constant 0000_00001
reg [15:0] data_in ;
always #5 clk = ~clk;
initial
begin
fid_in = $fopen("","r"); //constant 8000_00004
fid = $fopen(""); //constant 0000_00002
#10 clk <= 1'b0;
rst_n <= 1'b0;
data_valid <= 1'b1;
data <=32'b0;
#10 rst_n <= 1'b1;
for (j=0; j < 1536000; j=j+1) begin
@(posedge clk);
data <= {$random}%65535 ;
end
end
//-------------------------------------
//------read test---------------------
/
/-------------------------------------
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data_in <= 16'd0;
end
else
begin
rc_x = $fscanf(fid_in,"%d",data_in_int);
data_in <= data_in_int;
end
end
//-------------------------------------
//------write test---------------------
//-------------------------------------
always @ (posedge clk)
begin
if(data_valid)
begin
data_int = data;
$fdisplay(fid, "%d",data_int);
end
end
endmodule
系统函数将数据以32bit整型格式读⼊内存中,由于多位宽数据向少位宽数据赋值时,综合⼯具默认将多位宽数据的低位赋给少位宽数据,因此数据得以以原始⼤⼩传⼊ModelSim的输⼊数据寄存器内。
由于为了⽅便⼤家使⽤,同样附上matlab写.txt的代码:
fid = fopen('','w');
fprintf(fid,'%d\n',data_in);
fclose(fidro);
需要注意的时,matlab⽣成数据的设置位宽(其量化值对应的位宽)应同ModelSim内仿真要求的数据位宽相⼀致,这样才能保证数据的⼤⼩不会在传输中出现误差。
写⽂件:
以待写⼊数据位宽16bit为例。
parameter MAXVAL_c = 2**(16 -1);
parameter OFFSET_c = 2**(16);
initial
fid = $fopen("");
integer data_int;
always @ (posedge clk)
begin
if(data_valid)
begin
data_int = data;
$fdisplay(fid, "%d", (data_int < MAXVAL_c) ? data_int : data_int - OFFSET_c);
end
end
其中参数MAXVAL_c 为数据以补码形式表⽰时,向上溢出的临界值,即16bit位宽的数据转换成整型数据(integer,⾼位补零转成32位整型数据),当转换结果⼤于或等于MAXVAL_c 时,表⽰数据溢出。
实际上,只有16bit的数据为负数时,才会出现上述所提到的溢出情况,这个时候就要对其进⾏修正,使得matlab或者其他软件在读取转换后的整型数据时仍然能得到原始的数据值。这时就⽤到了偏移量OFFSET_c,直接整型转换后的结果减去OFFSET_c就得到了32位整型数据表⽰的原始数据值。
将待写⼊数据进⾏了以上整型转换后就可以直接写⼊.txt⽂件中。matlab软件可以使⽤load命令直接从txt⽂件中读取上述数据,得到最初的处
理输出结果。
matlab读取命令为:data= load('');
写任务⼆进制格式
这⾥写任务⽤$fopen和$fdisplay两个系统任务完成,其中前者⽤来得到⽂件句柄,所谓句柄就是⽤来打开这个⽂件的读写通道,这⾥笔者在modelsim环境下试验了⼀下⼀旦⽤$fopen打开⽂件就会将⽂件清空。因此要读⽂件最好⽤$readmemb任务,写⽂件再⽤$fopen,注意最好新建个新⽂件来写,以免重要数据被清空。
⽤$fopen取得想要写⽂件的句柄handle,然后我们desc=handle|1;(⽬的最低位置1)这样写⽂件时trancript框中也同样会输出;
⽤$fdisplay(desc,"display=%b",remember[k]);通过for语句就可以将原⽂件中的数据写到另⼀个⽂件中去了;
例⼦如下:
module rewr_test();
reg [7:0]mem[0:15];
integer k,handle2,desc;
initial
begin
handle2=$fopen("file2.dat");
$readmemb("file1.dat",mem);
desc=handle2 |1;
$display("handle2=%b desc=%b",handle2,desc);
for(k=0;k<=15;k=k+1)
begin
$fdisplay(desc,"%b",mem[k]);
end
end
endmodule
附录⼀,读取多个⽂件,打开关闭⽂件
module video_bt1120_bfm_v1
#(
parameter C_VIDEO_TLPF = 1125,
parameter C_VIDEO_ALPF = 1080,
parameter C_VIDEO_TSPL = 2200,
parameter C_VIDEO_ASPL = 1920,
parameter C_VIDEO_VBLK = 42
)
(
input I_sys_clk, ///148.5Mhz
input I_sys_rstn, ///Active low
output [15:00] O_video_pdat,
output O_video_pclk
);
localparam VF1_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF2_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF3_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF4_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF5_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF6_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF7_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/"; localparam VF8_PATH = "E:/3Dde_noise/simulation/3dn_v1_03/video_frame/video_in/";
reg [11:00] S_pixel_cnt;
reg [10:00] S_line_cnt;
reg [01:00] S_trs_vh;
reg S_trs_av;
reg S_trs_act;
reg S_file_rd_act;
reg [01:00] S_trs_vh_d1;
reg S_trs_act_d1;
reg S_first_frame;
reg [10:00] S_act_frame_cnt;
reg [01:00] S_trs_cnt;
reg [15:00] S_prbs_dat_gen;
wire [02:00] S_trs_fvh;
wire S_trs_p3;
wire S_trs_p2;
wire S_trs_p1;
wire S_trs_p0;
reg [15:00] S_video_pdat;
integer fp_rd;
integer S_int_dat;
integer t1;
reg [15:00] S_simu_dat;
always @(posedge I_sys_clk or negedge I_sys_rstn)
begin
if(~I_sys_rstn)
S_pixel_cnt <= 'b0;
else if(S_pixel_cnt == (C_VIDEO_TSPL))
S_pixel_cnt <= 1'b1;
else
S_pixel_cnt <= S_pixel_cnt + 1'b1;
end
always @(posedge I_sys_clk or negedge I_sys_rstn)
begin
if(~I_sys_rstn)
S_line_cnt <= 'b0;
else if(S_pixel_cnt == (C_VIDEO_TSPL))begin
if(S_line_cnt == (C_VIDEO_TLPF))
S_line_cnt <= 1'b1;
else
S_line_cnt <= S_line_cnt + 1'b1;
end
end
always @(posedge I_sys_clk or negedge I_sys_rstn)
begin
if(~I_sys_rstn)
S_trs_vh <= 2'b11;
else begin
fprintf格式if(S_pixel_cnt <= 12'd4)
S_trs_vh[0] <= 1'b1;
else
S_trs_vh[0] <= 1'b0;
if((S_line_cnt >= C_VIDEO_VBLK) && (S_line_cnt <= (C_VIDEO_VBLK + C_VIDEO_ALPF - 1'b1))) S_trs_vh[1] <= 1'b0;
else
S_trs_vh[1] <= 1'b1;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论