“本文主要分享了在Verilog設計過程中一些經驗與知識點,主要包括Verilog仿真時常用的系統任務、雙向端口的使用(inout)、邊沿檢測”
01
—
仿真時常用的系統任務($display,$fopen,$fscanf,$fwrite($fdisplay),$fclose,$random,$stop)
在RTL設計過程中,仿真的時候需要用一些系統函數,這邊筆整理了部分Verilog設計中常用的系統函數:$display,$fopen,$fscanf,$fwrite($fdisplay),$fclose,$random,$stop。
-
$display
這個函數系統任務的作用是用來在控制臺輸出信息。
-
$display("!!! Start Simulation !!!");直接顯示字符串
-
$display("data_display = %h hex %d decimal",100, 100); //顯示data_display 的16進制 ,10進制
-
$display("data_display = %o otal %b binary",100, 100);//顯示data_display 的8進制 2進制
-
$display("data_display = %d otal next line %bbinary", 100, 100);//主要展示換行操作
-
$display("simulation time is %t",$time);//顯示系統仿真時間
具體代碼如下:
regflag;
//****************************** 系統顯示 $display *******************************
reg[31:0]data_display;
initial
begin
data_display = 32'd100;
flag = 0;
$display("!!! Start Simulation !!!");
//顯示16進制 10進制
$display("data_display = %h hex %d decimal", 100, 100);
//顯示8進制 2進制
$display("data_display = %o otal %b binary", 100, 100);
//ASCII碼
$display("data_display has %c ascii character value",64);
//顯示10進制 換行 2進制
$display("data_display = %d otal next line %b binary", 100, 100);
//顯示系統仿真時間
$display("simulation time is %t",$time);
flag = 1;
end
仿真結果如下圖所示:
在第五行展示了換行功能;為了驗證系統仿真時間,筆者這邊用flag參數拉高來測試時間,時間結果如下圖顯示,和顯示時間一致;
-
$fopen
-
$fscanf
//****************************** 讀文件 $fscanf *******************************
//宏定義,定義數據長度
`define DATA_LENGTH 8
//定義RAM大小
reg signed [15:0] Sig0 [`DATA_LENGTH-1:0];
reg [15:0]Sig1[`DATA_LENGTH-1:0];
//定義句柄
integer data_file0;
integerdata_file1;
integeri;
//讀取函數
initial
begin
#200;
//打開句柄
data_file0 = $fopen("file/rd_data0_fpga.txt","r");
data_file1 = $fopen("file/rd_data1_fpga.txt","r");
for(i = 0;i < `DATA_LENGTH; i = i + 1)
begin
$fscanf(data_file0,"%d",Sig0[i]); //讀取十進制
$fscanf(data_file1,"%h",Sig1[i]); //讀取十六進制
end
$fclose(data_file0); ////關閉這個句柄
$fclose(data_file1); ////關閉這個句柄
end
仿真結果如下圖所示:
-
$fwrite($fdisplay)
代碼如下所示:
仿真結果如下所示//************************** 寫文件 $fwrite($fdisplay) *************************
//****** $fwrite 寫下一個數不會自動轉行,所以要加
//將讀取的Sig0,Sig1重新寫進兩個新的txt中
//定義句柄
integer data_wr0;
integer data_wr1;
integer m;
//讀取函數
initial
begin
#400;
//打開句柄
data_wr0 = $fopen("file/wr_data1_fpga.txt","w");
data_wr1=$fopen("file/wr_data2_fpga.txt","w");
for(m = 0;m < `DATA_LENGTH; m = m + 1)
begin
@(clk);
$fwrite(data_wr0,"%d ",Sig0[m]); //向txt寫十進制 寫下一個數不會自動轉行,所以要加
$fwrite(data_wr1,"%h ",Sig1[m]); //向txt寫十六進制 寫下一個數不會自動轉行,所以要加
end
//關閉這個句柄
$fclose(data_wr0);
$fclose(data_wr1);
end
$fwrite和$fdisplay的區別,$fwrite寫下一個數不會自動轉行,可以加 來轉行,$fdisplay則會自動轉行。
-
$fdisplay
仿真結果如下圖所示://****** $fdisplay
//將讀取的Sig0,Sig1重新寫進兩個新的txt中
//定義句柄
integer data_wr2;
integer data_wr3;
integer j;
//讀取函數
initial
begin
#600;
//打開句柄
data_wr2 = $fopen("file/wr_data3_fpga.txt","w");
data_wr3=$fopen("file/wr_data4_fpga.txt","w");
for(j = 0;j < `DATA_LENGTH; j = j + 1)
begin
@(clk);
$fdisplay(data_wr2,"%d",Sig0[j]); //向txt寫十進制 寫下一個數會自動轉行,所以不需要加
$fdisplay(data_wr3,"%h",Sig1[j]); //向txt寫十六進制 寫下一個數會自動轉行,所以不需要加
end
//關閉這個句柄
$fclose(data_wr2);
$fclose(data_wr3);
end
-
$fclose
-
$stop
02
—
雙向端口的使用(inout)
根據Verilog的語法定義,IO的端口可以定義為三種類型input、output和inout,其中inout為雙向端口。雙向端口通過控制三態門來實現,其結構框圖如下所示。
-
當T為1的時候,I端忽略(高阻),O端電平 = IO端電平;
-
當T為0的時候,IO端電平=I端電平=O端電平;
同樣,Xilinx也有三態門的源語assign io = ( !t ) ? i : 1'bz ;
assign o = io;
參考:Xilinx 7 Series FPGA Libraries Guide for HDL Design
仿真結果如下:IOBUF
.DRIVE ( 12 ), // Specify the output drive strength
.IBUF_LOW_PWR ( "TRUE" ), // Low Power - "TRUE", High Performance = "FALSE"
.IOSTANDARD ( "DEFAULT" ), // Specify the I/O standard
.SLEW ( "SLOW" ) // Specify the output slew rate
) IOBUF_inst (
.O(o1 ),//Bufferoutput
.IO(io),//Bufferinoutport(connectdirectlytotop-levelport)
.I(i1),//Bufferinput
.T ( t ) // 3-state enable input, high=input, low=output
);
可以看出:
-
當T=1的時候,O端電平=IO端電平;
-
當T=0的時候,O端電平=IO端電平=I端電平。
03
—
邊沿檢測
在程序設計過程中,經常需要檢測一個脈沖信號的上升沿或者下降沿,下面給大家介紹如何使用Verilog實現對脈沖信號的邊沿進行檢測。時鐘信號與脈沖信號如下圖所示。
Verilog代碼如下:
上述程序經過綜合后,其RTL結構如下圖所示,由兩個D觸發器和兩個與門組成。module edge_detection(
input wire clk,
input wire rst,
input wire sin_pulse,
output wire sout_r, //上升沿檢測
output wire sout_f //下降沿檢測
);
//--------------------------------------------------------------------------------
reg sin_reg0,sin_reg1;
//--------------------------------------------------------------------------------
clk or posedge rst)
begin
if(rst)
begin
sin_reg0 <= 0;
sin_reg1 <= 0;
end
else
begin
sin_reg0 <= sin_pulse;
sin_reg1 <= sin_reg0;
end
end
//--------------------------------------------------------------------------------
assign sout_r = sin_reg0 & (~sin_reg1); //上升沿檢測
(~sin_reg0)&sin_reg1;//下降沿檢測 =
//--------------------------------------------------------------------------------
仿真后的結果如下圖所示,可以看出sout_r為上升沿檢測結果,sout_f為下降沿檢測結果。
審核編輯:郭婷
-
Verilog
+關注
關注
28文章
1360瀏覽量
111191 -
代碼
+關注
關注
30文章
4866瀏覽量
69816
原文標題:Verilog基礎知識學習筆記(一)
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
關于FPGA進行外部邊沿檢測,檢測不準確問題?
邊沿檢測的目的及電路原理分析
Verilog HDL語言中任務與函數的比較
剖析verilog2005的騷操作之對數函數

評論