對於發展商而言,動土儀式無疑是最重要的任務。爲此,流水燈實驗做爲低級建模II的動土儀式再適合不過了。廢話少說,咱們仍是開始實驗吧。css
圖1.1 實驗一建模圖。html
如圖1.1 所示,實驗一有名爲 led_funcmod的功能模塊。若是無視環境信號(時鐘信號還有復位信號),該功能模塊只有一組輸出端,亦即4位LED信號。接下來讓咱們來看具體內容:學習
1. module led_funcmod
2. (
3. input CLOCK, RESET,
4. output [3:0]LED
5. );
以上內容爲出入端聲明。spa
6. parameter T1S = 26'd50_000_000; //1Hz
7. parameter T100MS = 26'd5_000_000; //10Hz
8. parameter T10MS = 26'd500_000; //100Hz
9. parameter T1MS = 26'd50_000; //1000Hz
10.
以上內容爲常量聲明。分別是1秒至1毫秒。code
11. reg [3:0]i;
12. reg [25:0]C1;
13. reg [3:0]D;
14. reg [25:0]T;
15. reg [3:0]isTag;
16.
17. always @ ( posedge CLOCK or negedge RESET )
18. if( !RESET )
19. begin
20. i <= 4'd0;
21. C1 <= 26'd0;
22. D <= 4'b0001;
23. T <= T1S;
24. isTag <= 4'b0001;
25. end
26. else
以上內容是相關的寄存器聲明以及復位操做。寄存器i用來指向步驟,寄存器C1用來計數,寄存器D用來暫存結果和驅動輸出,寄存器T用來暫存計數量,isTag則用來暫存延遲標籤。htm
27. case( i )
28.
29. 0:
30. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
31. else begin C1 <= C1 + 1'b1; D <= 4'b0001; end
32.
33. 1:
34. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
35. else begin C1 <= C1 + 1'b1; D <= 4'b0010; end
36.
37. 2:
38. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
39. else begin C1 <= C1 + 1'b1; D <= 4'b0100; end
40.
41. 3:
42. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
43. else begin C1 <= C1 + 1'b1; D <= 4'b1000; end
44.
45. 4:
46. begin isTag <= { isTag[2:0], isTag[3] }; i <= i + 1'b1; end
47.
48. 5:
49. if( isTag[0] ) begin T <= T1S; i <= 4'd0; end
50. else if( isTag[1] ) begin T <= T100MS; i <= 4'd0; end
51. else if( isTag[2] ) begin T <= T10MS; i <= 4'd0; end
52. else if( isTag[3] ) begin T <= T1MS; i <= 4'd0; end
53.
54. endcase
55.
56. assign LED = D;
57.
58. endmodule
以上內容爲是核心操做以及輸出驅動聲明。步驟0~3用來實現流水燈效果。最初,每一個步驟的停留時間是 1秒,而後步驟0~3按順序執行便會產生流水效果。步驟4是用來切換模式,步驟5則是根據isTag的內容再爲 T寄存器載入不一樣的延遲內容,如 [0] 延遲1秒,[1] 延遲100毫妙,[2] 延遲10毫妙,[3] 延遲1毫妙。默認下爲模式0(第24行),既延遲1秒(第23行)。blog
這個實驗所在意的內容根本不是實驗結果而是低級建模II自己。倘若比較《建模篇》的流水實驗,低級建模I與低級建模II之間是有明顯的差距。首先,低級建模II不再見計數器或者定時器等周邊操做。再者,低級建模II的整合度很高,例如步驟0~3:ip
1. 0:
2. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
3. else begin C1 <= C1 + 1'b1; D <= 4'b0001; end
4. 1:
5. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
6. else begin C1 <= C1 + 1'b1; D<= 4'b0010; end
7. 2:
8. if( C1 ==T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
9. else begin C1 <= C1 + 1'b1; D <= 4'b0100; end
10. 3:
11. if( C1 == T -1) begin C1 <= 26'd0; i <= i + 1'b1; end
12. else begin C1 <= C1 + 1'b1; D <= 4'b1000; end
代碼1.1rem
內容如代碼1.1所示,步驟0~3每一個步驟示意一段完整的小操做,例如步驟0爲4’b0001保持一段時間,步驟1爲4’b0010保持一段時間,步驟2~3也是如此。其中 -1也考慮了步驟切換的時間。假設流水間隔要求1毫妙,那麼每一個步驟都會準確無誤停留50000個時鐘。事實上,步驟0也能夠換成比較方便的寫法,如代碼1.2所示:rpc
1. reg [3:0] D = 4’b0001;
2. ......
3. 0,1,2,3:
4. if( C1 == T -1) begin D <= { D[2:0], D[3] }; C1 <= 26'd0; i <= i + 1'b1; end
5. else begin C1 <= C1 + 1'b1; end
代碼1.2
代碼1.2表示,只要寄存器D準備好初值,例如 4’b0001,那麼步驟0~3均可以共享一樣的操做,如此一來會大大減小行數,節省空間。好奇的同窗必定以爲疑惑,既然代碼1.2的寫法那麼方便,反之筆者爲什麼要選擇代碼1.1的寫法呢?緣由很單純,那是爲了清晰模塊內容,以至咱們容易腦補時序。感受上,二者雖然都差很少,可是咱們只要仔看,咱們便會發現 ... 代碼1.2它雖然書寫方便,但是細節模糊並且內容也不直觀。
在此,筆者須要強調!低級建模II雖然有整合技巧讓操做變得更加便捷,不過比起整合它更加註重表達能力以及清晰度。這樣作的關鍵是爲了發揮主動思想,以便擺脫無謂的仿真。因此說,若是讀者想和低級建模II做朋友,建模以前應該優先考慮內容的清晰度,而不是內容的精簡性。若是內容即精簡又直觀,這種狀況固然是最好的結果。
至於實驗一是沒有仿真的必要,由於內容足夠直白,這種程度足以腦補時序。最後筆者還要說道,實驗一雖然沒有什麼學習的價值,可是實驗一要表達的信息也很是清楚,即低級建模II是注重清晰,直觀的建模技巧。此外,實驗一也能夠做爲學習的熱身。