FSMの練習
from FPGA Prototyping by SystemVerilog Examples
FSMの状態遷移は、現在のステートと外部からの入力によって決まる
「状態遷移図(state diagram)」と「ASMチャート」
状態遷移図
コンパクト
シンプルなアプリ向け
ASMチャート
フローチャートみたいな書き方
細かく記述できる
複雑な状態遷移やアクションがあるものに向いてる
状態遷移図
https://gyazo.com/d63f54fdea2fdc69db7ea58d866a1541
ASMチャート
https://gyazo.com/12a423a7735a5acd3e267f12e09d2fbd
FSMの例
https://gyazo.com/52cb3c1d56ae55cb0041b258207b7ae2
マルチセグメントコード
116ページ
「next_stageロジック」と「outputロジック」をそれぞれ別の場所に置いたもの(always や assignを分ける)
code:verilog
module fsm_eg_mult_seg(
input logic clk, reset,
input logic a, b,
output logic y0, y1
);
// fsm state type
typedef enum {s0, s1, s2} state_type;
// signal declaration
state_type state_reg, state_next;
// state register
always_ff @(posedge clk, posedge reset)
if (reset)
state_reg <= s0;
else
state_reg <= state_next;
// next-state logic
always_comb
case (state_reg)
s0: if (a)
if (b)
state_next = s2;
else
state_next = s1;
else
state_next = s0;
s1: if (a)
state_next = s0;
else
state_next = s1;
s2: state_next = s0;
default: state_next = s0;
endcase
// Moore output logic
assign y1 = (state_reg == s0) || (state_reg == s1);
// Mealy output logic
assign y0 = (state_reg==s0) & a & b;
endmodule
ツーセグメントコード
「next-stageロジック」と「outputロジック」をひとつのブロックにまとめたもの
code:verilog
module fsm_eg_2_seg(
input logic clk, reset,
input logic a, b,
output logic y0, y1
);
typedef enum {s0, s1, s2} state_type;
state_type state_reg, state_next;
always_ff @(posedge clk, posedge reset)
if (reset)
state_reg <= s0;
else
state_reg <= state_next;
always_comb begin
// default values
state_next = state_reg;
y1 = 1'b0;
y0 = 1'b0;
case (state_reg)
s0: begin
y1 = 1'b1;
if (a)
if (b) begin
state_next = s2;
y0 = 1'b1;
end else
state_next = s1;
end
s1: begin
y1 = 1'b1;
if (a)
state_next = s0;
end
s2: state_next = s0;
default state_next = s0;
endcase
end
endmodule
マルチセグメントとツーセグメント
ステートの遷移(next-stageロジック)と出力ロジックの always ブロックを分けるのが「マルチセグメント」
同じalwaysブロックに書くのが「ツーセグメント」
always を分けるマルチセグメントの方が読みやすそう?
気付き
今書いてるCPUは、state以外の出力ロジックも next~ の形式で書いてたせいでごちゃごちゃしてたので、以下のように整理したい
state は next~ の形式に
出力ロジックは、next~ を使わず、現在のステートに合わせて出力( y0 = 1'b1 みたいな感じ)
assign でも良い