Verilog中的简单状态机如何?

时间:2013-04-10 17:32:03

标签: verilog

我正在尝试将简单state machine的流程图转换为Verilog代码。 但我不知何故坚持以下,因为我对Verilog几乎没有任何了解,我可能会遗漏一些东西。

如果0 and 1的计数可以除以3(或简单地说:如果已经有3次数为1),则状态机会检测到1的输入流。

enter image description here

module example (
  input clk,
  input rst,
  input input1,
  output output
);

reg state;
reg nextstate;

localparam state2 = 3'd0;
localparam state1 = 3'd1;
localparam state0 = 3'd2;

always @(posedge clk or posedge rst) begin
  if (rst)
    state <= state0;
  else
    state <= nextstate;
end

always @* begin
  case(state)
    state0: begin
      if(input1)
        nextstate = state1;
      end
    state2: begin
      if(input1)
        nextstate = state0;
      end
    state1: begin
      if(input1)
        nextstate = state2;
      end
    default: nextstate = state0;
  endcase
end

always @* begin
  output1 = state0 & input1;
end

endmodule

我不确定:

  • 我是否必须将输入+输出定义为regwire?或者是inputoutput!足够?

  • 我必须为reg state, nextstate提供向量维度吗?如果是,我如何知道要选择哪个尺寸?

  • 我可以像state0 & input1一样在最后写这些断言吗?或者我应该使用state = state0 & input1 = ?? - 是的,什么?

3 个答案:

答案 0 :(得分:2)

  

我必须将输入+输出定义为reg或wire吗?或输入输出!足够?

输入始终是连线,但由于您没有分配它们并不重要。默认情况下,输出是连线,但如果您想要一个寄存器,也可以声明output reg

  

我必须为reg状态提供向量维度吗,nextstate?如果是,我该如何知道要选择哪个尺寸?

是的,你必须声明一个维度,否则当verilog默默地将你的所有状态截断为01时,你的设计将会灾难性地失败。状态的宽度应与用于定义状态名称的localparams的宽度相同,或者更一般地,宽度应为log2(number of input states)

  

我可以在最后写出这种断言,如state0&amp;输入1?

我认为这不是你想要的。 State0只是一个常数。如果您想知道状态机是否处于state0 ,那么您需要将当前状态与常量state0进行比较。此外,您可能不希望在此处使用按位AND,因此请使用常规和&&。应该是:

output = (state == state0) && input1;

答案 1 :(得分:2)

always @* begin
  case(state)
    state0: begin
      if(input1)begin
        nextstate = state1;
         output1 = 0;
      end end
       else begin
        nextstate = state0;
         output1 = 1;
      end
    state2: begin
      if(input1)begin
        nextstate = state0;
        output1   = 1 ;
      end end
      begin
        nextstate = state2;
         output1 = 0;
      end
    state1: begin
      if(input1)begin
        nextstate = state2;
        output1   = 0;
      end end
     else begin
        nextstate = state1;
         output1 = 0;
      end
    default: nextstate = state0;
  endcase
end

答案 2 :(得分:1)

虽然为时已晚,但我上了学习Verilog的乐队马车并决定对你的询问进行拍摄。我编写了设计模块,并为它创建了一个测试平台。这符合您的期望。

`timescale 1ns/1ns
`define WIDTH 4
module FSM_Detect_Stream_Top();

    reg in_clk;
    reg in_rst_n;
    reg [`WIDTH-1:0] in_input;

    wire out_ouput;

    FSM Test (.i_clk(in_clk), .i_rst_n(in_rst_n), .i_input(in_input), .o_output(out_output));

    initial
        begin
            in_clk = 1'b0; // clk at t=0
            #1 in_rst_n = 1'b1;
            #2 in_rst_n = 1'b0;
            #5 in_rst_n = 1'b1;
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b00;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_rst_n = 1'b0;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b00; in_rst_n = 1'b1;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            $finish;
        end


    // Generating a 20ns width clock pulse with 50% duty cycle
    always
        #10 in_clk = ~in_clk;

endmodule // FSM_Detect_Stream_Top

//*********************************************************************************************
module FSM(input i_clk, input i_rst_n, input [`WIDTH-1:0] i_input, output reg o_output);
//*********************************************************************************************

    parameter S0 = 2'b00;   //FIRST STATE or DEFAULT
    parameter S1 = 2'b01;   //SECOND STATE
    parameter S2 = 2'b10;   //THIRD STATE
    parameter S3 = 2'b11;   //FOURTH STATE

    reg [`WIDTH-3:0] curr_state;
    reg [`WIDTH-3:0] next_state;

    //Sequential Logic for Storing Current State
    always @ (posedge i_clk or negedge i_rst_n) begin
        if(~i_rst_n)
            curr_state <= S0;
        else
            curr_state <= next_state;
        end

    //Combinational Logic for Next State
    always @ (curr_state or i_input)    begin
        case(curr_state)
            S0: begin
                if (i_input == 2'b01)
                    next_state <= S1;
                else
                    next_state <= S0;
            end
            S1: begin
                if (i_input == 2'b01)
                    next_state <= S2;
                else
                    next_state <= S1;
            end
            S2: begin
                if (i_input == 2'b01)
                    next_state <= S3;
                else
                    next_state <= S2;
            end
            S3: begin
                if (i_input == 2'b01)
                    next_state <= S0;
                else
                    next_state <= S3;
            end 
            default: next_state <= S0;
        endcase // curr_state
    end

    // Output Logic
    always @(posedge i_clk) begin
        if (~i_rst_n)
            o_output <= 1'b0;
        else begin
            case(curr_state)    
                S0: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else
                        o_output <= 1'b1;
                    end
                S1: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else
                        o_output <= 1'b0;
                    end
                S2: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else 
                        o_output <= 1'b0;
                    end
                S3: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else 
                        o_output <= 1'b0;
                    end
                default: o_output <= 1'b0;
            endcase
        end
    end 

endmodule