8bit CPUの命令長設定

今回の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