【Day15】状态机的撰写

什麽是状态机呢?

状态机,其实是有限状态机(finite-state machine(FSM))的简称,字面上来看可以知道它是有有限个状态,并且可以按照着特定的顺序来完成各个状态内的动作,这使数位电路也能按着想要的顺序完成特定的动作,例如某种演算法、某种传输协定等等。


状态的编码方式

常见的编码有以下三种:

  • 二进制编码
  • Gray code(格雷码)
  • One Hot

三种编码方式各自的优缺点

二进制编码

优点:

  • 可使用较少 bit 数的 register 来跑状态,n 个状态只需要 log2(n) 个 bit 的 register,在状态很多时能有效节省 register 数量,有助於面积的减小。
  • 编码规则较简单,采用数字递增的方式来编码即可。

缺点:

  • 会综合出较多的组合逻辑。
  • 在状态与状态之间转跳时,因为有多 bit 同时变化的情况发生,如此一来容易在次态的生成逻辑上产生 glitch(毛刺)。
  • 加上输出与状态有关,又二进制编码复杂的关系造成,容易成为整体电路的 critical path。

Gray code(格雷码)

优点:

  • 一样与二进制编码相同,可使用较少 bit 数(log2(n) bit)的 register 来跑状态。
  • 格雷码的特点是,上一个数字与下一个数字之间只差 1 bit 的变化,可以改善二进制编码中 glitch 的问题。

缺点:

  • 虽然可以改善二进制编码的缺点,但前提是状态的变化是依照顺序的,否则就失去这优势了,但实际上几乎不可能状态都按着顺序跳,所以这的编码方法几乎与二进制编码效果差不多。

One Hot

EX:

//One-Hot
localparam IDLE  = 4'b0001;
localparam START = 4'b0010;
localparam SHIFT = 4'b0100;
localparam STOP  = 4'b1000;

优点:

  • 状态与状态之间的变化最少 1 bit 而最多只会有 2 bit 的变化。
  • 因为 bit 变化少,组合逻辑资源也会相对较少。

缺点:

  • 跑状态的 register 需要花费较多的 bit 数,若 n 个状态则要 n 个 bit 的 register。

下面来看一个简单状态机的范例~

module testFSM(
  clkSys, 
  rst_n,
  en,
  out
);
/*--------localparam--------*/
localparam one   = 2'd0;
localparam two   = 2'd1;
localparam three = 2'd2;
localparam four  = 2'd3;
/*--------ports declarations--------*/
input       clkSys;
input       rst_n;
input       en;
output [2:0]out;
reg    [2:0]out;
/*--------variables--------*/
reg    [1:0]fstate;
/*--------state--------*/
always@(posedge clkSys or negedge rst_n)begin
  if(!rst_n)fstate <= one;
  else begin
    case(fstate)
      one:begin
        if(en)fstate <= two;
        else  fstate <= one;
      end
      two:begin
        if(en)fstate <= three;
        else  fstate <= two;
      end
      three:begin
        if(en)fstate <= four;
        else  fstate <= three;
      end
      four:begin
        if(en)fstate <= one;
        else  fstate <= four;
      end
      default:fstate <= one;
    endcase
  end
end
/*--------output--------*/
always@(posedge clkSys or negedge rst_n)begin
  if(!rst_n)out <= 3'd0;
  else begin
    case(fstate)
        one:    out <= 3'd1;
        two:    out <= 3'd2;
        three:  out <= 3'd3;
        four:   out <= 3'd4;
        default:out <= 3'd0;
    endcase
  end
end
endmodule

TestBench


`timescale 10ns/1ns
module tb_testFSM();
reg       clkSys;
reg       rst_n;
reg       en;
wire [2:0]out;
testFSM UUT(
  .clkSys(clkSys), 
  .rst_n(rst_n),
  .en(en),
  .out(out)
);

initial begin
  clkSys = 0;
  rst_n = 0;
  en = 0;
  repeat(2)@(posedge clkSys)rst_n = 0;
  rst_n = 1;
  en = 1;
  #20  en = 0;
  #40;
  en = 1;
  #20  en = 0;
  #40;
  en = 1;
  #20  en = 0;
  #40;
  en = 1;
  #20  en = 0;
  #100 $stop;
end

always #10 clkSys = ~clkSys;

endmodule

Wave

state machine

上面的例子,状态是以二进制编码来表示的,我自己的状态机是以两段式为主,并且输出逻辑为了 timing 更好,在 output logic 会再多敲一级 clk(循序逻辑),可以看到一个 always 处理状态的转移,而另一个 always 负责在该状态输出对应的信号,在这个例子中,在每一个状态内都要在 clk 为正缘时并且读到 en 为 "1" 时才会进入下一个状态,否则留在原状态等待 en 的来临。


<<:  Day18 - 建立追踪清单画面

>>:  Day 15 网页分析 - Web Application Analysis (网页快照截图 - cutycapt )

【Day26】快速乘法器的实作(Booth演算法)

为什麽要自己写乘法器? 这篇会来教大家写一个乘法器,那麽你可能会想:为什麽会需要乘法器呢?像我在 q...

EP 10 - [TDD] Message 加密及解密 (2/2)

Youtube 频道:https://www.youtube.com/c/kaochenlong ...

Day 03 - 任你存S3

云端服务的一项重点服务是资料储存,今天让我们一起来瞧瞧AWS上的资料储存服务-S3。 1. 为何要用...

【Day 26】JavaScript AJAX - XMLHttpRequest

说明 : 藉由 XMLHttpRequest(XHR)物件的方式来存取服务器端的资料,可以直接经由指...

Golang 学习笔记-- 快速上手/重点整理 - 2 - var, const

print import ("fmt") fmt.Println('hello'...