#2023,你的 FPGA 年度关键词是什么? # 对状态机的疑惑? - FPGA开发者技术社区 - 电子技术论坛 - 广受欢迎的专业电子论坛
分享 收藏 返回

商周 关注 私信
[问答]

#2023,你的 FPGA 年度关键词是什么? # 对状态机的疑惑?

自己平时一直在写的状态机格式,同事昨天说我写的是一段式的最多算是伪二段式的,说的看了不少文章我也有点疑惑了,所给大家贴出来一起看看,我这边写法和野火的一直这次就贴出野火FPGA的code,供大家参考对比。

module complex_fsm
(
input wire sys_clk , //系统时钟 50MHz
input wire sys_rst_n , //全局复位
input wire pi_money_one , //投币 1 元
input wire pi_money_half , //投币 0.5 元

output reg po_money , //po_money 为 1 时表示找零
//po_money 为 0 时表示不找零
output reg po_cola //po_cola 为 1 时出可乐
//po_cola 为 0 时不出可乐
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//parameter define
//只有五种状态,使用独热码
parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF = 5'b01000;
parameter TWO = 5'b10000;

//reg define
reg [4:0] state;

//wire define
wire [1:0] pi_money;

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//pi_money:为了减少变量的个数,我们用位拼接把输入的两个 1bit 信号拼接成 1 个 2bit 信号
//投币方式可以为:不投币(00)、投 0.5 元(01)、投 1 元(10),每次只投一个币
assign pi_money = {pi_money_one, pi_money_half};

//第一段状态机,描述当前状态 state 如何根据输入跳转到下一状态
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
	state <= IDLE; //任何情况下只要按复位就回到初始状态
else case(state)
	IDLE : if(pi_money == 2'b01) //判断一种输入情况
			state <= HALF;
		   else if(pi_money == 2'b10)//判断另一种输入情况
	        state <= ONE;
           else
	        state <= IDLE;

    HALF : if(pi_money == 2'b01)
            state <= ONE;
           else if(pi_money == 2'b10)
            state <= ONE_HALF;
           else
            state <= HALF;

    ONE : if(pi_money == 2'b01)
           state <= ONE_HALF;
          else if(pi_money == 2'b10)
           state <= TWO;
          else
           state <= ONE;

   ONE_HALF: if(pi_money == 2'b01)
              state <= TWO;
             else if(pi_money == 2'b10)
              state <= IDLE;
             else
              state <= ONE_HALF;

   TWO : if((pi_money == 2'b01) || (pi_money == 2'b10))
          state <= IDLE;
         else
          state <= TWO;
//如果状态机跳转到编码的状态之外也回到初始状态
   default : state <= IDLE;
endcase

//第二段状态机,描述当前状态 state 和输入 pi_money 如何影响 po_cola 输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
  po_cola <= 1'b0;
else if((state == TWO && pi_money == 2'b01) || (state == TWO &&pi_money == 2'b10) || (state == ONE_HALF && pi_money == 2'b10))
  po_cola <= 1'b1;
else
  po_cola <= 1'b0;

//第二段状态机,描述当前状态 state 和输入 pi_money 如何影响 po_money 输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
  po_money <= 1'b0;
else if((state == TWO) && (pi_money == 2'b10))
  po_money <= 1'b1;
else
  po_money <= 1'b0;

endmodule

更多回帖

×
发帖