Verilog代碼規范課件_第1頁
Verilog代碼規范課件_第2頁
Verilog代碼規范課件_第3頁
Verilog代碼規范課件_第4頁
Verilog代碼規范課件_第5頁
已閱讀5頁,還剩73頁未讀, 繼續免費閱讀

付費下載

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

2024/1/6第3章Verilog硬件描述語言(三)3.4VerilogHDL行為語句賦值語句順序塊和并行塊語句過程模塊的結構說明語句條件語句循環語句命令語句2024/1/63.4.1賦值語句VerilogHDL常用賦值方式有過程賦值和連續賦值兩種過程賦值語句的更新對象是寄存器,整數,實數等,這些類型變量在被賦值后,可以保持不變,直到賦值進程又被觸發,變量才被賦予新值。連續賦值語句中,任何一個操作數的變化都會重新計算賦值表達式,重新進行賦值。過程賦值阻塞賦值:操作符是用“=”例3-29:always@(posedgeclk)begina=b+1;c=a;end

過程賦值非阻塞賦值:操作符是用“<=”表示例3-30:always@(posedgeclk)begina<=b+1;c<=a;end連續賦值語句連續賦值常用于數據流行為建模。語句格式:assign賦值目標線網=表達式;例3-31:assigna=b|c;assign{c,sum[3:0]}=a[3:0]+b[3:0]+c_in;assignc=max(a,b);說明:(1)式子左邊的“賦值目標線網”只能是線網變量。(2)式子右邊表達式的操作數可以是線網,可以是寄存器,也可以是函數。(3)一旦等式右邊任何一個操作數發生變化,右邊的表達式就會立刻被重新計算,再進行一次新的賦值。(4)assign可以使用條件運算符進行條件判斷后賦值assigndata_out=sel?a:b;過程賦值和連續賦值的區別begin執行語句1;執行語句2;……..end順序塊語句begin塊名塊內變量、參數定義;執行語句1;執行語句2;……..end格式:并行塊格式:fork執行語句1;執行語句2;…joinfork塊名塊內變量、參數定義語句;執行語句1;執行語句2;…join順序塊和并行塊程序執行過程的區別例3-32:并行塊:forks=0;#2s=1;#4s=0;#7s=1;#8s=0;join順序塊:begins=0;#2s=1;#2s=0;#3s=1;#1s=0;end3.4.3結構說明語句1.initial語句語句格式:

initialbegin

語句1;語句2;

