小墨同学 发表于 2014-11-20 13:32:28

零基础学FPGA(八)浅谈状态机

本帖最后由 小墨同学 于 2014-11-20 16:59 编辑

前几天收到一封邮件,说我在EDNchina博客大赛中获了奖,我打开一看,还真是,而且一下就获了两个,一个三等奖,一个原创新人奖。然后我就想了一下,我好像没参加什么博客大赛啊,还有就是每过一段时间我写的东西的标题前面都加了博客大赛四个字,有一次我还好奇,然后自己把前面的那几个字给删了,就是我刚开始写的那几篇文章。现在也是,我写的有几篇日记前面还是加了博客大赛四个字...一开始我就打算是写给自己看的,也没想过参加什么博客大赛,莫名其妙就获奖了还是觉得有点奇怪哈~不过获了更好~毕竟有钱嘛~,在这里谢过EDNchina的工作人员,也谢谢看过我写的东西的人(可能我写的也没什么价值),祝EDNchina越办越好!
   今天我们来写状态机。
   关于状态机呢,想必大家应该都接触过,通俗的讲就是数电里我们学的状态转换图。状态机分为两中类型,一种叫Mealy型,一种叫Moore型。前者就是说时序逻辑的输出不仅取决于当前的状态,还取决于输入,而后者就是时序逻辑的输出仅仅取决于当前的状态。下面两个图分别表示两种不同的状态机。




下面我们就通过代码来写一下状态机,以下面的状态转换图为例

首先,是一种典型的状态机写法,这种写法我们称为一段时状态机,用于一些简单的设计是可以的,但如果是复杂的状态机,不建议大家用这种写法。

//***********************************************************
//**********************小墨笔记*****************************
//可综合的状态机设计的典型方法

//小墨同学于2014年5月31日在金翰林宿舍作

//实现典型的状态机设计

//************************小墨笔记,留作回忆**********************

module fsm (clk,rst_n,A,k1,k2,State);

input clk;
input rst_n;
input A;
output k1,k2;
output State;
reg k1;
reg k2;
reg State;   //当前状态寄存器

parameter   Idle = 2'b00,
                     Start = 2'b01,
                     Stop = 2'b10,
                     Clear = 2'b11;            //编码 ,注意,只有在最后一句用分号,其他地方用逗号

always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
   State <= Idle;
k1 <=1'b0;
k2 <=1'b0;
end
else case (State)                   //状态判断与组合逻辑赋值

       Idle :if(A) begin
      State <= Start;
k1 <= 0;
end
else begin
State <= Idle;
k1 <= 0;
k2 <= 0;
end
Start :if(!A) State <= Stop;
       else State<=Start;
Stop:if(A) begin
       State <=Clear;
k2 <= 1;
end
else State <= Stop;
Clear :if(!A) begin
       State <= Clear;
k2 <= 0;
k1 <= 1;
end
else State <= Clear;
default : State <= 2'bxx;   //告诉综合器 case语句已经指定了所有状态,这样综合器就会删除不需要的译码电路,使生成的电路简单
endcase
endmodule
//************************小墨品牌,你值得拥有~**************************





下面是另一种写法,叫做输出指定的码表示状态的状态机




//***********************************************************
//**********************小墨笔记*****************************
//由输出指定的码表示状态的状态机

//小墨同学于2014年5月21日在金翰林宿舍作

//用于高速状态机的设计

//************************小墨笔记,留作回忆**********************

module fsm2(clk,rst_n,A,k1,k2,State);
input clk;
input rst_n;
input A;
output k1,k2;
output State;
reg State;   //当前状态寄存器
assign k1 =State;
assign k2 =State;

parameter    Idle = 5'b00000,            //采用毒热编码(每个状态只有一个寄存器置位的状态机这样用的组合电路省一些,而且速度也快)
                      Start = 5'b00010,
                      Stop = 5'b00100,
                      StoptoClear = 5'b11000,
                      Clear = 5'b01010,
                     
CleartoIdle= 5'b00111;          //编码 ,注意,只有在最后一句用分号,其他地方用逗号

always @(posedge clk or negedge rst_n)
if(!rst_n)

   State <= Idle;

else case (State)                   //状态判断与组合逻辑赋值

       Idle :if(A)
      State <= Start;

else
State <= Idle;


Start :if(!A) State <= Stop;
       else State<=Start;
Stop:if(A)
       State <=StoptoClear;


