Verilog_有限狀態機
阿新 • • 發佈:2018-11-17
名詞解釋
狀態機就是一種能夠描述具有邏輯順序和時序順序事件的方法。
狀態機有兩大類:Mealy型和Moore型。
Moore型狀態機的輸出只與當前狀態有關,而Mealy型狀態機的輸出不僅取決於當前狀態,還受到輸入的直接控制,並且可能與狀態無關。
當使用Verilog來描述一個簡單狀態機的設計時,應將狀態暫存器的控制器的控制和狀態機狀態裡的組合邏輯分開。
程式碼風格
一段式
當前狀態、下一狀態、當前輸出值都寫在一個always塊中
二段式
當前狀態、下一狀態、當前輸出值寫在兩個always塊中
- 注意:這樣三種組合方式,及有三種方式寫這兩個always塊。
三段式
當前狀態、下一狀態、當前輸出值分別寫在各自的always塊中,這樣需要3個always塊。
自動售報機Verilog實現
設計說明
設計一個簡單的數位電路用於電子的報紙售賣機的投幣器。
design code
- 假設報紙的價格為15分。
- 投幣器只能接受5分和1角的硬幣。
- 必須提供適當的數目的零錢,投幣器不找零。
- 合法的硬幣組合包括1個5分的硬幣和1個一角的硬幣,3個5分的硬幣,1個1角的硬幣和1個5分的硬幣。2個1角的硬幣是合法的,但是投幣器不找零。
module vend( input [1:0] coin, input clock, input reset, output newspaper ); //宣告有限狀態機的內部狀態 wire [1:0] NEXT_STATE; reg [1:0] PRES_STATE; //狀態編碼 parameter s0 = 2'b00; parameter s5 = 2'b01; parameter s10 = 2'b10; parameter s15 = 2'b11; //用同步復位、時鐘正跳變沿觸發的狀態觸發器
[email protected](posedge clock) begin if(reset == 1'b1) PRES_STATE <= s0; else PRES_STATE <= NEXT_STATE; end //組合邏輯 function [2:0] fsm; //狀態變化及輸出組合邏輯 input [1:0] fsm_coin; input [1:0] fsm_PRES_STATE; reg fsm_newspaper; reg [1:0] fsm_NEXT_STATE; begin case(fsm_PRES_STATE) s0: //狀態為s0 begin if(fsm_coin == 2'b10) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s10; end else if(fsm_coin == 2'b01) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s5; end else begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s0; end end s5: //狀態為s5 begin if(fsm_coin == 2'b10) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s15; end else if(fsm_coin == 2'b01) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s10; end else begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s5; end end s10: //狀態為s10 begin if(fsm_coin == 2'b10) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s15; end else if(fsm_coin == 2'b01) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s15; end else begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s10; end end s15: //狀態為s15 begin fsm_newspaper = 1'b1; fsm_NEXT_STATE = s0; end endcase fsm = {fsm_newspaper,fsm_NEXT_STATE}; end endfunction //每當硬幣放入或當前狀態改變時,組合邏輯動作 assign {newspaper,NEXT_STATE} = fsm(coin,PRES_STATE); endmodule
testbench
module vend_tb;
reg clock;
reg reset;
reg [1:0] coin;
wire newspaper;
always #20 clock = ~clock;
initial
begin
clock = 0;
reset = 1;
#100;
reset = 0;
@(posedge clock) coin[1:0] = 2'b00;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b10;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b10;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b10;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b00;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
#200 $finish;
end
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
vend u_vend(
.coin(coin),
.clock(clock),
.reset(reset),
.newspaper(newspaper)
);
endmodule