Uploaded by 王聖龍

Verilog學習歷程

Verilog 學習歷程:
28 題:
Xor 可以選擇讓輸入是否要反向耶,B 如果選擇 1,則 A 會被反向,B 選擇 0,A
不變。XOR 可用一個反向器和多工器相替換。
A
B
A,B 的減法可用 A+~B+1 實現。
30 題:
Blocking vs. Non-Blocking Assignment
There are three types of assignments in Verilog:
•
Continuous assignments (assign
x = y;). Can only be used when not inside a
procedure ("always block").
•
•
Procedural blocking assignment: (x
= y;). Can only be used inside a procedure.
Procedural non-blocking assignment: (x <= y;). Can only be used inside a procedure.
32 題:always if2
設計電路時,你必須首先想到在電路方面:
•
我想要這個邏輯門
•
我想要一個具有這些輸入並產生這些輸出的邏輯組合塊
•
我想要一個邏輯組合塊,然後是一組觸發器
你不能做的是先寫代碼,然後希望它生成一個合適的電路。
•
如果(cpu_overheated)那麼 shut_off_computer = 1;
•
If (~arrived) then keep_driving = ~gas_tank_empty
38 題:
& a[3:0]
// AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf)
| b[3:0]
// OR:
b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0)
^ c[2:0]
// XOR: c[2]^c[1]^c[0]
把每個位元抓起來一起做運算,可用上面的方法化簡。
42 題
module top_module(
input [99:0] a, b,
input cin,
output reg [99:0] cout,
output reg [99:0] sum );
always@(*)begin:loop1
integer i;
sum[0] =a[0]^b[0]^cin; cout[0] = a[0]&b[0] | a[0]&cin | b[0]&cin ;
for (i=1;i<100;i=i+1)
sum[i] = a[i]^b[i]^cout[i-1];
end
//有一點在 verilog(硬體)很有趣,上下兩個 always block,他們合成電路後執行是平
行的,簡單來說就是我只是把它們的接線關係描述出來而已,並非像 C 一樣是順
序執行。
always@(*)begin:loop2
integer j;
for (j=1;j<100;j=j+1)
cout[j] = a[j]&b[j] | a[j]&cout[j-1] | b[j]&cout[j-1];
end
endmodule
54 題:
可用 XNOR 來判斷兩數是否相等,例如兩數皆為 4BIT,XNOR 後的結果如果通通為
1,也就是 1111,那麼這兩數相等
55 題:
Task 的使用很像模組?但和模組又有甚麼不同呢?
。
59 題:
module top_module (
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different
);
// Use bitwise operators and part-select to do the entire calculation in one line
of code
// in[3:1] is this vector:
in[3]
in[2]
in[1]
// in[2:0] is this vector:
in[2]
in[1]
in[0]
// Bitwise-OR produces a 3 bit vector.
// Assign this 3-bit result to out_any[3:1]:
|
o_a[3]
|
o_a[2]
|
o_a[1]
// Thus, each output bit is the OR of the input bit and its neighbour to the right:
// e.g., out_any[1] = in[1] | in[0];
// Notice how this works even for long vectors.
assign out_any = in[3:1] | in[2:0];
assign out_both = in[2:0] & in[3:1];//位元對位元直接做檢測,注意是他是用
in[2]&in[3],in[1]&in[2],in[0]&in[1]直接將位置錯開了,挺有趣的可以多想想。
// XOR 'in' with a vector that is 'in' rotated to the right by 1 position: {in[0],
in[3:1]}
// The rotation is accomplished by using part selects[] and the concatenation
operator{}.
assign out_different = in ^ {in[0], in[3:1]};這和上面的一樣把位置錯開後,不一
樣的是 in[3]^in[0],題目有說要做成循環的
endmodule
63 題:
out = '1;//可用 ‘1 表示 out 全部位元都為 1,這樣寫就不用管他幾位元了,假他
16bit,照我之前的寫法我會寫 16’hffff,太慢了。
always @(*) begin
out = '1;
// '1 is a special literal syntax for a number with all bits set to
1.
// '0, 'x, and 'z are also valid.
// I prefer to assign a default value to 'out' instead of
using a
// default case.
case (sel)
4'h0: out = a;
4'h1: out = b;
4'h2: out = c;
4'h3: out = d;
4'h4: out = e;
4'h5: out = f;
4'h6: out = g;
4'h7: out = h;
4'h8: out = i;
endcase
end
endmodule
有設初始條件就不用在 case 裡加入 default 了
64 題:
256 to 1MUX,in 有 256bit =2^m => m=8bit,故選擇線為 8bit
65 題:
當要做位元切片時,Verilog 裡沒有這樣的寫法
out = in[sel*4+3:sel*4];
可改成
assign out = in[sel*4 +: 4];
// 从 sel*4 开始,选择比特序号大于 sel*4 的 4 位比特,相当于
[sel*4+3:sel*4]
assign out = in[sel*4+3 -: 4];
// 从 sel*4+3 开始,选择比特序号小于 sel*4+3 的 4 位比特,相当于
[sel*4+3:sel*4]
注意!!
每次 quatus 跑波型驗證時,只要修改完 code,跑驗證時第一
次都會是上一個 code 的結果,所以要記得跑第二次驗證才知
道 code 有沒有改對。
70 題:
要檢查兩補數有無溢位 ==> 先檢查符號位是否一樣(只有符號一樣的數才有溢
位的情況),在檢查運算結果是否和倆數的符號是否一樣,不一樣就是溢位,ex 兩
個負的加到變正的??太奇怪了一定溢位
71 題:
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum} = a+b+cin;
//超狂寫法,不須注意中間 carry-out 信號,最後一位的 carry-out 信號自動填進 cout
Endmodule
74 題:
注意他的 K-map 的上欄,跟我熟悉的順序不同,但只要相鄰兩項只有一位變化,那
邏輯就相等。
75 題:
看到棋盤 Kmap,就知道是 XOR 系列的,且他是在奇數個 1 才為 1,所以她是 xor。
76 題:
Pos=>關注為 1 的項,把基項 or 起來,每個基項都是各個輸入 and 在一起
Sop=>關注為 0 的項,把基項 and 起來,每個基項都是各個輸入 or 在一起
80 題:
網站提供的解答和我的想法相差蠻多的,值得看。
88 題:
同步 reset(synchronous reset) => 跟著時脈邊緣決定要不要 reset
非同步 reset (asynchronous reset)=> 不跟著時脈即可自行觸發 reset
92 題
訊號中繼站不能算是 in 或 output
z = ~(z1 | z2 | z3);//z 並不是在時脈觸發才會更動值,而是一直在更動,所以她是
個組合邏,不能放在 always block 內
95 題:
判斷倆數是否相等可用 XOR
Always block 裡的敘述到底是順序的還是平行的呢?
Ans:
如果使用
blocking ( = ) 則敘述是會順序執行的,
non-blocking( <= ) 則是平行執行的,會先把右側資料準備好,然後在觸發條件成立
時把敘述內右側的值賦值到左側
奇數除頻器
外加兩個由 clk 的正負緣所產生的 clk,來實現奇數除頻器
原理:假設要做 1/25 的除頻器,
module divn
(
11
input
clk,
12
input
rst_n,
13
output o_clk
14 );
15
16 parameter WIDTH = 3;
17 parameter N
= 6;
18
19 reg [WIDTH-1:0] cnt_p;
20 reg [WIDTH-1:0] cnt_n;
21 reg
clk_p;
22 reg
clk_n;
23
24 assign o_clk = (N == 1) ? clk ://N=1 為不除頻
25
(N[0])
? (clk_p | clk_n) : (clk_p);//N[0]為 1,為奇數,反之為
偶數
26
27 always@(posedge clk or negedge rst_n) begin
28
if (!rst_n)
29
30
cnt_p <= 0;
else if (cnt_p == (N-1))//0~N-1 總長為 N
31
32
cnt_p <= 0;
else
33
cnt_p <= cnt_p + 1;
34 end
35
36 always@(posedge clk or negedge rst_n) begin
37
38
39
if (!rst_n)
clk_p <= 1;
else if (cnt_p < (N>>1))//假如除 25,則 clk_p 為 1 的時間要在 0~12
40
41
clk_p = 1;
else
42
clk_p = 0;
43 end
44
45 always@(negedge clk or negedge rst_n) begin
46
if (!rst_n)
47
48
cnt_n <= 0;
else if (cnt_n == (N-1))
49
50
cnt_n <= 0;
else
51
cnt_n <= cnt_n + 1;
52 end
53
54 always@(negedge clk or negedge rst_n) begin
55
if (!rst_n)
56
57
clk_n <= 1;
else if (cnt_n < (N>>1)) //假如除 25,則 clk_n 為 1 的時間要在 0~12,13+13-1=25(-
1 是因為 clk_n 和 cnt_p 會重疊,所以總共是 25 個 clk)
58
59
clk_n = 1;
else
60
clk_n = 0;
61 end
62
63 endmodule
---------------------------------------------------如果要設計一個數值會循環的功能,可利用%來完成,例如我要讓 X 從 0~9,9 之後再+1 就變 10,這時個位
數可用 x%10 來實現循環的功能
----------------------------------------------------
注意!!input 不能使用 reg 的資料型態!!
做兩次 xor 會是原來的值
---------------------------------mealy 機和 moore 機的差別:
mealy 機的輸出和輸入有關,輸入改變的話輸出也會跟著變(再最後
不用等 clk),而 moore 機輸入不直接和輸出有關係
--------------------------------------狀態機:
n 個狀態要用 x 個暫存器?
Ans:滿足 n≦2^x 的最小整數即可, 假如 n=5,則 x=3
Always@(posedge clk)這個 blk 一定會合出有關 D 型正反器的
東西,這樣想,這個 blk 是在正緣 clk 才會動作,
e.g.
state <= next_state, 不是正緣 clk 時 state 會是甚麼值??
想當然他只能維持之前的值,所以需要一個儲存元件(正反器)
------------------------------------------------狀態機:
要想清楚在某一時刻的 clk 的 state 或 next_state 和其他控制
動作的時序的關係,要想好到底該以 state 還是 next_state 為
sensitivity list