tag 标签: 序列检测

相关博文
  • 热度 20
    2014-9-10 11:08
    1020 次阅读|
    0 个评论
    经常在笔试的时候出现这样的题:检测序列为11001101,输出为1,否则输出为0。 抽空写了下代码,仅供参考。 FSM1:一段式 module machine_test1(clk,rst,din,dout); input clk,rst; input din; output dout; //11001101 parameter idle=0,     st0=1,     st1=2,     st2=3,     st3=4,     st4=5,     st5=6,     st6=7; reg next_state; reg dout;   always @ (posedge clk or negedge rst) begin  if(!rst)  begin   next_state=idle;   dout=0;  end  else  begin   case(next_state)   idle:    if(din)    begin     next_state=st0;     dout=0;    end    else    begin     next_state=idle;     dout=0;    end   st0:    if(din)    begin     next_state=st1;     dout=0;    end    else    begin     next_state=idle;     dout=0;    end   st1:    if(!din)    begin     next_state=st2;     dout=0;    end    else    begin     next_state=st1;     dout=0;    end   st2:    if(!din)    begin     next_state=st3;     dout=0;    end    else    begin     next_state=st0;     dout=0;    end   st3:    if(din)    begin     next_state=st4;     dout=0;    end    else    begin     next_state=idle;     dout=0;    end   st4:    if(din)    begin     next_state=st5;     dout=0;    end    else    begin     next_state=idle;     dout=0;    end   st5:    if(!din)    begin     next_state=st6;     dout=0;    end    else    begin     next_state=st1;     dout=0;    end   st6:    if(din)    begin     next_state=idle;     dout=1;    end    else    begin     next_state=idle;     dout=0;    end   default:    begin     next_state=idle;     dout=0;     end   endcase  end end        endmodule FSM2:两段式 module machine_test(clk,rst,din,dout); input clk,rst; input din; output dout; //11001101 parameter idle=0,     st0=1,     st1=2,     st2=3,     st3=4,     st4=5,     st5=6,     st6=7; reg current_state,next_state; reg dout; always @ (posedge clk or negedge rst) begin  if(!rst)   current_state=idle;  else   current_state=next_state; end   always @ (next_state or current_state or din or dout) begin  case(current_state)  idle:   if(din)   begin    next_state=st0;    dout=0;   end   else   begin    next_state=idle;    dout=0;   end  st0:   if(din)   begin    next_state=st1;    dout=0;   end   else   begin    next_state=idle;    dout=0;   end  st1:   if(!din)   begin    next_state=st2;    dout=0;   end   else   begin    next_state=st1;    dout=0;   end  st2:   if(!din)   begin    next_state=st3;    dout=0;   end   else   begin    next_state=st0;    dout=0;   end  st3:   if(din)   begin    next_state=st4;    dout=0;   end   else   begin    next_state=idle;    dout=0;   end  st4:   if(din)   begin    next_state=st5;    dout=0;   end   else   begin    next_state=idle;    dout=0;   end  st5:   if(!din)   begin    next_state=st6;    dout=0;   end   else   begin    next_state=st1;    dout=0;   end  st6:   if(din)   begin    next_state=idle;    dout=1;   end   else   begin    next_state=idle;    dout=0;   end  default:   begin    next_state=idle;    dout=0;    end  endcase end     endmodule FSM3:三段式 module machine_test2(clk,rst,din,dout); input clk,rst; input din; output dout; //11001101 parameter idle=0,     st0=1,     st1=2,     st2=3,     st3=4,     st4=5,     st5=6,     st6=7,     st7=8; reg current_state,next_state; reg dout; always @ (posedge clk or negedge rst) begin  if(!rst)   current_state=idle;  else   current_state=next_state; end   always @ (next_state or current_state or din or dout) begin  case(current_state)  idle:   if(din)    next_state=st0;   else    next_state=idle;  st0:   if(din)    next_state=st1;   else    next_state=idle;  st1:   if(!din)    next_state=st2;   else    next_state=st1;  st2:   if(!din)    next_state=st3;   else    next_state=st0;  st3:   if(din)    next_state=st4;   else    next_state=idle;  st4:   if(din)    next_state=st5;   else    next_state=idle;  st5:   if(!din)    next_state=st6;   else    next_state=st1;  st6:   if(din)    next_state=st7;   else    next_state=idle;  st7:   if(din)    next_state=st1;   else    next_state=idle;  default:   next_state=idle;  endcase end     always @ (posedge clk) begin  if(next_state==st7)   dout=1'd1;  else   dout=1'd0; end      endmodule
  • 热度 27
    2014-9-1 23:37
    9875 次阅读|
    1 个评论
    什么是状态机? 简单来说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。硬件的并行性决定了用 Verilog 描述的硬件实现(譬如不同的 always 语句)都是并行执行的,那么如果希望分多个时间完成一个任务,怎么办?也许可以用多个使能信号来衔接多个不同的模块,但这样做显得有些繁琐。状态机的提出大大简化这一工作。 硬件设计很讲究并行设计思想, 虽然用 Verilog 描述的电路大都是并行实现,但是对于实际工程应用,往往需要让硬件来实现一些具有一定顺序的工作,这就是要用到状态机的思想 。(以上摘自特权同学的《深入浅出玩转 FPGA 》一书)   有限状态机 FSM ( Finite State Machine )是数字电路设计中的常用模块。 组成元素:输入、状态、状态转移条件、输出 分类: Mealy 状态机 :时序逻辑的输出不仅取决于当前状态,还与输入有关; Moore 状态机 :时序逻辑的输出只与当前状态有关; 描述方式: 1. 状态转移图:设计分析时使用,工具自动翻译的代码效率不高,适合规模小的设计;对于大规模设计, HDL 更好;                     2. 状态转移表;                     3. HDL 描述; 设计步骤: 1. 逻辑抽象,得到状态转移图:确定输入、输出、状态变量、画状态转移图;                     2. 状态简化,得到最简的状态转移图:合并等价状态;                     3. 状态编码: binary 、 gray 、 one-hot 编码方式;                     4. 用 HDL 描述; 写法:一般有三种写法,他们在速度、面积、代码可维护性等各个方面互有优劣。       一段式 :   只有一个 always block ,把所有的逻辑(输入、输出、状态)都在一个 always block 中实现;这种写法看起来很简洁,但是不利于维护。如果状态复杂一些就很容易出错。不推荐这种方法,但是在简单的状态机可以使用。        二段式 :  有两个 always block ,把时序逻辑和组合逻辑分隔开来。时序逻辑里进行当前状态和下一状态的切换,组合逻辑实现各个输入、输出以及状态判断。这种写法不仅便于阅读、理解、维护,而且利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。在两段式描述中,当前状态的输出用组合逻辑实现,可能存在竞争和冒险,产生毛刺。则要求对状态机的输出用寄存器打一拍,但很多情况不允许插入寄存器节拍,此时使用三段式描述。其优势在于能够根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而不需要额外插入时钟节拍。         三段式 : 有三个 always block ,一个时序逻辑采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件、描述状态转移规律,第三个模块使用同步时序的方式描述每个状态的输出。代码容易维护,时序逻辑的输出解决了两段式组合逻辑的毛刺问题,但是从资源消耗的角度上看,三段式的资源消耗多一些,且输出比另外两种会延时一个时钟周期。 应用:接口控制,协议转换和处理,以及处理器设计等等。 我们以 1101 序列检测器为例: 1101 序列检测器 Mealy 状态机状态转移图 1101 序列检测器 Moore 状态机状态转移图 我们以 Mealy 状态机为例 一段式状态机 (部分核心代码) : 两段式状态机 (部分核心代码) : 三段式状态机(部分核心代码): 三种方式的状态机的写法,使用 Quartus II 的 State Machine Viewer 观察状态转移图都是: Testbench : module ex3_tb; reg    clk; reg    rst_n; reg    in; wire   out; ex3 i_ex3(             .clk        (clk  ) ,             .rst_n      (rst_n) ,             .in         (in   ) ,             .out        (out  )           );                   initial begin      clk = 1;      forever  #10 clk = ~clk; end initial begin      rst_n = 0;      in = 0;      #1000;      rst_n = 1;      in = 1;      #20;      in = 1;      #20;      in = 1;      #20;      in = 0;      #20;      in = 1;      #20;      in = 1;      #20;      in = 0;      #20;      in = 1;      #20;      in = 0;      #20;      in = 1;      #1000;      $stop; end endmodule Modelsim 仿真结果: 有什么不对的地方欢迎大家批评指正!!!