2008/12/23

Spartan3 PCIバス付きFPGA評価ボード(12) - 状態遷移不正続き

前回のエントリの状態遷移不正ですが、まだ一部おかしいところがありました。

#003367: AD fa000000, CBE 8(mw ), FRAME# H, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 0, app 0
#003368: AD 87654321, CBE f(---), FRAME# L, DEVSEL# L, IRDY# H, TRDY# L, STOP# L, stat 0, app 0
#003369: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 1, app 0


このstat 0->stat 0の箇所です。状態0はIDLE状態、状態1はアドレス取り込みの状態で、本来IDLE状態でFRAME#がH('0')を検出したら、アドレス取り込み状態へ遷移しなければなりません(少なくとも書いた人の意図は ;-))

VHDLはこんな感じになっています。

-- BUS idle
when IDLE =>
if (N_FRAME_IO = '0' and N_IRDY_IO = '1') then
buscommand <= N_CBE_IO;
address <= AD_IO;
idsel <= IDSEL_I;
nxtstate := ADDR;
else
nxtstate := IDLE;
end if;

-- Address decode
when ADDR =>
if (Hit_device = '1') then
N_DEVSEL_IO <= '0';
TRDY_PORT <= '1';
-- deassert STOP#
STOP_PORT <= '1';
nxtstate := IRDY;
else
nxtstate := BUSY;
end if;


ごく単純な状態遷移機械を書いたつもりなのですが、どうしても一拍待って?しまっています。

良くわからずWebを彷徨っていたら、「状態遷移機械と次状態計算とデータ出力は分けて書いたほうがいい」というTIPSがありました。

要は、

  state <= nextstate

を行うprocess文(状態遷移機械)と、

when state =>
nextstate <= ST_XXX;

を行う組み合わせロジック(次状態計算)と、

when state =>
datax <= xxx;
datay <= yyy;

といったデータ出力ロジックを分けて書けということのようです。

若干半信半疑ながら、そのTIPSにしたがって対処したら綺麗にIDLEステートからADDRステートへ遷移するようになりました。

IDLE(0)→ADDR(1)→IRDY待ち(3)→appcore待ち(4)→DISCONNECT(7)/COMPLETE(5)→COMPLETE2(6)→IDLEという一連の状態遷移が期待通りにできるようになりました。0xfa000004へのライトはバースト転送になっていますが、きちんとDISCONNECTで打ち切っています。

[WRITE]
#00169c: AD fa000000, CBE 8(mw ), FRAME# H, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 0, app 0
#00169d: AD 87654321, CBE f(---), FRAME# L, DEVSEL# L, IRDY# H, TRDY# L, STOP# L, stat 1, app 0
#00169e: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 3, app 0
#00169f: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 0
#0016a0: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 0
#0016a1: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 3
#0016a2: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# H, STOP# H, stat 5, app 5
#0016a3: AD 87654321, CBE f(---), FRAME# L, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 6, app 0
#0016a6: AD fa000004, CBE 8(mw ), FRAME# H, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 0, app 0
#0016a7: AD 87654321, CBE f(---), FRAME# H, DEVSEL# L, IRDY# H, TRDY# L, STOP# L, stat 1, app 0
#0016a8: AD 87654321, CBE f(---), FRAME# H, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 3, app 0
#0016a9: AD 87654321, CBE f(---), FRAME# H, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 0
#0016aa: AD 87654321, CBE f(---), FRAME# H, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 0
#0016ab: AD 87654321, CBE f(---), FRAME# H, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 3
#0016ac: AD 87654321, CBE f(---), FRAME# H, DEVSEL# H, IRDY# H, TRDY# H, STOP# H, stat 5, app 5
#0016ad: AD 87654321, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# H, stat 7, app 0
#0016ae: AD 87654321, CBE f(---), FRAME# L, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 6, app 0

[READ]
#0048e4: AD fa000000, CBE 9(mr ), FRAME# H, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 0, app 0
#0048e5: AD fa000000, CBE f(---), FRAME# L, DEVSEL# L, IRDY# H, TRDY# L, STOP# L, stat 1, app 0
#0048e6: AD fa000000, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 3, app 0
#0048e7: AD fa000000, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 0
#0048e8: AD fa000000, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 0
#0048e9: AD deadbeef, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# L, STOP# L, stat 4, app 3
#0048ea: AD deadbeef, CBE f(---), FRAME# L, DEVSEL# H, IRDY# H, TRDY# H, STOP# H, stat 5, app 5
#0048eb: AD deadbeef, CBE f(---), FRAME# L, DEVSEL# L, IRDY# L, TRDY# L, STOP# L, stat 6, app 0

論理的にはまったく同じように見えるのに、ハードウェアは奥が深いなあ。結局、回路のレベルでは何か違いが(タイミング問題とか)あるんでしょうけど、解明できていません。

それはそれとして、上のように分けて書くと、if文が二箇所に分散するのであまり記述性がよろしくないと思うのですが、どんなもんなんでしょうね。

0 件のコメント: