閱讀514 返回首頁    go 阿裏雲 go 技術社區[雲棲]


通過文件讀寫方式實現Matlab和Modelsim的聯合仿真

雖然Modelsim的功能非常強大,仿真的波形可以以多種形式進行顯示,但是當涉及到數字信號處理的算法的仿真驗證的時候,則顯得有點不足。而進行數字信號處理是Matlab的強項,不但有大量的關於數字信號處理的函數,而且圖形顯示功能也很強大,所以在做數字信號處理算法的FPGA驗證的時候借助Matlab會大大加快算法驗證的速度。

    關於MatlabModelsim聯合仿真,我從網上看到兩種方法,一種是通過Link for Modelsim建立MatlabModelsim的聯合仿真接口;另一種就是通過文件讀寫的方式實現MatlabModelsim的聯合仿真。我沒有仔細研究過第一種方法,我大概看了一下,感覺過程比較複雜,不過功能肯定也很強大,網上有一篇關於Link for Modelsim的文章https://space.ednchina.com/Upload/2009/11/16/9e8d0364-20ed-4583-a85e-4d1fc50783a7.rar" target=_blank>,有興趣的朋友可以去看一看。關於第二種方法,隻是通過幾個文件讀寫函數就可以實現了,而且基本可以滿足當前仿真的要求,所以這裏主要討論一下我所使用的這種方法,希望能夠拋磚引玉吧,因為我也隻能算個初學者而已。

    1. Matlab產生數據用作Modelsim仿真

    在FPGA進行算法驗證的時候,經常需要輸入仿真數據,這些數據可以用FPGA產生,但是如果數據產生過程很複雜的話,需要耗費很大的精力,並且產生的數據的準確性也不能保證。例如,如果要驗證一個通信接收機的相關算法,那麼我們就需要先產生發送數據,也就是說得先做一個發射機,如果這個過程也由FPGA實現的話,也是一個很複雜的過程。這時候我們就可以借助Matlab,利用Matlab內部自帶的各種函數,產生需要的信號,再經過定點化,就作為FPGA接收模塊的輸入信號了。這樣做無疑會節約很多時間和精力。

    下麵用一個簡單的例子說明如何用Matlab產生的數據用作Modelsim仿真。

    首先利用matlab產生一個周期2568bit的正弦波數據,然後以16進製形式寫入sin.txt文件

          N = 256;

          n = 1:256;

          x = fix(128 + (2^7 - 1) * sin(2*pi*n/N));

          fid = fopen('sin.txt','wt');

          fprintf(fid,'%x\n',x);

         fclose(fid);

    下圖是截取的產生的數據文件的內容


   然後將產生的sin.txt文件複製到Modelsim的工程下,在Verilog文件中先定義一個8bit X 256數組,然後通過$readmemh命令,將文件中的數據讀入,相關的Verilog代碼如下:

reg [7:0] data_mem[0:255]; //定義一個8bit X 256的數組

initial

    begin

    $readmemh("sin.txt",data_mem); //sin.txt中的數據讀入存儲器data_mem

    end

    關於$readmemh的用法可以參見Verilog的參考書,這裏就不詳細說了。

後麵就可以用data_mem作為你的測試數據了。例如可以通過以下代碼,將data_mem的數據送給data_out

always @(posedge clk)

begin

    if(rst)

        begin

        data_out <= 8'd0;

        i <= 8'd0;

        end

    else

        begin

        data_out <= data_mem[i]; //將存儲器中的數據輸出

        i <= i + 8'd1;

        end

end


    這樣利用data_out就可以輸出一個正弦波波形,下圖是Molesim仿真產生的正弦波波形:

    2. MatlabModelsim仿真生成的數據進行分析

        MatlabModelsim仿真生成數據的處理也是通過文件讀寫實現的。即通過Verilog語句,將仿真過程中的某個信號寫入文件,然後在Matlab中在把這個文件的數據讀出來,就可以在Matlab中進行分析了。

    下圖也通過一個簡單的例子,說明一下整個過程。

    以下的Verilog語句實現將信號data_out的數據寫入data_out.txt文件

    integer w_file;

    initial w_file = $fopen("data_out.txt");

    always @(i)

    begin

        $fdisplay(w_file,"%h",data_out);

        if(i == 8'd255)    //共寫入256個數據

            $stop;

    end


    下圖是截取的data_out.txt的部分內容:

 

    然後就可以編一小段Matlab的程序將data_out.txt中的數據讀取進行分析了。下麵一段Matlab的程序是將數據讀取,並通過圖形顯示出數據的波形。

    fid = fopen('data_out.txt','r');

    for i = 1 : 256;

        num(i) = fscanf(fid, '%x', 1);    %這句話的意思是從fid所指的文件以16進製方式讀出一個數據。

    end

    fclose(fid);

    plot(num);

    當利用fscanf函數時要注意兩點

    第一:保證讀取的數據格式和文件中保存的數據格式是相同的,例如這裏文件中保存的格式是十六進製,所以讀取的時候也應該以十六進製的形式讀出。

    第二:要保證文件中數據的個數和設定的讀取的數目(這裏是256)保持一致。例如,要將生成文件data_out.txt中多餘的換行符去掉(一般最後會多出一行),否則Matlab會將空的行也當做一個數據,從而兩個數目不一致,導致Matlab報錯。

    下圖是Matlabdata_out.txt中的數據讀出,並顯示出的波形

 

    當然,有了Matlab這個強大的工具,也就可以很方便的看信號的頻譜等信息了。

    另外在說一點,就是關於通過Verilog將數據寫入文件有多種方法,上麵用的是$fdisplay這個係統函數,當然還有$fmonitor$fwrite等幾個命令,下麵簡單說一下這幾個命令的不同。


  • $fdisplay

    這個命令需要有觸發條件,才會把數據寫入文件,例如,上例的觸發條件就是always(i),當i變化的時候才寫入。每寫入一次數據會自動增加一個換行符。


  • $fmonitor

    這個命令不需要觸發條件,隻要有變化就可以將數據寫入文件。例如可以通過以下語句:

    initial $fmonitor(w_file,"%h",data_out);

    這樣可以將整個仿真過程產生的data_out數據都寫入文件中。


  • $fwrite

    這個命令和$fdisplay基本相同,也是需要觸發條件才會寫入,不同的是每寫入一個數據不會自動添加換行符。例如可以通過以下語句:

    always @(posedge clk)

    begin

        $fwrite(w_file,"%h\n",data_out);

    end

    關於這幾個命令的詳細介紹,大家可以參考Verilog的相關數據。

        簡單總結一下上麵用到的幾個函數:

  • 關於Matlab的函數有:fopen fscanffclose 
  • 關於Modelsim的函數有:$fopen$fclose$readmemh$readmemb$fmonitor$fdisplay$fwrite

    上麵就是我關於MatlabModesim進行聯合仿真的一些心得,如果大家還有其他更好的方法,希望不吝賜教啊!

最後更新:2017-04-03 05:39:50

  上一篇:go (管道)寫入子shell
  下一篇:go 對ISE仿真的理解