【FPGA】狀態機思想回顧流水燈
- 一、LED流水燈實現
- 1. 基本要求
- 2. 狀態機思想
- 3. 關鍵代碼
- 4. 仿真測試
- 5. 效果演示
- 二、CPLD和FPGA
- 1. 技術區別
- 2. 應用場景
- 三、HDLbits組合邏輯題目
- 四、實驗總結
一、LED流水燈實現
1. 基本要求
- 用狀態機思想寫一個 LED流水燈的FPGA代碼
- 寫出仿真測試代碼,用Modelsim進行仿真分析
- DE2-115板上驗證
2. 狀態機思想
用狀態機思想的話,流水燈通常可以用幾個狀態來表示不同的LED亮的位置。
比如,每個狀態對應一個LED亮,然后通過狀態轉移來實現流動的效果。由于我們流水燈是8個燈亮,所以對應8個狀態。
所以,狀態機的狀態定義可能如下:
狀態S0: LED[0]亮
狀態S1: LED[1]亮
…
狀態S7: LED[7]亮
流水燈就是一個狀態持續一段時間再進入下一個狀態。
3. 關鍵代碼
// File: led_flow.v
module led_flow(input clk, // 50MHz時鐘 (DE2-115 PIN_Y2)input rst_n, // 復位信號 (低電平有效)output reg [7:0] led// LED輸出 (DE2-115 LEDG7-LEDG0)
);// 狀態定義
localparam S0 = 3'b000; // 初始狀態:LED0亮
localparam S1 = 3'b001;
localparam S2 = 3'b010;
localparam S3 = 3'b011;
localparam S4 = 3'b100;
localparam S5 = 3'b101;
localparam S6 = 3'b110;
localparam S7 = 3'b111;// 內部信號
reg [2:0] state; // 當前狀態
reg [24:0] cnt; // 分頻計數器
wire en; // 狀態切換使能(0.5Hz)// 0.5Hz分頻(0.5秒切換)
assign en = (cnt == 25'd24_999_999); // 50MHz/(25M+1) ≈ 0.5Hz// 分頻計數器
always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt <= 0;else if(en) cnt <= 0;else cnt <= cnt + 1;
end// 狀態機主邏輯
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginstate <= S0;led <= 8'b0000_0001; // 初始狀態endelse if(en) begincase(state)S0: begin led <= 8'b0000_0010; state <= S1; endS1: begin led <= 8'b0000_0100; state <= S2; endS2: begin led <= 8'b0000_1000; state <= S3; endS3: begin led <= 8'b0001_0000; state <= S4; endS4: begin led <= 8'b0010_0000; state <= S5; endS5: begin led <= 8'b0100_0000; state <= S6; endS6: begin led <= 8'b1000_0000; state <= S7; endS7: begin led <= 8'b0000_0001; state <= S0; enddefault: state <= S0;endcaseend
endendmodule
4. 仿真測試
寫完代碼后,參考連接博客進行仿真。
Quartus使用步驟及聯合Modelsim仿真教程-
知安的小白
操作步驟這篇博客講的很清楚了,一同操作后的效果截圖如下
仿真代碼(tb_led_flow.v)
// File: tb_led_flow.v
`timescale 1ns/1ps
module tb_led_flow();reg clk;
reg rst_n;
wire [7:0] led;// 實例化被測模塊
led_flow uut(.clk(clk),.rst_n(rst_n),.led(led)
);// 生成50MHz時鐘
initial beginclk = 0;forever #10 clk = ~clk; // 20ns周期=50MHz
end// 測試激勵
initial begin// 初始化rst_n = 0;#100;rst_n = 1;// 觀察10個狀態周期#100000000; // 仿真10ms(實際應仿真更長時間)$stop;
endendmodule
下面是仿真波形:
5. 效果演示
[FPGA]狀態機思想回顧流水燈演示效果
二、CPLD和FPGA
1. 技術區別
特性 | 特性 | FPGA |
---|---|---|
結構 | 乘積項邏輯 | 查找表(LUT)結構 |
邏輯容量 | 通常<10萬門 | 可達數百萬邏輯單元 |
布線結構 | 固定互聯 | 可編程互聯 |
時序特性 | 確定延遲 | 布線依賴延遲 |
存儲資源 | 有限 | 包含專用Block RAM |
配置方式 | 非易失,上電即用 | 通常需要外部配置芯片 |
功耗 | 低靜態功耗 | 高動態功耗 |
適用場景 | 膠合邏輯、狀態機 | 復雜算法、并行處理 |
2. 應用場景
-
CPLD典型應用:
接口協議轉換(UART、SPI)
簡單狀態機控制
地址譯碼電路
上電時序管理 -
FPGA典型應用:
數字信號處理(FIR濾波器)
高速接口(PCIe、DDR)
圖像處理流水線
協議加速(TCP/IP Offload)
三、HDLbits組合邏輯題目
HDLbits問題集(Verilog)精選題目及解答
題目1:Exams/m2014 q4g
module top_module (input in1,input in2,input in3,output out);assign out = (~(in1^in2)^in3);
endmodule
題目2:Gates
Module Declaration
module top_module(
input a, b,
output out_and,
output out_or,
output out_xor,
output out_nand,
output out_nor,
output out_xnor,
output out_anotb
);
大概意思就是寫個邏輯語句實現名稱。
module top_module( input a, b,output out_and,output out_or,output out_xor,output out_nand,output out_nor,output out_xnor,output out_anotb
);assign out_and=a&b;assign out_or=a|b;assign out_xor=a^b;assign out_nand=~(a&b);assign out_nor=~(a|b);assign out_xnor=~(a^b);assign out_anotb=a&(~b);
endmodule
題目3:Arithmetic Circuits–Adder(加法器設計)
module top_module (input [3:0] x, input [3:0] y, output [4:0] sum);assign sum = x + y;
endmodule
題目4:7420
74LS20芯片內部邏輯電路如下,由兩個nand(與非門)組成。需要寫個語句實現7420功能。
module top_module ( input p1a, p1b, p1c, p1d,output p1y,input p2a, p2b, p2c, p2d,output p2y );assign p1y=~(p1a&p1b&p1c&p1d);assign p2y=~(p2a&p2b&p2c&p2d);
endmodule
題目5:Truthtable1
按真值表實現電路。
如果數電學的不好不知道怎么辦的話,可以用logisim,點擊Project->Analyze Circuit->Table:
再點擊Build Circuit就生成電路圖了。
module top_module( input x3,input x2,input x1, // three inputsoutput f // one output
);assign f=((~x3)&x2)|(x1&x3);
endmodule
四、實驗總結
本次實驗掌握了狀態機編程思想,事實上,狀態機思想也更簡易更容易想到。