sky 发表于 2021-3-16 22:33:57

【FPGA】Verilog状态机设计

本帖最后由 sky 于 2021-3-16 22:33 编辑

状态机是fpga设计中极其重要的一种技巧,掌握状态机的写法可以使fpga的开发事半功倍。

下面记录一下状态机的基本知识理论。.



实例:



三种状态机实现代码:

// 一段式状态机

module style1_fsm(i_clk, rst_n, i1, i2, o1, o2, err);

input i_clk, rst_n, i1, i2;
output o1, o2, err;

parameter IDLE = 4'b0001,
                S1   = 4'b0010,
                S2   = 4'b0100,
                ERROR= 4'b1000;

reg o1, o2, err;
reg state;

always @(posedge i_clk or negedge rst_n)
begin
      if(!rst_n) begin
                state <= IDLE;
                {o1, o2, err} <= 3'b000;
      end
      else
                case(state)
                IDLE:      begin
                              if(!i1) begin
                                        {o1, o2, err} <= 3'b000;
                                        state <= IDLE;
                              end
                              if(i1 & i2) begin                                       
                                        {o1, o2, err} <= 3'b100;
                                        state <= S1;
                              end
                              if(i1 & !i2) begin                                       
                                        {o1, o2, err} <= 3'b111;
                                        state <= ERROR;
                              end
                        end
                S1:      begin
                              if(!i2) begin                                       
                                        {o1, o2, err} <= 3'b100;
                                        state <= S1;
                              end
                              if(i1 & i2) begin                                       
                                        {o1, o2, err} <= 3'b010;
                                        state <= S2;
                              end
                              if(!i1 & i2) begin                                       
                                        {o1, o2, err} <= 3'b111;
                                        state <= ERROR;
                              end
                        end
                S2:      begin
                              if(i2) begin                                       
                                        {o1, o2, err} <= 3'b010;
                                        state <= S2;
                              end
                              if(i1 & !i2) begin                                       
                                        {o1, o2, err} <= 3'b000;
                                        state <= IDLE;
                              end
                              if(!i1 & !i2) begin                                       
                                        {o1, o2, err} <= 3'b111;
                                        state <= ERROR;
                              end
                        end
                ERROR:      begin
                              if(i1) begin                                       
                                        {o1, o2, err} <= 3'b111;
                                        state <= ERROR;
                              end
                              if(!i1) begin                                       
                                        {o1, o2, err} <= 3'b000;
                                        state <= IDLE;
                              end
                        end
                default:begin                              
                              {o1, o2, err} <= 3'b000;
                              state <= IDLE;
                        end
                endcase

end


endmodule// 两段式状态机

module style2_fsm(i_clk, rst_n, i1, i2, o1, o2, err);

input i_clk, rst_n, i1, i2;
output o1, o2, err;

parameter IDLE = 4'b0001,
                S1   = 4'b0010,
                S2   = 4'b0100,
                ERROR= 4'b1000;

reg o1, o2, err;
reg curr_state, next_state;

always @(posedge i_clk or negedge rst_n) begin
      if(!rst_n)
                curr_state <= IDLE;
      else
                curr_state <= next_state;
end

always @(curr_state or i1 or i2) begin
      case(curr_state)
      IDLE:      begin
                        if(!i1) begin
                              IDLE_OUT;
                              next_state = IDLE;
                        end
                        if(i1 & i2) begin
                              S1_OUT;
                              next_state = S1;
                        end
                        if(i1 & !i2) begin
                              ERROR_OUT;
                              next_state = ERROR;
                        end
                end
      S1:      begin
                        if(!i2) begin
                              S1_OUT;
                              next_state = S1;
                        end
                        if(!i1 & i2) begin
                              ERROR_OUT;
                              next_state = ERROR;
                        end
                        if(i1 & i2) begin
                              S2_OUT;
                              next_state = S2;
                        end
                end
      S2:      begin
                        if(i2) begin
                              S2_OUT;
                              next_state = S2;
                        end
                        if(i1 & !i2) begin
                              IDLE_OUT;
                              next_state = IDLE;
                        end
                        if(!i1 & !i2) begin
                              ERROR_OUT;
                              next_state = ERROR;
                        end
                end
      ERROR:      begin
                        if(i1) begin
                              ERROR_OUT;
                              next_state = ERROR;
                        end
                        if(!i1) begin
                              IDLE_OUT;
                              next_state = IDLE;
                        end
                end
      default:begin
                        IDLE_OUT;
                        next_state <= IDLE;
                end
      endcase
end

task IDLE_OUT;
      {o1, o2, err} = 3'b000;
endtask

task S1_OUT;
      {o1, o2, err} = 3'b100;
endtask

task S2_OUT;
      {o1, o2, err} = 3'b010;
endtask

task ERROR_OUT;
      {o1, o2, err} = 3'b111;
endtask

endmodule// 三段式状态机

module style3_fsm(i_clk, rst_n, i1, i2, o1, o2, err);

input i_clk, rst_n, i1, i2;
output o1, o2, err;

parameter IDLE = 4'b0001,
                S1   = 4'b0010,
                S2   = 4'b0100,
                ERROR= 4'b1000;

reg o1, o2, err;
reg curr_state, next_state;

always @(posedge i_clk or negedge rst_n)
begin
      if(!rst_n)
                curr_state <= IDLE;
      else
                curr_state <= next_state;
end

always @(curr_state or i1 or i2)
begin      
      case(curr_state)
      IDLE:      begin
                        if(!i1)                next_state = IDLE;
                        if(i1 & i2)      next_state = S1;
                        if(i1 & !i2)      next_state = ERROR;
                end
      S1:      begin
                        if(!i2)                next_state = S1;
                        if(i1 & i2)      next_state = S2;
                        if(!i1 & i2)      next_state = ERROR;
                end
      S2:      begin
                        if(i2)                next_state = S2;
                        if(i1 & !i2)      next_state = IDLE;
                        if(!i1 & !i2)      next_state = ERROR;
                end
      ERROR:      begin
                        if(i1)                next_state = ERROR;
                        if(!i1)                next_state = IDLE;
                end
      default:begin
                        next_state = IDLE;      // 不加这个default项 输出会一直是000!!!
                end
      endcase
end

always @(posedge i_clk or negedge rst_n)
begin
      if(!rst_n)
                {o1, o2, err} <= 3'b000;
      else begin
                case(next_state)
                IDLE:      {o1, o2, err} <= 3'b000;
                S1:      {o1, o2, err} <= 3'b100;
                S2:      {o1, o2, err} <= 3'b010;
                ERROR:      {o1, o2, err} <= 3'b111;
                default:{o1, o2, err} <= 3'b000;//不加这个default 复位前信号都为不定值X
                endcase
      end
end



endmodule



页: [1]
查看完整版本: 【FPGA】Verilog状态机设计