Matlab,vivado/modelsim,python的数据交互

         在进行verilog模块的开发过程中,常常需要对数据处理过程进行行为级仿真,以验证代码的功能逻辑是否正确,因此需要将RTL级仿真的结果与MATLAB或python的处理结果进行对比验证。将输入输出结果数据存入文件进行对比是在数据对比中常用的方法。本文讲述了Matlab,Verilog/SV,python之间进行的数据交互,包括matlab/python 写txt 或者dat 文件,verilog/SV读取与写入txt文件。脚本均进行了功能仿真,有问题请在评论区或者私信交流。

        Matlab是一个非常好用的工具,对于浮点仿真数据,我们需要进行定点化生成2进制或者16进制数据写入txt或者dat文档,方便后续Verilog代码读取($readmemb,$reammemh)。下面的代码有两种方式生成16进制或者2进制数据,写入数据的前提都是用round、floor等函数将浮点小数生成整数(round*(2^(N-1)))。下面的Matlab代码是将整形数据写入txt文件,第一种hex file代码简单,且写入迅速,美中不足的是只能写入正数,需要将有符号数转化成无符号数;第二种方法(%注释代码)是以二进制补码写入txt文件,逐bit判断,速度很慢,可以满足写入有符号数的需求。此外示例中给了两个基础函数用法,即有符号数与无符号数的转换,可以使用。

%%  methon1:signed to unsigned and output to txt.file in hex 
fid=fopen('C:\... \Desktop\DataIn.txt','w');
unsigned_si = s2us(si,24);
fprintf(fid,"%06x\n",unsigned_si); % fprintf only unsigned hex(%x)number 


%%  methon2:output  binary complement data  to txt.file
% for k=1:length(si)
%     B_s=dec2bin(si(k)+(si(k)<0)*2^N,N);
%     for j=1:N
%         if B_s(j)=='1'
%             tb=1;
%         else
%             tb=0;
%         end
%         fprintf(fid,'%s',B_s(j));
%     end
%     fprintf(fid,'\r\n');
% end
% fprintf(fid,';');
fclose(fid);


%% base function:signed to unsigned 
function out = s2us(in,dw)
% narginchk(2,3);
re = real(in) + (real(in)<0)*2^dw;
im = imag(in) + (imag(in)<0)*2^dw;
out = re + im*2^dw;
% if nargin == 3
%     if comp == 0 %real
%         out = in + (in<0)*2^dw;
%     else % complex
%         re = real(in) + (real(in)<0)*2^dw;
%         im = imag(in) + (imag(in)<0)*2^dw;
%         out = re + im*2^dw;
%     end
% else
%     out = in + (in<0)*2^dw;
% end


%% base function :unsigned to signed

function out = us2s(in,dw)

if isReal(in)
    re = mod(in,2^dw) - (mod(in,2^dw) >=2^(dw-1))*2^dw;
    im = floor(in/2^dw) - (floor(in/2^dw) >=2^(dw-1))*2^dw;
    out = re + 1j*im;
else
    re = real(in)-(real(in)>=2^(dw-1))*2^dw;
    im = imag(in)-(imag(in)>=2^(dw-1))*2^dw;
    out = re + 1j*im;
end

% narginchk(2,3);
% if nargin == 3
%     if comp == 0 %real
%         out = in - (in>=2^(dw-1))*2^dw;
%     else % complex
%         real = mod(in,2^dw) - (mod(in,2^dw) >=2^(dw-1))*2^dw;
%         imag = fix(in/2^dw) - (fix(in/2^dw) >=2^(dw-1))*2^dw;
%         out = real + 1j*imag;
%     end
% else
%     out = in - (in>=2^(dw-1))*2^dw;
% end

        目前随着python的流行,利用python 生成仿真数据,并与verilog进行数据交互的情形也非常之多。下面给出一段示例代码,将python的浮点数据(整数)打印成.dat文件数据格式。

