今回のCPUでは、デコード時に命令長を確定させないといけないのだけど、その処理を書いてなかった。
DE0で8bit CPUのデコーダを動かす
で、すでに非常に大きなcase文ができあがってて、そこにちくちくと命令長を設定していくのは非常に面倒だしミスも多そうと思って放置していた。
そんなところで、別の文脈だけど、 natsutanさんからアドバイスもらって、ソフトウェアじゃないんだからひとつの分岐ですべての処理をすませる必要はないのだなと気付いた。
Z80作成日記をみて思ったことをつらつらと - ぱたヘネ
というわけで、命令ごとの命令長を整理してみる。
そうすると、ほとんどが1で、わずかに2・3のところがあることがわかる。
こうやって分けて整理したほうが簡単な記述にできるし、ソフトウェアの場合と違って分岐の回数が増えても単純に実行効率が悪くなるわけでもない。むしろレイテンシが少なくなるかもしれない。
で、実装してみて、LCDに命令長も表示するようにしてみた。
よく考えたら7セグが2ケタあまってるんで、わざわざLCDに表示することもなかったのだけど、やはりLCDにまとめていろいろ情報を表示できるのは便利。
LCDの制御もだいぶ慣れた。
今回追加したコードはこんな感じ
always @(code) begin case(sect) 2'b01,2'b10: op_len <= 1; 2'b00:begin if(subop[2:0] == 6)begin op_len <= 2; end else if(subop == 1)begin op_len <= 3; end else begin case(code) 8'h20,8'h30,8'h18,8'h28: op_len <= 2; 8'h22,8'h32,8'h38,8'h2a,8'h3a: op_len <= 3; default: op_len <= 1; endcase end end 2'b11:begin if(subop[2:0] == 6)begin op_len <= 2; end else begin case(code) 8'hc2,8'hd2,8'hc3,8'hca,8'hda: op_len <= 3; 8'hd3,8'hdb: op_len <= 2; default: op_len <= 1; endcase end end endcase end