else State <= Stop;
StoptoClear :State <= Stop;

Clear :if(!A)
       State <= Clear;


else State <= Clear;
CleartoIdle :State <= Idle;
default : State <= Idle;//告诉综合器 case语句已经指定了所有状态,这样综合器就会删除不需要的译码电路,使生成的电路简单
endcase

endmodule

//************************小墨品牌,你值得拥有~**************************
这样写就是把状态码的指定与状态机控制的输出联系起来,把状态的变化直接作用于输出,这样做可以提高输出信号的开关素的并节省电路器件。但这种方法也有缺点,就是快关的维持时间必须与状态维持的时间一致,这种设计方法常用在告诉状态机中。


下面这种写法应该是以后我们经常要用到的,即三段式状态机写法,比较适合于多输出的状态机设计。


//***********************************************************
//**********************小墨笔记*****************************
//多输出状态时的状态机

//小墨同学于2014年5月31日在金翰林宿舍作

//用于多输出时的状态机设计,也即三段式状态机的常见写法,推荐!

//************************小墨笔记,留作回忆**********************
module fsm3 (clk,rst_n,A,k1,k2,state);
input clk,rst_n,A;
output k1,k2;
output state;
reg k1,k2;
reg state;
reg xiaomo;
parameter Idle = 2'b00,
                  start = 2'b01,
                  stop = 2'b10,
                  clear = 2'b11;
always @ (posedge clk or negedge rst_n)   
       if(!rst_n) state <= Idle;
else state <= xiaomo;      //每一个时钟产生一个可能的变化,即时序逻辑部分



always @ (state or A)      //组合逻辑部分
       begin
case (state)
    Idle : if(A) xiaomo = start;
      elseiaomo = Idle;
start : if(!A)xiaomo = stop;
               else iaomo = start;
stop: if(A)xiaomo = clear;
            else iaomo = stop;
clear : if(!A) xiaomo =Idle;
               else iaomo = clear;
default : xiaomo = 2'bxx;
   endcase
end
always @ (state or A or rst_n)    //产生输出k1的组合逻辑
      if(!rst_n) k1=0;
else if(state ==clear && !A)
   k1=1;
else k1=0;
always @(state or A or rst_n)      //产生输出k2的组合逻辑
      if(!rst_n) k2=0;
else if(state ==stop && A)
    k2=1;
else k2=0;


endmodule
//************************小墨品牌,你值得拥有~**************************


此外,以后小墨同学的文章将在EDNchina和北京至芯科技官方技术论坛同时更新,至芯科技的官方技术论坛也有很多的资料供大家下载,里面也有小墨的专题板块,希望广大网友和爱好者的大力支持~
http://www.fpgaw.com/
小墨同学专版网址
http://www.fpgaw.com/thread-78527-1-1.html
下面是至芯科技官方网站,夏宇闻教授和那里的老师都超好的~有意愿接受FPGA培训的可以找工作人员咨询
http://www.zxopen.com/
       以后小墨同学的教程会跟这款开发板配套,想跟小墨同学一起学习,一起进步的的可以考虑一下购买一块开发板,毕竟学习要舍得投资嘛,下面是开发板淘宝链接
http://item.taobao.com/item.htm?spm=a230r.1.14.13.NZBxw3&id=42366952129&ns=1&abbucket=13#detail

zhiweiqiang33 发表于 2014-11-20 13:57:26

优化设计代码 风格 学习

lijia01 发表于 2014-11-20 16:19:41

正在学习谢谢分享

斥候兵1991 发表于 2015-3-3 11:01:22

建议优化代码风格

scott 发表于 2015-6-29 14:46:32

直接抄的书上的。。。。。

linuvzg 发表于 2022-5-1 14:28:07

本帖最后由 linuvzg 于 2022-5-27 13:41 编辑

支持一下,谢谢分享





















每種冷氣機的維修與清洗費都不一樣,因此有不少人都會選擇定期為冷氣機進行家居洗冷氣機,亦即是 洗冷氣 diy「冷氣通」師傅會檢查冷氣機的積水狀況丶水管高度丶安裝位置與接駁線路等,使整個維修過程更具效率。

















乔奈一一 发表于 2025-4-18 17:19:15

零基础学FPGA(八)浅谈状态机

宇xx 发表于 2025-4-19 14:28:10

零基础学FPGA(八)浅谈状态机
页: [1]
查看完整版本: 零基础学FPGA(八)浅谈状态机