def print2dat_qi(data=0, bw=16, name="file"):
    """
    :param data:打印数据
    :param bw:  位宽
    :param name:打印文件名称
    """
    data_qi = []
    file = str(name + ".dat")
    bwhex = np.ceil(bw / 4)
    modbw = 4 - np.mod(bw, 4)
    with open(file, "w") as f:
        pass
    with open(file, "a") as f:
        for i in range(len(data)):
            if isinstance(data[i, 0], complex):
                # data_rnd = complex(round_new(data[i].real), round_new(data[i].imag))
                data_rnd = data[i, 0]
                data_i = data_rnd.real
                data_q = data_rnd.imag
                if data_i < 0:
                    data_i =  data_i + 2 ** bw
                else:
                    data_i =  data_i

                if data_q < 0:
                    data_q =  data_q + 2 ** bw
                else:
                    data_q =  data_q

                if modbw == 4:
                    bwhexh = bwhex
                    bwhexl = bwhex
                else:
                    data_i = np.mod(data_q, 2 ** modbw) * 2 ** bw + data_i  # 高Q低I
                    data_q = np.floor(data_q / 2 ** modbw)
                    bwhexh = int(np.ceil((bw - modbw) / 4))
                    bwhexl = int(bwhex)

                data_str = "%0" + str(bwhexh) + "x%0" + str(bwhexl) + "x" + "\n"
                f.write(data_str % (int(data_q), int(data_i)))
                # f.write(data_str % (int(data_i), int(data_q)))

            else:
                # data_rnd = round_new(data[i])
                data_rnd = data[i,0]
                if data_rnd < 0:
                    data_qi =  data_rnd + 2 ** bw
                else:
                    data_qi =  data_rnd
                data_str = "%0" + str(bwhex) + "x\n"
                f.write(data_str % int(data_qi))
# how to use  the function 
# print2dat_qi(np.array([data_in]).T, 16, "print_datain")

        除了与verilog数据交互外,python也可以读取matlab的数据格式.mat,方便我们python 与matlab进行数据传递。

coefFile = './coef_light_fix.mat'
dataFile = './sign_fix.mat'
sign_fix = scio.loadmat(dataFile)
print(sign_fix)
signal_data = sign_fix['sigin_fix']
coef_tmp = scio.loadmat(coefFile)
coef = coef_tmp['coef_light_fix']
signal_data_flatten = signal_data.flatten()
fir_in = signal_data_flatten[32767:32767+8192]
coef_in =  coef.flatten()
intp = 2
fir_in_intp2=np.zeros(len(fir_in)+(len(fir_in)-1)*intp,dtype=complex)
fir_in_intp2[::intp+1]=fir_in

        经过以上几个部分,我们大致了解了如何利用python或者matlab进行数据格式如txt,dat生成,那么在我们的仿真中,如何在testbench上利用这些数据呢?

Verilog中读写文件常用到的系统任务主要有以下几个:

1.文件打开、关闭与定位操作:$fopen(file_name)、$fclose(file_name)、$fseek();

2.文件读取:$fscanf和 $​readmemh,其中$​readmemh的作用是件文件中的数据一次性的读入某个数组中,然后依次从数组中取出1个数据进行处理;而$fscanf的作用是从文件中读出一行的数据。两个系统任务的常见用法如下:

$​readmemh         or         $​readmemb

logic x_in[0:8191];
logic [12:0] cnt_in;

initial begin
    $readmemb({"D:./algorithm_sim/pdm_1b.dat"},x_in,0,8191); //建议使用绝对路径
end
        
always #1 clk = ~clk;

initial
begin
    

    clk <= 1'b0;
    d_in <= 1'b0;
    repeat(10) @(posedge clk);
    rst <= 1'b1;
    @(posedge clk);
    rst <= 1'b0;

end

always @(posedge clk or posedge rst) begin
    if (rst)
        cnt_in <= 13'd0;
    else 
        cnt_in <= cnt_in + 1'b1;
end

always @(posedge clk) begin
    d_in <= x_in[cnt_in];
end

        Verilog在读取仿真数据的时候,有时候也需要进行仿真数据文件的输出,常用的函数有$fwrite(file_name)、$fdisplay(file_name),相应的脚本这里一并给出。

`timescale 1ns / 1ns
module tb_read_write( );
 
integer fp_r,fp_w;  
logic [7:0]count;   
logic clk;
logic [15:0] reg1;
 
initial  
begin 
    clk = 1'b0; 
    reg1 = 16'h0;
    count = 8'd0;
    // method 1 : fopen fwrite
    fp_r=$fopen("data.txt","r");//以读的方式打开文件  
    fp_w=$fopen("data_out.txt","w");//以写的方式打开文件  
end 

always #5 clk = ~clk;
 
always@(posedge clk)
begin
    if(count < 9'd500)
    begin
        $fscanf(fp_r,"%d" ,reg1) ;//每次读一行 
        count <= count + 1'b1; 
        $fwrite(fp_w,"%d\n",reg1) ;//写入文件
    end
    else
    begin
         $fclose(fp_r);//关闭已打开的文件
         $fclose(fp_w);
    end  
end

//method 2 :fdisplay
integer file_Sn;
initial
begin
   //文件放置在"工程目录\simulation\modelsim"路径下                                                  
    file_Sn = $fopen("Sn.txt");
end
always @(posedge clk)
$fdisplay(file_Sn,"%d",Sn);//将数据Sn写入文本

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值