1.示例代碼參考
這段代碼是用 Verilog 編寫的一個 LED 閃爍控制模塊,主要實現了 LED 按一定時間間隔循環移位閃爍的功能。下面詳細解釋其架構組成:
模塊定義與端口聲明
- 模塊名為?
led_flash
,包含三個端口:sys_clk
:輸入端口,是系統時鐘信號,用于驅動整個模塊的時序邏輯。rst_n
:輸入端口,是系統復位信號(低電平有效),用于在復位時將模塊狀態恢復到初始狀態。led
:輸出端口,是一個 4 位的寄存器,用于控制 4 個 LED 的亮滅狀態。
內部信號聲明
cnt
:28 位的寄存器,作為計數器,用于計時,實現 0.25 秒的時間間隔。add_cnt
:線網類型(wire
)信號,用于指示是否進行計數操作。end_cnt
:線網類型(wire
)信號,用于指示計數是否結束(即達到 0.25 秒的時間)。
計數器邏輯(cnt
?部分)
- 采用時序邏輯(
always @(posedge sys_clk or negedge rst_n)
),在時鐘上升沿或復位信號下降沿時觸發。- 當?
rst_n
?為低電平時(復位),cnt
?被置為 0。 - 當?
add_cnt
?為高電平時(允許計數):- 如果?
end_cnt
?為高電平(計數結束),cnt
?被置為 0,重新開始計數。 - 否則,
cnt
?加 1,繼續計數。
- 如果?
- 當?
控制信號賦值
add_cnt
?被賦值為 1,意味著始終允許計數器進行計數操作。end_cnt
?是一個組合邏輯信號,當?add_cnt
?為 1 且?cnt
?計數到?10_000_000 - 1
?時,end_cnt
?為 1,表示計數結束(即經過了 0.25 秒,假設系統時鐘頻率為 40MHz,10_000_000
?個時鐘周期約為 0.25 秒)。
LED 控制邏輯
- 同樣采用時序邏輯(
always @(posedge sys_clk or negedge rst_n)
)。- 當?
rst_n
?為低電平時(復位),led
?被置為?4'b1110
,這是復位后的初始狀態(可以根據實際硬件連接,確定具體哪個 LED 亮滅)。 - 當?
end_cnt
?為高電平時(計數結束,即經過 0.25 秒),led
?進行循環移位操作({led[2:0], led[3]}
),實現 LED 狀態的切換。 - 否則,
led
?保持當前狀態不變。
- 當?
// 模塊名稱:led_flash
// 功能描述:實現4個LED按0.25秒間隔循環移位閃爍
// 輸入信號:sys_clk(系統時鐘)、rst_n(復位信號,低電平有效)
// 輸出信號:led(4位,控制4個LED的亮滅狀態)
module led_flash(input sys_clk, // 系統時鐘,假設頻率為40MHzinput rst_n, // 復位信號,低電平有效output reg [3:0] led // 4位LED輸出,高/低電平對應LED亮/滅(取決于硬件設計)
);// 內部信號定義
reg [27:0] cnt; // 28位計數器,用于計時(最大計數2^28-1,滿足計時需求)
wire add_cnt; // 計數使能信號,為1時允許計數器遞增
wire end_cnt; // 計數結束信號,為1時表示達到設定時間// 計數器時序邏輯:在時鐘上升沿或復位下降沿更新計數器值
always @(posedge sys_clk or negedge rst_n) beginif(!rst_n) begin // 復位狀態:計數器清零cnt <= 28'd0;endelse if(add_cnt) begin // 計數使能有效if(end_cnt) begin // 計數達到目標值:計數器清零,重新計數cnt <= 28'd0;endelse begin // 未達到目標值:計數器遞增cnt <= cnt + 28'd1;endendelse begin // 計數使能無效:保持當前值cnt <= cnt;end
end// 計數使能信號:始終為1,讓計數器持續工作
assign add_cnt = 1'b1;// 計數結束信號:當計數器達到10,000,000-1時為1
// 計算依據:40MHz時鐘周期為25ns,10,000,000個周期 = 10,000,000 × 25ns = 0.25秒
assign end_cnt = add_cnt && (cnt == 28'd9_999_999);// LED控制時序邏輯:在時鐘上升沿或復位下降沿更新LED狀態
always @(posedge sys_clk or negedge rst_n) beginif(!rst_n) begin // 復位狀態:初始LED狀態為4'b1110(假設低電平點亮,此時最右側LED亮)led <= 4'b1110;endelse if(end_cnt) begin // 每0.25秒更新一次LED狀態:循環左移一位// 移位邏輯:將低3位移到高3位,最高位移到最低位// 例:1110 → 1101 → 1011 → 0111 → 1110(循環)led <= {led[2:0], led[3]};endelse begin // 未到更新時間:保持當前LED狀態led <= led;end
endendmodule
2.通過本程序對FPGA的進一步理解
硬件并行特性與非軟件式循環
FPGA 是基于硬件描述語言(如 Verilog、VHDL)進行設計,本質上是對硬件電路的描述。 它通過配置可編程邏輯單元(如查找表、觸發器等)和布線資源來實現特定功能。硬件電路一旦上電配置完成,各個功能模塊會并行地持續工作。比如在一個簡單的流水燈 FPGA 設計中,計數器模塊和 LED 控制模塊是同時在工作的,不存在像軟件程序中由 CPU 一條一條按順序執行指令那樣的循環。
時鐘驅動下的持續狀態更新
FPGA 中的時序邏輯(如觸發器、寄存器等)通常由時鐘信號驅動。以之前提到的 LED 閃爍控制模塊為例,在時鐘上升沿或者下降沿,相關寄存器(如計數器?cnt
?、LED 輸出寄存器?led
?)會根據當前的輸入信號和邏輯條件來更新狀態。 時鐘信號不斷地產生上升沿或下降沿,就會讓這些模塊持續不斷地進行狀態更新,看起來就好像是在 “循環運行”。
組合邏輯的即時響應
FPGA 中的組合邏輯部分,如加法器、多路選擇器等,只要輸入信號發生變化,輸出就會立即根據邏輯關系進行更新。比如一個由組合邏輯實現的簡單運算電路,輸入數據一旦改變,輸出會馬上重新計算得出新值,這種持續根據輸入變化而即時響應的特性,也會給人一種在不斷 “運行” 的感覺。
狀態機與類似循環的操作
狀態機是 FPGA 設計中常用的一種設計方法。在狀態機里,會根據當前狀態和輸入信號決定下一個狀態。 當狀態機進入一個循環狀態序列時,就會在這些狀態之間不斷切換,從而實現特定的功能。比如一個交通燈控制狀態機,會在 “紅燈 - 綠燈 - 黃燈” 等狀態間循環切換,從宏觀功能上看就像是在循環運行。