天天看點

2021-08-21Verilog三段式狀态機的寫法,标準示例和仿真。

Verilog三段式狀态機的寫法,标準示例和仿真。

第一段:同步狀态轉移。第一個always塊格式化描述次态寄存器遷移到現态寄存器。

第二段:目前狀态判斷接下來的狀态。組合邏輯always子產品,描述狀态轉移條件判斷用current_state

第三段:次态描述輸出。同步時序always子產品,描述次态寄存器輸出(有誤,見下一篇文章)

注意:

三段式并不是一定要寫為3個always塊,如果狀态機更複雜,就不止3段了。

  1. 三段always子產品中,第一個和第三個always子產品是同步時序always子產品,用非阻塞指派(“ <= ”);第二個always子產品是組合邏輯always子產品,用阻塞指派(“ = ”)。
  2. 第二部分為組合邏輯always子產品,為了抑制warning資訊,對于always的敏感清單建議采用always@(*)的方式。
  3. 第二部分,組合邏輯always子產品,裡面判斷條件一定要包含所有情況!可以用else保證包含完全。
  4. 第二部分,組合邏輯電平要維持超過一個clock,仿真時注意。
  5. 需要注意:第二部分case中的條件應該為目前态(current_state)。
  6. 第三部分case中的條件應該為次态(next_state)。
  7. 編碼原則,binary和gray-code适用于觸發器資源較少,組合電路資源豐富的情況(CPLD),對于FPGA,适用one-hot code。這樣不但充分利用FPGA豐富的觸發器資源,還因為隻需比較一個bit,速度快,組合電路簡單。

    示例1. 狀态轉移圖:

    2021-08-21Verilog三段式狀态機的寫法,标準示例和仿真。

(1)fsm.v檔案:

module fsm(//go,ws,clk,rst_n,rd,ds);

input go,

input ws,

input clk,

input rst_n,

output reg rd,

output reg ds,

output reg [1:0] current_state,

output reg [1:0] next_state,

output reg [3:0] led

);

//reg rd,ds;

parameter [1:0] IDLE = 2’b00;

parameter [1:0] READ = 2’b01;

parameter [1:0] DLY = 2’b10;

parameter [1:0] DONE = 2’b11;

//reg [1:0] current_state,next_state;

//next state logic

always @(posedge clk or negedge rst_n)begin

if(!rst_n) current_state <= IDLE;

else current_state <= next_state;//

end

//state register

always @(current_state or go or ws)begin

next_state = 2’bx;

case(current_state)

IDLE : if(go) next_state = READ;

else next_state = IDLE;

READ : next_state = DLY;

DLY : if(ws) next_state = READ;

else next_state = DONE;

DONE : next_state = IDLE;

endcase

end

//Output logic

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

rd <= 1’b0;

ds <= 1’b0;

end

else begin

rd <= 1’b0;

ds <= 1’b0;

led <= 4’b0000;

case(next_state)//注意是next_state.

IDLE: if(go) begin rd <= 1’b1; led <= 4’b0001; end

READ: begin rd <= 1’b1; led <= 4’b0010; end

DLY: if(ws) begin rd <= 1’b1; led <= 4’b0100; end

else begin ds <= 1’b1; led <= 4’b1000; end

DONE: begin ds <= 1’b1; led <= 4’b1000; end

endcase

end

end

Endmodule

(2)fsm_test.v檔案:

`timescale 1ns/1ps

module fsm_test();

reg clk;

reg rst_n;

reg go;

reg ws;

wire rd;

wire ds;

wire [3:0] led;

wire [1:0] current_state;

wire [1:0] next_state;

fsm u1(

.go(go),

.ws(ws),

.clk(clk),

.rst_n(rst_n),

.rd(rd),

.ds(ds),

.current_state(current_state),

.next_state(next_state),

.led(led)

);

initial begin

clk =1’b0;

rst_n = 1’b1;

#50 rst_n =1’b0;

#50 rst_n =1’b1;

go = 1’b0;

ws = 1’b0;

#100 go = 1’b1;

#2000 $stop;//仿真2000ns後停止。

end

always #25 clk = ~clk;

Endmodule

仿真波形如下:

狀态和輸出對得上。需要注意第三個always塊裡的state用的是next_state.

2021-08-21Verilog三段式狀态機的寫法,标準示例和仿真。

原問題:當第三段使用current_state判斷時,狀态和輸出對不上。改為next_state正常。

仿真發現狀态跳轉不對:

2021-08-21Verilog三段式狀态機的寫法,标準示例和仿真。

繼續閱讀