Verilog小總結
基礎
assign
assign作為一個組合邏輯常用的陳述句,可認為是將電線連接起來,當然它能做的不僅僅是將一個輸入直接輸出,它能把輸入信號進行邏輯運算后再輸出,當assign左右兩邊位寬不相等時,將自動進行零擴展或截斷以匹配左邊的位寬,
eg:
module top_module (
input a,
input b,
input c,
input d,
output out,
output out_n );
wire w1, w2; // Declare two wires (named w1 and w2)
assign w1 = a&b; // First AND gate
assign w2 = c&d; // Second AND gate
assign out = w1|w2; // OR gate: Feeds both 'out' and the NOT gate
assign out_n = ~out; // NOT gate
endmodule
Vectors
宣告向量
type [upper:lower] vector_name;
type
指定向量的資料型別,通常是wire
或reg
,如果要宣告輸入或輸出埠,則該型別還可以另外包括埠型別(例如,input
或output
)
wire [7:0] w; // 8-bit wire
reg [4:1] x; // 4-bit reg
output reg [0:0] y; // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z; // 6-bit wire input (negative ranges are allowed)
output [3:0] a; // 4-bit output wire. Type is 'wire' unless specified otherwise.
wire [0:7] b; // 8-bit wire where b[0] is the most-significant bit.
部分選擇
使用向量名稱訪問整個向量,但是當assign左右兩邊位寬不相等時,將自動進行零擴展或截斷以匹配左邊的位寬,
使用vector_name[up:low]
的形式獲取部分向量,注意方向應與定義的一致,如定義了一個a[3:0]
,那么不能反向獲取a[0:3]
,
矢量運算
- 位運算
符號 | 功能 |
---|---|
~ |
按位取反 |
& |
按位與 |
| |
按位或 |
^ |
按位異或 |
^~ |
按位同或 |
注意:除了~
外均為雙目運算子;若進行雙目運算時左右兩個運算元位數不一樣,位數少的將在相應的高位用0擴展,
- 邏輯運算
邏輯運算會將整個向量視為布林值(真=非零,假=零),并且產生1位輸出,如有input [2:0] a
和input [2:0] b
那么他們的邏輯或運算即為assign out = a || b;
,a和b均視為一個布林值,
- 縮減運算
對一個向量的每一位進行位操作,如有a[2:0]
,那么b=&a
相當于b=(a[0]&a[1])&a[2]
矢量串聯
串聯運算子{a,b,c}
用來將小向量串聯起來創建一個更大的向量,串聯中不允許使用不定尺寸的常量,如{1,2,3}
是非法的,因為Verilog不知道他們的位寬,
還可以用{n{vec}}
的形式來復制向量,如{6{a}}
和{a,a,a,a,a,a}
是一樣的,同時注意兩組大括號都是必須的,即{1'b1,6{1'b0}}
是非法的,因為其中的6{1'b0}
少了一組大括號,正確的寫法是{1'b1,{6{1'b0}}}
,這其實比較好理解,串聯運算子{a,b,c}
中的abc均為一個向量,{n{vec}}
也代表了一個向量,因此{a,b,{n{c}}}
也是一個向量
模塊
mod_name instance_name (signal_name1,signal_name2,signal_name3);//by position
mod_name instance_name (.port_name1(signal_name1),.port_name2(signal_name2),.port_name3(signal_name3));//by name
可以理解為一個函式,注意括號內的是外部連接到模塊的信號,
always塊
組合邏輯
使用always @(*)
可以類似于assign
的效果,當右方有變數發生改變時,左邊輸出隨之立即改變,assign out1 = a & b | c ^ d;
和always @(*) out2 = a & b | c ^ d;
是一樣的
時序邏輯
- 同步與異步復位
//同步復位
always @(posedge clk) begin
if(reset == 1) begin
//reset
end
end
//異步復位
always @(posedge clk,posedge areset) begin
if(areset == 1) begin
//reset
end
end
- 阻塞賦值非阻塞賦值
一般來說,我們在組合邏輯的always塊中使用阻塞賦值(x = y;
);在時序邏輯的always塊中使用非阻塞賦值(x <= y;
)
case
always @(*) begin //這是一個組合邏輯
case (in)
1'b1: begin
out = 1'b1;
end
1'b0: out = 1'b0;
default: out = 1'bx;
endcase //一定記得寫endcase
end
注意一定要寫endcase,
另外還有case的好兄弟casez,他可以匹配形如4'bzzz1
的向量,z表示無關位,
eg:優先編碼器
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez (in)
8'bzzzzzzz1 : pos = 0;
8'bzzzzzz1z : pos = 1;
8'bzzzzz1zz : pos = 2;
8'bzzzz1zzz : pos = 3;
8'bzzz1zzzz : pos = 4;
8'bzz1zzzzz : pos = 5;
8'bz1zzzzzz : pos = 6;
8'b1zzzzzzz : pos = 7;
default: pos =0;
endcase
end
endmodule
for
組合for回圈
與C語言的用法類似,
eg:人口計數器
module top_module (
input [254:0] in,
output reg [7:0] out
);
always @(*) begin //組合邏輯always塊
out = 0; //一定要初始化為0
for (int i=0;i<255;i++)
out = out + in[i];
end
endmodule
生成for回圈
當對矢量中多個位進行重復操作時,或進行多個模塊的實體化參考的重復操作時,可使用生成塊簡化程式,寫法如下
genvar i;//只能用genvar作為回圈變數
generate
for (i=1;i<99;i=i+1) begin: add_loop//這個名字是必須的
mod_name instance_name(......);//括號里寫由i推出的信號
end
endgenerate
eg:Bcdadd100
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
genvar i;
wire [99:0]cout1;
bcd_fadd mod1(a[3:0],b[3:0],cin,cout1[0],sum[3:0]);
generate
for (i=1;i<99;i=i+1) begin: addloop
bcd_fadd mod2(a[(4*i+3):(4*i)],b[(4*i+3):(4*i)],cout1[i-1],cout1[i],sum[(4*i+3):(4*i)]);
end
endgenerate
bcd_fadd mod3(a[399:396],b[399:396],cout1[98],cout,sum[399:396]);
endmodule
狀態機寫法
Moore型
三段式寫法:使用一個state用于存當前狀態,使用一個next_state用于存下一狀態,第一段用于寫狀態轉換邏輯,第二段用于狀態轉移,第三段用于輸出,
reg state, next_state;
//第一段:
always @(*) begin //一個組合邏輯always塊,用于寫狀態轉換邏輯,當in改變時,next_state將立即改變,
case(state)
A: next_state = f(in)//關于in的函式
B: next_state = f(in)
...
endcase
end
//第二段(異步):
always @(posedge clk, posedge areset) begin
if(areset == 1) begin
state <= 0;//reset
end
else state <= next_state;
end
//第二段(同步):
always @(posedge clk) begin
if(reset == 1) begin
state <= 0;//reset
end
else state <= next_state;
end
//第三段(assign法)
assign out = (state == ...);//判斷state
//第三段(組合邏輯always塊法)
always@(*) begin
case (state)
A: {out3,out2,out1} = 3'b111;
B: {out3,out2,out1} = 3'b110;//對每一種狀態輸出
...
endcase
end
Mealy型
僅僅第三段發生了改變,可使用{state,in}
來做輸出判斷,
//第三段(assign法)
assign out = f(state,in);//關于state和in的函式
//第三段(組合邏輯always塊法)
always@(*) begin
case ({state,in})
4'b0000: {out3,out2,out1} = 3'b111;
4'b0001: {out3,out2,out1} = 3'b110;//對每一種state與in做輸出
...
end
(希望明天P1能過嗚嗚嗚
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/205064.html
標籤:其他