1. 程式人生 > 實用技巧 >HDL檔案操作總結

HDL檔案操作總結

VHDL  

檔案操作都在tb中,因為涉及到作業系統,所以無法綜合。

  在vhdl中,檔案被看作 行 組成的一維陣列。

  預先要把兩個檔案讀寫相關的庫宣告。

1 use STD.TEXTIO.all;

2 use ieee.STD_LOGIC_TEXTIO.all;

  首先要宣告用來儲存檔案資料的陣列,以一個80X64的32位浮點影象資料為例。

1     type TYPE_MdlImgDat32_r is array (0 to 79) of std_logic_vector(31 downto 0);
2     type TYPE_MdlImgDat32 is array (0 to
63) of TYPE_MdlImgDat32_r;

  首先定義了一個80大小的一維陣列型別,陣列成員為32位std_logic_vector

  然後再定義了一個64大小的一維陣列型別,陣列成員型別為一維陣列。

  這樣我們就得到了一個二維陣列型別,當然我們也可以用下面的方法來直接定義:

    type matrix is array(0 to 63, 79 downto 0) of std_logic_vector;

  在定義完用來存數的陣列結構之後,我們需要申明檔案控制代碼。

1     file FILE_MdlImg          : TEXT;
2     file FILE_MdlImg_rad      : TEXT
; 3 file FILE_MdlImg_mag : TEXT; 4 file FILE_RefImg : TEXT; 5 file FILE_RefImg_Software : TEXT; 6 file FILE_MdlImg_Software : TEXT;

  申明完檔案控制代碼之後,記得要把前面定義的陣列初始化。、

1 variable vMdlImgDat32 : TYPE_MdlImgDat32 := (others => (others => (others => '0')));     

  因為檔案內部是一行一個數據,而且是32位的HEX表示,所以還需要宣告行控制代碼

1         variable MdlL_OUT : LINE;
2 
3         variable RefL_OUT : LINE;
4 
5         variable RefL_OUT_Software : LINE;
6 
7         variable MdlL_OUT_Software : LINE;

  把檔案讀入二維陣列中

  file_open,第一個引數是前面定義的檔案控制代碼,後面是檔案的絕對路徑,最後是讀或者寫模式。

  readline,第一個引數還是檔案控制代碼,第二個是前面定義的行控制代碼。

  hread,第一個引數是行控制代碼,第二個引數是二維數組裡面的某個元素。

  file_close,關閉之前開啟的檔案。

1         FILE_OPEN(FILE_MdlImg_Software, "C:\Users\MekiX\Documents\Recorded_projects\cal_mag\mag_cal_ready_valid\Data\srcimg_oactave__80x64_hex.txt", READ_MODE);
2         ReadMdlImgFromFiles : for i in 0 to 63 loop
3             loopX               : for j in 0 to 79 loop
4                 READLINE(FILE_MdlImg_Software, MdlL_OUT_Software);
5                 HREAD(MdlL_OUT_Software, vMdlImgDat32(i)(j));
6             end loop;
7         end loop;
8         FILE_CLOSE(FILE_MdlImg_Software);

  總結一下就是,先把檔案開啟,再把檔案的行讀取,之後再把檔案的行內元素依次寫入到二維陣列中。(readline應該可以放到loopx上面,還未驗證)。

  對於寫操作,基本類似。

  先也是file_open,

  HWRITE,第一個引數是行控制代碼,第二個資料,第三個是游標向右移動的位置,10是移動的長度。32位的HEX表示應該是8,寫成10留了點餘量。資料前面會有兩個空格。寫入方式也就是一個數據一行。

  WRITELINE,第一個引數是檔案控制代碼,第二個是行變數。

  最後再把檔案關閉。

  生成的檔案在vivado工程的sim資料夾下.

 1         FILE_OPEN(FILE_MdlImg_rad, "MdlImg_rad.txt", WRITE_MODE);
 2         wait until rising_edge(aclk);
 3 
 4         while m_axis_rad_tuser = '0' loop
 5             wait until rising_edge(aclk);
 6             if (m_axis_rad_tvalid and m_axis_rad_tready) = '1'then
 7                 HWRITE(MdlL_OUT, m_axis_rad_tdata, right, 10); 9                 WRITELINE(FILE_MdlImg_rad, MdlL_OUT);
