4 |
BSVにおけるコマンドバッファ制御 (13) |
ChatGPTのコードがあまり良くないので、次の考え方で整理してコードを修正します。
元の処理はbusyを内部演奏状態に使用すると同時に外部にbusyを見せていたので、プリエンプティブではなかった。この2つを分離し、playを内部演奏状態とし、外部には受取りの1サイクルのみbusyを立てるようにしてください。
以下に変更したコードを示します。
package Consumer4;
interface Consumer4Ifc;
method Action consume(UInt#(4) x);
endinterface
module mkConsumer4 (Consumer4Ifc);
Reg#(UInt#(4)) cnt <- mkReg(0); // 0-14 を数える 4bit で十分
Reg#(Bool) busy <- mkReg(False); // ハンドシェーク停止用 1 サイクル
Reg#(Bool) play <- mkReg(False); // 15 サイクル演奏フラグ
Reg#(UInt#(4)) lastVal <- mkRegU; // 取り込んだコード
/* 15 サイクル演奏タイマ */
rule timer (play);
if (cnt == 14) begin
cnt <= 0;
play <= False; // 演奏終了
end
else
cnt <= cnt + 1;
endrule
/* busy は 1 サイクル後に自動クリア */
rule clear_busy (busy);
busy <= False;
endrule
/* 受信メソッド
ガード if (!busy) を付けることで
can_fire = !busy が自動生成される */
method Action consume(UInt#(4) x) if (!busy);
lastVal <= x; // EN=1 サイクルでラッチ
$display("%0t: consume = %h", $time, x);
busy <= True; // 1 サイクルだけbusyを上げる
play <= True; // 演奏開始
cnt <= 0;
endmethod
endmodule
endpackage