在對VHDL代碼進行ModelSim仿真的時候,如果測試一個比較簡單的功能,比如簡單地測試一個IPCore,那麼我們只需要
signalName <= x"01"; wait for cam_period*5;
signalName <= x"10"; wait for cam_period*5;
類似的代碼就可以滿足我們的要求。
但是呢,假如你要測試一個大的COMPONENT,或者是測試一個數據序列,抑或是一個圖像,那麼這時候,通過文件讀取數據將會使工作簡單很多。與此同時,爲了保存試驗結果,也常常用到文件。尤其是對於FPGA的圖像處理,文件讀取必不可少。首先將一副正常圖像轉換爲一個txt文件,然後作爲FPGA的輸入,經過處理的圖像數據再保存成txt文件,再將這個txt文件轉換爲圖像,這樣就可以直觀地看到圖像處理的效果了。
那麼今天筆者就來講一下VHDL中txt文件的讀取和寫入。
file_open(file_status,FILE_OUT,"data_record.txt",write_mode);
上面那句代碼是整個文件讀取與寫入系統中最重要的,意思是以write Mode
形式打開“data_record.txt”這個文檔。
TXT文本的讀寫方式一共有三種,分別是READ_MODE
、WRITE_MODE
和APPEND_MODE
。按照字面意思就可以理解,分別是讀取模式、寫入模式與擴展模式。APPEND_MODE
與WRITE_MODE
的區別在於,WRITE_MODE
會清除掉文本中原來存在的內容,而APPEND_MODE
不會。
file_open(file_status,FILE_OUT,"data_record.txt",read_mode);
file_open(file_status,FILE_OUT,"data_record.txt",append_mode);
這是另外兩種模式。
--讀取數據
stim_process : process(cam_clk)
variable i : integer:= 0;
file TEST_IN : TEXT;
variable LINE_IN: line;
variable dat_in : std_logic_vector(31 downto 0);
begin
if(rst_n = '0' and dataIn = '0') then
file_open(TEST_IN, "image-binary-data.txt", READ_MODE);
dataIn <= '1';
elsif(rising_edge(cam_clk)) then
if((i mod ((512*135) + 300)) < 300) then
vs_i <= '0';
else
vs_i <= '1';
end if;
if (((i mod ((512*135) + 300)) < 300) or (((i mod (512*135+300))-300) mod 135) < 7) then
hs_i <= '0';
dv_i <= '0';
da_i <= (others => '0');
else
hs_i <= '1';
dv_i <= '1';
readline(TEST_IN, LINE_IN);
read(LINE_IN, dat_in);
da_i <= dat_in;
end if;
i := i + 1;
end if;
end process;
這是從 image-binary-data.txt 讀取數據的一個過程,當然其中還包含了一個判斷的過程,只在某些時刻纔會從文本中讀取數據。
在這邊有一個小技巧,就是設置一個標誌signal,這裏我設置的是 dataIn
, 設置其初始值爲'0'
,當文本打開之後,將該signal設置爲’1’,在 rst_n = '0'
以及dataIn = '0'
這兩個條件都滿足的情況下才進行文本的打開,之後就開始進行文本按行地讀取,並輸入到下一個COMPONENT中。
下面介紹一下文本的寫入。
--保存輸出數據
process(cam_clk)
FILE FILE_OUT : TEXT;
variable file_status:file_open_status;
variable buf:LINE;
begin
if(rst_n = '0' and dataOut = '0') then
file_open(file_status,FILE_OUT,"data_record.txt",write_mode);
file_close(FILE_OUT);
file_open(file_status,FILE_OUT,"data_record.txt",append_mode);
dataOut <= '1';
elsif(rising_edge(cam_clk))then
if(dv_o='1') then
write(buf,da_o);
writeline(FILE_OUT,buf);
end if;
if(sim_end = '1') then
file_close(FILE_OUT);
end if;
end if;
end process;
和上面的代碼一樣,這裏也有一個dataOut的標誌signal,在rst_n = '0' and dataOut = '0'
這兩個要求同時滿足的時候纔打開文本。但是看到在 rst_n = '0' and dataOut = '0'
這個條件下面做了四件事情,打開文本,再關閉,再打開,然後將標誌signal置‘1’,而且兩次打開的模式不同,一次是write_mode
,一次是append_mode
,爲什麼要這樣處理呢。下面給大家講一下這個緣由。
文本打開了,肯定是要關閉的,那如果用write_mode這種模式打開的話,file_close(FILE_OUT)的時候,也就是文本關閉的時候,文本中只會留下一行數據。而換成append_mode這種模式的話,在file_close(FILE_OUT)的時候,之前寫入文本的數據都會留下來。那爲什麼先要用write_mode這種模式打開呢,我用這種模式打開了,然後再關閉,整個文檔裏的內容就清除了,就可以保證接下去操作的是空文本,這就是先用write_mode打開的原因。
要注意的是,在寫入的狀態下,在沒有關閉文本的情況下,文本的大小一直是0K,但是呢,打開還是能看到文本中的數據信息的,裏面的數據也可以複製出來,但是這些數據並不真正存在於這個文本中,這個文本也被ModelSim佔用,不能複製,剪切等操作。
這裏設置了一個結束仿真的標誌signal sim_end
,這個默認值也是‘0’。有兩種用法,一個是在仿真代碼裏寫明什麼情況這個signal置一,比如延時多少之後,或者是某個標誌位變化了之類的。還有一種比較暴力,就是利用ModelSim中signal的Force,覺得仿真了一段時間差不多了,就將該值強制Force爲‘1’,然後文本就關閉了,仿真就結束了。
在write_mode
和append_mode
的時候,要寫入的文本是會自動生成的,不需要事先生成,這樣就比較方便,比如說仿真的時候,把輸出文檔命名成時間,或者是跟更改參數有關的文件名,多仿真幾次之後再去處理這些生成的文本。
要提醒的是,輸入進來的數據和輸出的數據都是二進制數據,所以要先用Matlab或者是Visual Studio等工具先將數據轉換成二進制數據。同理,輸出的數據也要先轉換爲普通數據,才能很好地去觀察其特性。
如何你覺得這個文章對你有幫助,支持一下作者~