10             else
11                 wait until (m_axis_rad_tvalid and m_axis_rad_tready) = '1';
12                 wait until rising_edge(aclk);
13                 HWRITE(MdlL_OUT, m_axis_rad_tdata, right, 10);15                 WRITELINE(FILE_MdlImg_rad, MdlL_OUT);
16             end if;
17         end loop;
18         FILE_CLOSE(FILE_MdlImg_rad);

Verilog

  以下都是task型別的.

  讀檔案一般使用$readmemb,$readmemh,分別是讀二進位制和16進位制的檔案。

  同樣需要先建立一個數組

  1 reg[31:0] mem[79:0][63:0]//多維陣列是verilog2001的新功能,之前只支援一維

  但是不需要再開啟檔案

  1 $readmemb("file1.txt",mem);

  上面的檔案可以使用絕對地址,只需要把"\"換成"/".

  寫檔案一般是

  首先定義一個整數型別的檔案指標,然後用$fopen開啟檔案.

  $fopen實際上可以有兩個引數,中間用 , 隔開,後面一個是mode

  常用mode包括

  “w",“wb" 清除檔案內容並從檔案頭開始寫,如果不存在就建立檔案,只寫模式。(預設模式) .

  “w+",'w+b","wb+"清除檔案內容並從檔案頭開始讀寫,如果不存在就建立檔案,可讀寫模式.

  "a","ab"    從檔案末尾開始寫,如果不存在就建立檔案,只寫模式。

  “a+","a+b","ab+" 檔案末尾開始讀寫,如果不存在就建立檔案,可讀寫模式.

  "r","rb"     只讀模式.

  "r+","r+b","rb+" 可讀寫方式.

  多一個b為binary

  1 integer hex_image_80X64; 2 hex_image_80X64 = $fopen("hex_image_80X64.txt")

  然後我們向檔案寫入資訊,常用的task有:

  $fdisplay,$fwrite,$fstrobe,$fmonitor.格式控制有

      %c %C character (low 8 bits)
                    %d %D decimal  %0d for minimum width field
                    %e %E E format floating point %15.7E
                    %f %F F format floating point %9.7F
                    %g %G G general format floating point
                    %h %H hexadecimal
                    %l %L library binding information
                    %m %M hierarchical name, no expression
                    %o %O octal
                    %s %S string, 8 bits per character, 2´h00 does not print
                    %t %T simulation time, expression is  $time
                    %u %U unformatted two value data  0 and 1 
                    %v %V net signal strength
                    %z %Z unformatted four value data  0, 1, x, z

  %5d, %5b.前面的數字類似vhdl,也是長度控制.,也可以直接在task後面加b/h/o,也可以直接把預設格式切換成指定的格式,例如$fdisplayb,就是二進位制.

  $fdisplay和 $fwrite在每次被執行的時候都會向檔案中寫入指定格式的資料,區別在於$fdisplay每次執行完畢會新增新的一行,而$fwrite不會.

  $fstrobe也是寫入資料但是是在同一時刻所有語句執行完畢之後再執行,舉例:

1 initial 
2 #1 a=1; 
3 b=0; 
4 $fstrobe(hand1,a,b); // 預設格式將ab寫入
5 b=1;

  此時,檔名是hand1,寫入的ab都是1;

  $fmonitor是在引數變化的時候往檔案裡寫數.

  它們的具體格式非常類似c,這也是因為verilog開發的初衷就是為了比VHDL貼近C.舉例如下:

  

1 f = $fopen("output.txt","w");
2 $fmonitor(f, "%h", acc_out);
3 $fclose(f);

  這些task前面的f去掉之後就是在螢幕上顯示而非寫入檔案.而具體的語法區別在於最前面的引數從檔案控制代碼(通過$fopen得到)換成了類似c的字串輸出,舉例如下

1 $monitor("monitor a:%h @ %0t", acc_out, $time);

  分別將accout以16進位制替換%h,time替換%0t.同時,與c語言類似,也有

1                                                  \t   tab
2                                                  \\   backslash反斜槓
3                                                  \"   quote引號
4                                                  %%   percent

  如果這些task沒有指定輸出或者寫入格式會怎麼樣?

  寫入完成之後,呼叫$fclose關閉檔案,引數是整數控制代碼變數而非檔名.

  讀取和寫入一般只執行一次,放在initial塊中.

  task還有很多,下次用到再寫.