Verilog學習筆記

admin @ 2014-03-26 , reply:0

概述
一般認為VerilogHDL在系統級抽象方面比VHDL略差一些,而在門級開關電路描述方面比VHDL要強的多寫了第一個verilog程序,是一個加法器內容如下moduleadder(count,sum,……

一般認為
Verilog HDL在系統級抽象方面比VHDL略差一些,而在門級開關電路描述方面比VHDL要強的多

寫了第一個verilog程序,是一個加法器內容如下
module adder(count,sum,a,b,cin);
input[2:0] a,b;
input cin;
output count;
output [2:0] sum;
assign{count,sum}=a+b+cin;
endmodule

開始編譯出現了幾次錯誤,後來發現給實體的命名和程序中實體要一致而且大小寫要一樣,整個程序是嵌套再module和endmodule當中的

而其中的註釋和C/C++類似,用//和/*…*/來標明

module compare(equal,a,b);
output equal;
input [1:0] a,b;
assign equal=(a==b)?1:0;//和C語言中的相同
endmodule


verilog的基本設計單元是“模塊(BLOCK)”。一個模塊由兩個部分組成,一部分描述埠,一部分描述邏輯功能,即定義輸入是如何影響輸出的。如下
module block(a,b,c,d);
input a,b;
output c,d;

assign c=a|b;
assign d=a&b;
endmodule

模塊中最重要的部分是邏輯功能定義。有三種方法可以再模塊中產生邏輯。
1、用“assign”聲明語句
如:assign a=b&c;
2、用實例元件,如同調入庫元件一樣
如:and and_inst(q,a,b);
3、用“always”塊
如:always @(posedge clk or posedge clr)  //always塊生成了一個帶有非同步清除端的D觸發器。
               begin
                             if(clr) q<=0;
                   else if(en)  q<=d;
     end
採用assign語句是最常用的方法之一。“always”塊可以用於產生各種邏輯,常用於描述時序邏輯。

Verilog HDL中總共有19種數據類型
4 個最基本的數據類型:integer型、parameter型、reg型和wire型。其他的類型有large型、medium型、scalared型、 time型、small型、tri型、trio型、tril型、triand型、trior型、trireg型、vectored型、wand型和wor 型,以後會有介紹。

一、數字
整數
有二、八、十、十六進位
<位寬>’<進位><數字>,這是一種全面的描述方式
預設的位寬由具體的機器系統決定,至少是32位
預設的進位為十進位
x表示不定值,z代表高阻值,z還可以用?代替
4'b10x0 //位寬為4的二進位數從低位數起第二位為不定值
4'b101z //位寬為4的二進位數從低位數起第一位為高阻值
12'dz    //位寬為12的十進位數,其值為高阻值
12'd?    //同上
8'h4x    //位寬為8的十六進位數,其低4位值為不定值
要表示負數的話只需在位寬表達式前加一個減號

4、下劃線(underscore_)
可以用在數字之間提高數字的可讀性如16'b1010_1011_1111_1010

二、參數(parameter)型
即用parameter來定義一個標識符代表一個常量,稱為符號常量,類似於const和define pi一樣。

網路數據類型表示結構實體(例如門)之間的物理連接,不能儲存值,而且必須收到驅動器的驅動,如果沒有驅動則該變數就是高阻的,值為z,常用的網路數據類型包括wire和tri型,wire型變數通常是用來表示單個門驅動或連續賦值語句驅動的網路型數據,tri型變數則用來表示多驅動器驅動的網路型數據
wire[7:0] b;//定義了一個8位的wire型數據

reg型
寄存器是數據存儲單元的抽象,預設初始值為不定值x

memory型
Verilog HDL通過對reg型變數建立數組來對存儲器建模,可以描述RAM,ROM和reg文件。
如reg[7:0] mema[255:0];
定義了一個名為mema的存儲器,有256個8位的寄存器,地址範圍從0到255。
如果想對memory中的存儲單元進行讀寫操作。必須指定該單元在存儲器中的地址。·

2.3  運算符及表達式
(1)算數運算符(+,-,*,/,%);%為模運算,求余運算符
(2)賦值運算符(=,<=);
(3)關係運算符(>,<,>=,<=);
(4)邏輯運算符(&&,||,!);邏輯與,邏輯或,邏輯非
(5)條件運算符(?:);r=s?t:u;如果s為真,則r=t,否則r=u
(6)位運算符(~,|,^,&,^~);~取反,|位或,^按位異或,&按位與,^~按位同或(異或非)
(7)移位運算符(<<左移,>>右移);a>>n,n代表移幾位,都用0來填補移出的空位
(8)拼接運算符({});把多個信號的某些位拼接起來
(9)其他。
單目運算縮減運算,如&b,是將b的每一位相與得出一位的結果

賦值語句和塊語句
信號有兩種賦值方式
1、非阻塞(non_blocking)賦值方式(如b<=a;)b的值不是立刻改變的,等到塊結束后才完成賦值操作
2、阻塞(blocking)賦值方式(如b=a;)b的值立刻改變

順序塊
語句是順序執行的
parameter d=50;
reg[7:0] r;
begin
#d r='h35;
#d r='hE2;
#d r='h00;
#d r='hF7;
#d ->end_wave;
end

用順序塊和延時控制組合來產生一個時序波形

并行塊是語句同時執行的
在并行塊和順序塊中都有一個起始時間和結束時間的概念。對於順序塊,起始時間就是第一條語句開始被執行的時間,結束時間就是最後一條語句執行結束的時間。而對於并行塊來說,起始時間對於塊內所有的語句是相同的,即程序植程式控制制進入該塊的時間,其結束時間是按時間排序在最後的語句執行結束的時間。

if_else語句
case_endcase 語句
(1)case(表達式)<case分支項> endcase
(2)casez(表達式)<case分支項> endcase
(3)casex(表達式)<case分支項> endcase
Verilog HDL 針對電路的持性提供了case語句的其他兩種形式,用來處理caee語句比較過程中的不必考慮的情況(don't care condition)。其中,casez語句用來處理不考慮高阻值z的比較過程,casex語句則將高阻值z和不定值x都視為不必關心的情況。所謂不必關心的情況,即在表達式進行比較時,不將該位的狀態考慮在內。這樣,在case語句表達式進行比較時,就可以靈活地設置以對信號的某些位進行比較。見下面的兩個例子。

2.6  循環語句
有4種類型的循環語句
(1)forever--連續執行的語句,常用於產生周期性的波形,作為模擬測試信號。
(2)repeat--連續執行一條語句n次
(3)while--執行一條語句直到某個條件不滿足
(4)for循環語句,和C/C++中的循環語句類似

2.7  結構說明語句
(1)initial;和always在模擬一開始即開始執行,initial語句只執行一次
(2)always;而always語句則不斷重複執行
(3)task;和function語句可以在程序模塊的一處或多處調用
(4)function;

always #half_period areg=~areg;//這條語句生成了一個周期為2*half_period的無限延續的信號波形。

reg[7:0] counter
reg tick;
always @(posedge areg)
begin
tick=~tick;
counter=counter+1;
end
這種時間控制是always語句最常用的

2.7.3  task和function說明語句
    task 和function說明語句分別用來定義任務和函數。利用任務和函數可以把一個很大的程序模塊分解成許多較小的任務和函數,便於理解和調試。輸入、輸出和匯流排信號的值可以傳入、傳出任務和函數。任務和函數往往還是大的程序模塊中在不同地點多次用到的相同的程序段。學會使用task和function語句可以簡化程序的結構,使程序簡明易懂,是編寫較大型模塊的基本功。

一、task和function說明語句的不同點
任務和函數有些不同,主要表現為以下4點:
(1)函數只能與主模塊共用同一個模擬時間單位,而任務可以定義自己的模擬時間單位。
(2)函數不能啟動任務,而任務能啟動其他任務和函數。
(3)函數至少要有一個輸入變數,而任務可以沒有或有多個任何類型的變數。
(4)函數返回一個值,而任務則不返回值

例:這個例子描述了一個簡單的交通燈的時序控制,並且該交通燈有它自己的時鐘產生器。
module traffic_lights;
reg clock,red,amber,green;
parameter on=1,off=0,red_tics=350,amber_tics=30, green_tics=200;
//initialization
initial red=off;
initial amber=off;
initial green=off;
//clk control
always
begin
red=on;                          //red light on
light(red,red_tics);           //transfer hold mission
green=on;                      //green light on
light(green,green_tics);    //wait for 200 time unit
amber=on;                     //yellow light on
light(amber,amber_tics);   //wait for 30 time unit
end
//define traffic light on mission
task light(color,tics);
output color;
input[31:0] tics;
begin
repeat(tics)@(posedge clock);//use repeat sentence to wait for posedge clock
color=off;                            //turn off the light
end
end task
//generate clock
always
begin
#100 clock=0;
#100 clock=1;
end
end module

三、function說明語句
函數的目的是返回一個用於表達式的值
例子 定義了一個叫factorial的函數,返回一個32位的寄存器類型的值,可後向調用自身,並列印出部分結果值。
module tryfact;
//function define
function[31:0] factorial;             //定義函數名
input[3:0] operand;                    //埠說明
reg[3:0] index;
begin
factorial=operand?1:0;               //語句...
for(index=2;index<=operand;index=index+1)
factorial=index*factorial;
end
endfunction
//function test
reg[31:0] result;
reg[3:0] n;
initial
begin
result=1;
for(n=2;n<=9;n=n+1)
begin
$display("partial result n=%d result=%d",n,result);
result=n*factorial(n)/((n*2)+1);
end
$display("finalresult=%d",result);
end
endmodule

2.8  系統函數和任務
Verilog HDL語言中共有以下一些系統函數和任務:
$bitstoreal, $rtoi,$display,$setup,$finish,$skew,$hold,$setuphold,$itor,$strobe,$ period,$time,$printtimescale,$timefoemat,$realtime,$width,$real tobits,$ write,$recovery.
2.8.1 $display和$write任務
格式:
$display(p1,p2,…,pn);
$write(p1,p2,…,pn);
用來輸出信息,將參數p2~pn按參數p1給定的格式輸出。
$display("d=%0h a=%0h",data,addr);
這樣顯示輸出數據的時候,經過格式轉換以後總是以最少的位數來顯示錶達式的當前值。

2.8.2  系統任務$monitor
格式:
$monitor(p1,p2,…,pn);
$monitor;
$monitoron;
$monitoroff;
具有監控和輸出參數列表中的表達式或變數值的功能。使得每當參數列表中變數或表達式的值發生變化時,整個參數列表中變數或表達式的值都將輸出顯示。
在$monitor中,參數可以是$time系統函數,如下
$monitor($time,,"rxd=%b txd=%b",rxd,txd);
在$display中也可以這樣使用。
$monitoron和$monitoroff這兩個任務的作用是通過打開和關閉監控標誌來控制、監控任務$monitor的啟動和停止,這樣使得程序員可以很容易的控制$monitor何時發生。

2.8.3  時間度量系統函數$time
$time和$realtime,用這兩個時間系統函數可以得到當前的模擬時刻。

cpu

5. 指令寄存器(INSTRUCTION REGISTER)
module register(r,clk,data,ena,rst);
output[7:0] r;
input [7:0] data;
input clk,ena,rst;
wire load;

and a1(load,clk,ena);
DFF d7(r[7],,load,data[7],rst);
DFF d6(r[6],,load,data[6],rst);
DFF d5(r[5],,load,data[5],rst);
DFF d4(r[4],,load,data[4],rst);
DFF d3(r[3],,load,data[3],rst);
DFF d2(r[2],,load,data[2],rst);
DFF d1(r[1],,load,data[1],rst);
DFF d0(r[0],,load,data[0],rst);
endmodule

6. 狀態控制器(STATE CONTROLLER)
`timescale 1ns/1ns
module control(load_acc,mem_rd,mem_wr,inc_pc,load_pc,load_ir,halt,opcode,fetch,zero,clk,clk2,reset);
output load_acc,mem_rd,mem_wr,inc_pc,load_ir,halt;
reg load_acc,mem_rd,mem_wr,inc_pc,load_pc,load_ir,halt;
input[2:0] opcode;
input fetch,zero,clk,clk2,reset;

`define HLT 3'b000
`define SKZ 3'b001
`define ADD 3'b010
`define AND 3'b011
`define XOR 3'b100
`define LDA 3'b101
`define STO 3'b110
`define JMP 3'b111

always @(posedge fetch)
if(reset)
ctl_cycle;

always @(negedge reset)
begin
disable`ctl_cycle;
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt}=7'b0000000;
end

always @(posedge reset)
@(posedge fetch) ctl_cycle;
task ctl_cycle;
begin
//state0 --first address setup
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt}=7'b0000000;
//state1 --instruction fetch
@(posedge clk)
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt}=7'b0000100;
//state2 --instructionload
@(negedge clk)
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt}=7'b0000110;
//state3 --idle
@(posedge clk)
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt}=7'b0000110;
//state4 --second address setup
@(negedge clk)
if(opcode==`HLT)
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt)=7'b1000001;
else
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt)=7'b1000000;
//state5 --operand fetch
@(posedge clk)
if((opcode==`ADD||(opcode==`AND)||(opcode==`XOR)||(opcode==`LDA))
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt)=7'b0000100;
else
{inc_pc,load_acc,load_pc,mem_wr,mem_rd,load_ir,halt)=7'b0000000;
//state5 --operand fetch




[admin via 研發互助社區 ] Verilog學習筆記已經有10802次圍觀

http://cocdig.com/docs/show-post-43515.html