【黑金原創教程】【FPGA那些事兒-驅動篇I 】【實驗一】流水燈模塊


實驗一:流水燈模塊

對於發展商而言,動土儀式無疑是最重要的任務。為此,流水燈實驗作為低級建模II的動土儀式再適合不過了。廢話少說,我們還是開始實驗吧。

clip_image002

圖1.1 實驗一建模圖。

如圖1.1 所示,實驗一有名為 led_funcmod的功能模塊。如果無視環境信號(時鍾信號還有復位信號),該功能模塊只有一組輸出端,亦即4位LED信號。接下來讓我們來看具體內容:

led_funcmod.v
1.    module led_funcmod
2.    (
3.         input CLOCK, RESET,
4.         output [3:0]LED
5.    );

以上內容為出入端聲明。

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毫秒。

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則用來暫存延遲標簽。

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行)。

這個實驗所在乎的內容根本不是實驗結果而是低級建模II本身。假若比較《建模篇》的流水實驗,低級建模I與低級建模II之間是有明顯的差距。首先,低級建模II再也不見計數器或者定時器等周邊操作。再者,低級建模II的整合度很高,例如步驟0~3:

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.1

內容如代碼1.1所示,步驟0~3每個步驟示意一段完整的小操作,例如步驟0為4’b0001保持一段時間,步驟1為4’b0010保持一段時間,步驟2~3也是如此。其中 -1也考慮了步驟切換的時間。假設流水間隔要求1毫妙,那么每個步驟都會准確無誤停留50000個時鍾。事實上,步驟0也可以換成比較方便的寫法,如代碼1.2所示:

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是注重清晰,直觀的建模技巧。此外,實驗一也可以作為學習的熱身。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM