至簡設計法之實用技巧5
來自專欄 FPGA至簡設計法1 人贊了文章
信號命名和定義應該明確
在設計中,我們不斷的給目錄、源代碼、文件、函數、變數、參數、類、封包進行命名與定義。當一件工作需要進行的次數非常之多,足以證明它是不可或缺的基本工作。我們一定要知道一點,基礎工作是整個項目的基石。忽視抑或是輕視基礎工作是一件非常錯誤的工作理念。我們需要用最嚴謹認真的態度去對待,同時作為回報,它將令你的作品顯得專業而優雅。
我們以信號的定義為例來說明這個問題。先來看這麼一組代碼:
官網技巧二別人的代碼。(2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
4344
45
464748
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
assign add_cnt = flag1||flag2 ;
assign end_cnt = add_cnt && cnt==x-1 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
flag1 <= 1b0;
end
else if(en1)begin
flag1 <= 1b1;
end
else if(end_cnt)begin
flag1 <= 1b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
flag2 <= 1b1;
end
else if(en2)begin
flag2 <= 1b1;
end
else if(end_cnt)begin
flag2 <= 1b0;
end
end
always @(*)begin
if(flag1)
x = 5;
else if(flag2)
x = 7;
else begin
x = 0;
end
end
這組代碼的功能是當en1時計數5下;en2計數7下。在這組代碼中,en1時flag1拉高;end-cnt時flag1變低;en2時flag2拉高;end-cnt時flag2變低;也就是在flag1或者flag2時加一,然後用flag1和flag2分別區分計數5下和7下。
儘管能夠實現功能,但是在這組代碼中,存在信號定義不明確得現象。 flag1和flag2到底是什麼意思?是表示flag1(flag2)時en1產生,還是en1(en2)時的計數狀態?為說明這一點就得用到XXXXX (寫加一條件時需要用到add_cnt = flag1||flag2)語句。
這裡重申一下我們很重要的那條簡單原則,一個代碼(信號)只做一件事且做好這件事!按照這個規則,思路就是這樣了:用一個信號flag1來表示計數狀態,另外一個信號flag2表示是由en1還是en2所產生。那麼,加一與否的條件非常簡單,就是是否處於工作狀態(flag1);同理,計數5或者7下只需要使用flag2一個信號。那麼代碼就會是這樣:
官網技巧二我們的代碼。(3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
3839
404142
43
44
45
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
assign add_cnt = flag1 ;
assign end_cnt = add_cnt && cnt==x-1 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
flag1 <= 1b0;
end
else if(en1||en2 )begin
flag1 <= 1b1;
end
else if(end_cnt)begin
flag1 <= 1b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
flag2 <= 1b1;
end
else if(en1)begin
flag2 <= 1b0;
end
else if(en2)begin
flag2 <= 1b1;
end
end
always @(*)begin
if(flag==0)
x = 5;
else
x = 7;
end
看到這裡,也許有些朋友會覺得:好像區別沒那麼大啊?ok,我們假設一下,如果程序中不僅是是en1,en2,而是有en3,en4……enX,又或者將來需要維護和優化,這兩者的區別將會天壤之別。
關於信號定義方面,《至簡設計法》的作者潘文明給出了一個近乎完美的答案。例如在計數器代碼設計中的「架構八步法」,第一步就是明確定義信號,用具體、清晰且無疑異的語句,定義每個信號所要實現的功能,以及重點描述信號的變化情況。如下圖中的信號列表。
信號列表。(4)(用文字版)
信號名
I/O
位寬
說明
clk
I
1
系統工作時鐘
rst_n
I
1
系統複位信號
Din_sop
I
1
當vld=1時才有效,輸入報文頭指示信號
Din_eop
I
1
當vld=1時才有效,輸入報文尾指示信號
Din_vld
I
1
輸入數據有效標誌,高電平有效
Din_err
I
1
輸入報文錯誤標誌,在eop有效時才有效
din
I
8
輸入數據匯流排
Dout_sop
O
1
當vld=1時才有效,輸出報文頭指示信號
Dout_eop
O
1
當vld=1時才有效,輸出報文尾指示信號
Dout_vld
O
1
輸出數據有效標誌,高電平有效
dout
O
8
輸出數據匯流排
Dout_err
O
1
輸出報文錯誤標誌,在eop有效時才有效
可以看出,優秀的FPGA設計師一開始就從頂層結構明確定義信號,將可能出現的混亂從根源上解決。這樣的思路和方法實在非常值得我們每一位從業者學習和借鑒。
推薦閱讀:
TAG:產品設計 | 現場可編輯邏輯門陣列FPGA |