2012-09-24 170 views
1

我想在verilog中創建一個有限狀態機。該系統具有4個1-bit輸入rstclkAB和一個輸出ZVerilog有限狀態機

如果: A在最後兩個時鐘沿上具有相同的值,則Z等於1。

或B自從最後一條規則爲真以來,在每個時鐘邊沿都處於高位(1)。

否則z=0;

我沒有工具來模擬我的嘗試atm。所以我想知道這是否是正確的方法,如果我在正確的軌道上?

module StateMachine(R, A, B, clk, Z); 
    input R, A, B, clk; 
    output reg Z; 

    reg ATemp; 
    reg state; 

    always @ (posedge clk or A) 
     if (A == 1'b1) 
     ///////////////// 
     begin 
     if (ATemp == 1'b1) state <= 1'b1; 
     else ATemp <= A; 
     end 
     //////////////// 
     else 
     //////////// 
     begin 
      if (ATemp == 1'b0) state <= 1'b1; 
      else ATemp <= A; 
     end 


    always @ (state) 
     case(state) 
     1'b0: Z=0; 
     1'b1: Z=1; 

     default: Z=0; 
     endcase 

endmodule 
+2

如果你沒有模擬工具,那麼你需要得到一些。否則,這是毫無意義的,如果沒有模擬,你將永遠無法到達任 – Tim

+0

你爲什麼不有SIM工具(最商業的提供30天的演示)? –

回答

0

您沒有下一個狀態邏輯,所以狀態永遠不會改變,並且沒有重置,所以狀態將以1'bz開始。編碼狀態機時,我建議從Xilinx guidelines開始。

+0

良好的起點(不像'一切正常'的答案)。 –

+0

如果狀態在posedge上更改,則不需要定義下一個狀態。然而在這種情況下,它只有1次,所以不起作用。 – Morgan

0

您對觸發器的定義有些不對。您有always @ (posedge clk or A)。您不應該組合邊緣觸發器和非邊緣觸發器。它可能在模擬中起作用,但你不會在綜合中得到你想要的。

如果你只希望值來改變時鐘邊沿上,然後使用always @(posedge clk)或一個組合輸入,是與輸入使用always @(A)或更多的現代版always @*輸出的變化。 @ *將觸發任何更改。缺少靈敏度列表中的項目是合成代碼與RTL模擬不一樣的主要原因。

說如果你正在建造一個觸發器,你應該包括一個重置。always @ (posedge clk or negedge rst_n)

還要注意的狀態永遠不會設置爲0,這樣的第一印象是,這將鎖定到一個特定的國家/輸出。我很難看到代碼如何實現被問到的問題。我的解決方案會是這樣的:

module statemachine(
    input  rst, 
    input  A, 
    input  B, 
    input  clk, 
    output reg Z 
); 

    reg [1:0] a_last_two; 
    wire  rule_one; 

    always @ (posedge clk or negedge rst) begin 
    if (~rst) begin 
     a_last_two <= 2'b0; 
    end 
    else begin 
     a_last_two <= {a_last_two[0] ,A}; 
    end 
    end 

    assign rule_one = (a_last_two[1] == a_last_two[0]); 
    //rule one could be written as ~^a_last_two (xnor reduction operator) 

    reg rule_two; 
    always @ (posedge clk or negedge rst) begin 
    if (~rst) begin 
     rule_two <= 1'b0 ; 
    end 
    else begin 
     //rule 2 resets when rule_one is true 
     if (rule_one) begin 
     rule_two <= 1'b1 ; 
     end 
     else begin 
     rule_two <= rule_two & B ; 
     end 
    end 
    end 

    assign Z = rule_one | rule_two ; 

endmodule