MacでVerilogのシミュレーションをしてみる3

MacでVerilogのシミュレーションをしてみる1 - k-igrsの日記

MacでVerilogのシミュレーションをしてみる2 - k-igrsの日記

の続き

このままではアドレスを順にインクリメントしていくだけなので、実行アドレスを変更するJump命令を追加する。

Jump命令は01h,その後のメモリにJumpするアドレスを格納する。

なので、ステートマシンはデコードの時にPCをインクリメントしておき、Jumpアドレスを読み込むステートに遷移する。その後、PCに読み込んだJumpアドレスを格納してFetchステートに戻る。

f:id:k_igrs:20210703053415j:plain

Jump命令を定義する。

parameter OP_JMP = 8'h01;

分岐先を指定する信号を定義する。

wire [2:0] state_sel;

FetchしたオペコードがJump命令ならステートマシンにJumpのパスへ分岐するようにする。

assign path_jump = (op_code == OP_JMP ) ? 3'b001 : 3'b000;

assign state_sel = path_jump;

Decodeステートの後はメモリリードとなるのでRDBをアクティブにする。

// Make Read pulse                                          
assign pre_rdb =
    ( Q == 4'b1111)                         ? 1'b0 :        
    ( Q == 4'b0010)                         ? 1'b0 :        
    ((Q == 4'b0001) && (op_code == OP_JMP)) ? 1'b0 : 
    ( Q == 4'b0100)                         ? 1'b0 : 1'b1;  

 メモリから読み込んだJumpアドレスをラッチする。

always @( posedge CK, negedge RB )
    if ( RB == 1'b0 )
            jmp_adrs <= 10'h000;
    else
        if ( Q == 4'b0011 )
            jmp_adrs = DI[9:0];

 ステートマシンにJumpへの分岐とJumpのステートを追加する。

            4'b0001:begin
                if ( STATE_SEL == 3'b000 )
                    Q <= 4'b0010;
                else if ( STATE_SEL == 3'b001 ) begin
                    Q <= 4'b0011;
                    PC <= PC + 1;
                end
            end
            4'b0011: begin
                Q <= 4'b0100;
            end

            4'b0100: begin
                Q <= 4'b0000;
                PC <= JMP_ADRS;
            end

メモリデータに jump命令を追加してシミュレーションを実行して確認する。

0000
0001
0002
0100 <- Jump命令
000a <-飛び先
0005
0006

 実行結果

f:id:k_igrs:20210703063402p:plain