2

Verilog で作業してきた 16 ビット シングル サイクルの非常にまばらな MIPS 実装があります。分岐が 1 クロック サイクル全体で遅延するという事実を除いて、すべてが機能します。

always @(posedge clock) begin
    // Necessary to add this in order to ensure PC => PC_next
    iaddr <= pc_next 
end

上記のコードは、モジュール PCLogic から取得されるプログラム カウンター/命令アドレスを更新するために使用されます。

module PCLogic(
        pc_next,    // next value of the pc
        pc,     // current pc value
        signext,    // from sign extend circuit
        branch, // beq instruction
        alu_zero,   // zero from ALU, used in cond branch
        reset       // reset input
        );

output [15:0] pc_next;
input [15:0] pc;
input [15:0] signext;  // From sign extend circuit
input branch;
input alu_zero;
input reset;

reg [15:0] pc_next; 

    always @(pc or reset) begin
        if (reset == 1)
            pc_next = 0;
        else if (branch == 1 && alu_zero == 1)
            pc_next = pc+2+(signext << 1);
        else
            pc_next = pc+2;
    end

endmodule

iaddrプログラム カウンタを格納する単純な 16 ビット レジスタです。

なぜこの回路に問題があるのか​​ わかりませんが、何らかの理由で、回路全体が分岐するまで 1 クロック サイクル遅延します (たとえば、0x16 に常にジャンプする BEQ 命令がある場合、それは実行されます)。 0x18 で次の命令を実行し、0x20 から相対オフセットにジャンプします)。

解決策が目の前にあるような気がしますが、セマンティックについて何が欠けているのかわかりません。+2真の「バブル」またはハードウェアによるノーオペレーションがない限り、常に暗黙的な を削除すると、オフセットの問題は解決しますが、遅延は依然として存在します。

誰かが遅延の原因とその理由を説明できますか?

4

2 に答える 2

2

組み合わせ回路をコーディングする別の方法:

reg [15:0] pc_next; 

always @* begin
    if (reset == 1)
        pc_next = 0;
    else if (branch == 1 && alu_zero == 1)
        pc_next = pc+2+(signext << 1);
    else
        pc_next = pc+2; // latch will be inferred without this
end

ネストされた if-else がたくさんあると assign ステートメントが読みにくいため、組み合わせ回路がより複雑になると、これが必要になります。

これに関する注意

pc_next = pc+2; // latch will be inferred without this

組み合わせブロックにはデフォルト値が必要です。条件ステートメントにデフォルト値が定義されていない場合、その値が保持され、正しくない動作につながります。組み合わせブロックは値を保持してはなりません。

予期しないラッチの詳細については、これを参照してください。

于 2015-12-02T04:35:58.757 に答える