…end一個模塊中可以包含多個initial語句,所有的initial語句都同時從0時刻開始并行執行,但是只能執行一次。initial語句常用于測試文本中信號的初始化,生成輸入仿真波形,監測信號變化等。也可以使用fork…join對語句進行組合。例3-33:`timescale1ns/100psreg[1:0]a,b;regc;initialbegina=1;b=0;#10begina=2;b=3;end

#10begina=0;b=2;endendinitialc=1;always語句語句格式:

always@<觸發事件>語句或語句組說明:always的觸發事件可以是控制信號的變化、時鐘邊沿的跳變等。always塊的觸發控制信號可以是一個,也可以是多個,其間用or連接例:always@(posedgeclockorposedgereset)always@(aorborcord)2)只要always的觸發事件產生一次,always就會執行一次。在整個仿真過程中,如果觸發事件不斷產生,則always中的語句將被反復執行例3-34:regq;always@(posedgeclock)q<=d;

一個模塊中可以有多個always語句,每個always語句的執行時間各個always語句書寫的前后順序無關例:always@(posedgeclk)if(rst)counter<=4'b0000;elsecounter<=counter+1always@(counter) $display("thecounteris=%d",counter);

練習:分別用assign,always語句實現模塊模塊名:my_module輸入信號:位寬:1bit信號名:data_in1,data_in2,data_in3輸出信號:位寬3bits

信號名:data_out功能描述:data_out[2]=data_in1&data_in2data_out[1:0]=data_in1+data_in2+data_in32024/1/6任務(task)語句格式:task任務名;<輸入輸出端口聲明>;

<任務中數據類型聲明>;語句1;語句2;…endtask1)任務定義在關鍵字“task”和“endtask”之間2)任務調用與變量的傳遞,輸入和輸出是局部寄存器,執行完返回結果。格式:任務名(端口1,端口2,…,端口n)3)當任務被調用時,任務被激活。同時一個任務可以調用別的任務或函數moduletop;……..//例化一個fifofifoctlr_ccu1(.clock_in(clockin),.write_enable(write_enable),write_data(write_data),read_enable(read_enable).……);taskwriteburst;input[7:0]wdata;

beginalways@(posedgeclockin)beginwrite_enable=#21;

write_data=#2wdata;

endendendtaskinitialbeginwriteburst(128);…..endendmodule4)任務也可以沒有參數的輸入,只執行操作例3-37:將輸入信號的與和或的結果分別輸出moduleresult(data_in1,data_in2,data_out1,data_out2);….regdata_out1,data_out2;taskexample;//定義任務examplebegindata_out1<=data_in1&data_in2; data_out2<=data_in1|data_in2; end endtaskalways@(data_in1ordata_in2)example;endmodule

moduleoperation;…parameterdelay=10;reg[15:0]A,B;reg[15:0]AB_AND,AB_OR,AB_XOR;always@(AorB)beginbitwise_oper(AB_AND,AB_OR,AB_XOR,A,B);endtaskbitwise_oper;output[15:0]ab_and,ab_or,ab_xor;input[15:0]a,b;begin#delayab_and=a&b;ab_or=a|b;ab_xor=a^b;endendtaskendmodule函數(function)語句格式:function<返回值的位寬、類型說明>函數名;<輸入端口與類型說明>;<局部變量說明>;begin語句;endendfunction 1)函數定義在關鍵字“function.”和“endfunction”之間,函數的目的是返回一個用于表達式的值例3-38:function[3:0]max; input[3:0]a,b;beginif(a>b)max=a;elsemax=b;endendfunction函數的定義使得在模塊中定義了一個和函數同名,位寬相同的寄存器類型變量2)函數的調用是用和函數同名的寄存器變量作為表達式的操作數來進行,并根據函數輸入數據的要求,攜帶、傳送數據。例:調用前述定義的max函數

c=max(10,5);3.4.4條件語句if語句1格式:(1)if(表達式)<語句>;(2)if(表達式)<語句1>;else<語句2>;(3)if(表達式1)<語句1>;elseif(表達式2)<語句2>;……elseif(表達式n)<語句n>;else<語句n+1>;if后面的表達式,可以是邏輯表達式、關系表達式還可以是操作數。如if(a)等價于if(a==1)如果if和else后有多個執行語句,可以用begin…end塊將其整合在一起例3-39:if(a>b)begindata_out1<=a;data_out2<=b;endelsebegindata_out1<=b;data_out2<=a;end

if語句嵌套使用時,else與最近的if語句配對例3-40:if(a>b)if(c)data_out<=c+1;

elsedata_out<=a+1;elsedata_out<=b;如果不正確使用else,可能會生成不需要的鎖存器。例3-41:always@(aorb)beginif(a)data_out<=a;endif-else表達了一個條件選擇的設計意圖,它與條件運算符有重要的區別條件運算符可以出現在一個表達式中。if-else只能出現在always,initial塊語句,或函數、任務中,一般只能在行為建模中使用。課堂練習設計四位計數器(使用always,if-else語句)輸入:CLK,RST,ENA輸出:Q(位寬4bits)功能描述:當RST有效(等于1)時,輸出置零;ENA有效RS無效時,將對CLK的輸入個數進行計數2024/1/6課堂練習moduleCNT4B(CLK,RST,ENA,OUTY,COUT); inputCLK,RST,ENA; output[3:0]Q; reg[3:0]Q; regCOUT;

always@(posedgeCLKornegedgeRST) begin if(RST) begin Q<=4'b0000; end else if(ENA) begin Q<=Q+1; end endendmodule2024/1/6case語句如果選項數目很多,用if-else-if會不方便,可使用case語句。語句格式:case(控制表達式)分支表達式1:語句1;…分支表達式n:語句n;default:默認語句;endcase例3-42:用case語句實現四選一電路modulemux4(clk,rst,data_in1,data_in2,data_in3,data_in4,select,data_out);input[3:0]data_in1,data_in2,data_in3,data_in4;input[1:0]select;inputclk,rst;output[3:0]data_out;reg[3:0]data_out;always@(posedgeclk)if(rst)data_out<=4'b0000;else case(select) 2'b00:data_out<=data_in1;

2‘b01:data_out<=data_in2;2'b10:data_out<=data_in3;

2'b11:data_out<=data_in4;

default:$display("thecontrolsignalisinvalid"); endcaseendmodule如果多個不同的狀態值有相同的執行語句,可以用逗號將各個狀態隔開。例3-43:case(select) 2'b00:data_out<=data_in1; 2'b01:data_out<=data_in2;2'b10:data_out<=data_in3; 2'b11:data_out<=data_in4;2'b0x,2'bx0,2'b1x,2'bx1,2'bxx:data_out<=4'bxxxx;2'b0z,2'bz0,2'b1z,2'bz1,2'bzz:data_out<=4'bzzzz;default:$display("thecontrolsignalisinvalid");endcase建議在case語句中最好加入default分支3.4.5循環語句循環語句只能在initial,always塊中使用。下面介紹常用的循環句:for、forever、repeat和while2024/1/6for語句語句格式:for(表達式1;表達式2;表達式3)語句;2024/1/6初始條件表達式循環終止條件改變循環控制變量的賦值語句語句執行過程例3-44:用for語句對存儲器組進行初始化。reg[7:0]my_memory[511:0];integeri;initialbeginfor(i=0;i<512;i=i+1)my_memory[i]<=8’b0;end2024/1/6例:initialbeginfor(i=0;i<32;i=i+2)stage[i]=0;for(i=1;i<32;i=i+2)state[i]=1;end2024/1/6實現了:所有偶元素初始化為0所有奇元素初始化為1for循環一般用于具有固定開始和結束條件的循環,如果只有一個執行循環的條件,最好還是用while循環2024/1/6while語句語句格式:

while(條件表達式)

語句

語句執行過程

先求解條件表達式的值,如果值為真(等于1),執行內嵌的執行語句(組),否則結束循環。

如果一開始就不滿足條件表達式,則循環不執行。2024/1/6例3-45:用while語句求從1加到100的值,加法完成后打印結果modulecount(clk,data_out);inputclk;output[12:0]data_out;reg[12:0]data_out;integerj;initial//data_out和j賦初值為0begindata_out=0;j=0;endalways@(posedgeclk)beginwhile(j<=100)begindata_out=data_out+j; j=j+1; end$display("thesumis%d,j=%d",data_out,j);endendmodule語句格式:forever

語句;

表示永久循環,無條件地無限次執行其后的語句,相當于while(1),直到遇到系統任務$finish或$stop不能獨立寫在程序中,必須寫在initial結構中。2024/1/6forever語句

例3-46:使用forever語句生成一個周期為20個時間單位的時鐘信號。regclock;initialbeginclock=0;forever#10clock=~clock;end2024/1/6repeat語句語句格式:

repeat(表達式)

語句

repeat語句執行其表達式所確定的固定次數的循環操作。

其表達式通常是常數,也可以是一個變量,或者一個信號,如果是變量或者信號,循環次數是循環開始時刻變量或信號的值,而不是循環執行期間的值2024/1/6modulemux(data_in1,data_in2,data_out);input[3:0]data_in1,data_in2;output[7:0]data_out;reg[7:0]data_out;reg[7:0]data_in1_shift,data_in2_shift;initialbegindata_in1_shift=data_in1;data_in2_shift=data_in2;data_out=0;repeat(4)beginif(data_in2_shift[0])data_out=data_out+data_in1_shift; data_in1_shift=data_in1_shift<<1;data_in2_shift=data_in2_shift>>1; endendendmodule系統任務和系統函數$<標識符>‘$’

符號表示Verilog的系統任務和函數常用的系統任務和函數有下面幾種:$time//找到當前的仿真時間$display,$monitor//顯示和監視信號值的變化$stop//暫停仿真$finish//結束仿真$readmemb和$readmemh/*將文件中的數據讀到存儲器陣列中*/$fopen和$fclose2024/1/6$display用于變量,字符串,表達式的屏幕顯示,格式:$display(p1,p2,…pn);表3.8,表3.92024/1/6例3-48:$display("TESTEDCOMPLETEPNSEQUENCErollingovertotestagain.");顯示結果:TESTEDCOMPLETEPNSEQUENCErollingovertotestagain.$display("a=%d,b=%2.2f”,a,b);//數值的顯示,設a=5,b=2.345顯示結果:a=5,b=2.35$display(“hello\nworld);//特殊字符的顯示顯示結果:helloworld2024/1/6$monitor函數提供了對信號變化進行監控的功能,格式:$monitor(p1,p2…..pn);p1,p2….pn可以是字符串,變量,表達式,時間函數$time等。2024/1/6在整個仿真過程中,在任意一個時刻,只要監測的一個或多個變量發生變化時,就會啟動$monitor函數,輸出這一時刻的數值情況。例:

initial$monitor($time,”a=%b,b=%h”,a,b);/*每當a或b值變化時該系統任務都顯示當前的仿真時刻并分別用二進制和十六進制顯示信號a和b的值*/2024/1/6說明:

說明:$monitor函數一般書寫在initial塊中,即,只需調用一次$monitor函數,在整個仿真過程中都有效,這與$display不同。在仿真過程中,若在源程序中調用了多個$monitor函數,只有最后一個調用有效。Verilog語言提供了兩個用于控制監控函數的系統任務$monitoron,$monitoroff,$monitoron用于啟動監控任務,$monitoroff用于關閉監控任務。2024/1/6$stop和$finish$stop暫停仿真,進入交互模式,將控制權交給用戶;$finish結束仿真過程,返回主操作系統2024/1/6例3-49initialbegin#100begina=1;b=1;end#100$stop;//在200ns暫停仿真,交由用戶控制#200$finish;//在400ns時,退出仿真end2024/1/6$readmemb和$readmemh格式:$readmemb(“文件名”,存儲器名,起始地址,終止地址);$readmemh(“文件名”,存儲器名,起始地址,終止地址);2024/1/6moduletest();reg[1:0]my_mem[7:0];integeri;initialbegin$readmemb("D:/test/my_data.dat",my_mem);for(i=0;i<8;i=i+1)$display("my_mem[%d]=%b",i,my_mem[i]); endendmodule//定義了8個寬度為2位存儲器組//將位于D:/test目錄下的my_data.dat中的數據讀入my_mem中其中my_data.dat如下內容:000110110001 10112024/1/6執行結果如下:memory[0]=00memory[1]=01memory[2]=10memory[3]=11memory[4]=00memory[5]=01memory[6]=10memory[7]=11數據文件中可以用@<地址>將數據存入存儲器的指定位置,地址用十六進制數表示,@和<地址>間不能有空格。例:@10000@61xz1

執行結果如下:my_mem[0]=xxmy_mem[1]=00my_mem[2]=00my_mem[3]=xxmy_mem[4]=xxmy_mem[5]=xxmy_mem[6]=1xmy_mem[7]=z1語句中的起始地址和終止地址的不同定義對數據裝載有影響例:initial$readmemh(“mem.data”,mem);initial$readmemh(“mem.data”,mem,16);2024/1/6

$fopen和$fcloseVerilog語言支持將仿真結果輸出到指定的文件中,使用系統函數$fopen打開一個可以寫入數據的文件;再使用系統任務$fclose將前面打開的文件關閉。格式:

<file_descriptor>=$fopen(“文件名”);2024/1/63.4.7編譯預處理命令在進行Verilog語言綜合時,綜合工具首先對這些編譯預處理命令進行“預處理”,然后將得到的結果和源程序一起再進行通常的編譯處理。編譯預處理指令前有一個標志符“`”(反引號)加以確認。其作用范圍是:命令定義后直到本文件結束或其他命令替代或取消該命令為止。2024/1/6宏定義命令`define宏定義`define指定一個宏名來代表一個字符串。語句格式:`define宏名字符串2024/1/6說明為與變量名區別,建議使用大寫字符定義宏名。在源文件中引用已定義的宏名時,必須在宏名前加“`”。例:`defineADDa+b//用a+b表示ADD字符串assignc=`ADD;2024/1/6宏定義可嵌套使用。例:

`defineADD1a+b`defineADD2`ADD1+dassigndata_out=`ADD2;2024/1/6//等同于data_out=a+b+d;條件編譯命令`ifdef、`elsif、`else和`endif應用場合:在一些特定的情況下,對源程序中滿足指定編譯條件的語句才進行編譯,或者滿足某條件時,對一組語句進行編譯,否則編譯另一組語句。一般有以下幾種情況:1)選擇模塊的不同代表部分2)選擇不同的時序或結構信息3)對不同的EDA工具,選擇不同的激勵。2024/1/6格式格式1:`ifdef宏名(標識符)程序段1`else程序段2`endif2024/1/6格式2:`ifdef宏名(標識符)程序段1`endif文件

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論