Make/Day

毎日なにか作ります

21日目 ~ALU~

こんにちは!今日はついにALUの機能紹介と実装を行います。また、テストベンチの実装は次回になるため、今回紹介するコードは参考書籍の環境での検証までしか行っていません。使用する際は、自己責任でお願いしますm(_ _)m

対象となるALUはNand2tetris(参考書籍)で紹介されている、"Hack"とします。
よって、実装する命令は以下の18種類となります。

  • 0
  • 1
  • -1
  • x
  • y
  • NOT(!x)
  • NOT(!y)
  • -x
  • -y
  • x+1
  • y+1
  • x-1
  • y-1
  • ADD(x+y)
  • SUB(x-y)
  • SUB(y-x)
  • AND
  • OR

ALUのこれらの動作を制御するbitは全部で6本になり、
それぞれ入力xを0にする(zx)、反転する(nx)、入力yを0にする(zy)、反転する(ny)、AddかAndの関数の選択bit(f)、出力の反転(no)を指示します。
これらの制御ビットは信号を選択するマルチプレクサのセレクト信号として働かせます。
従って、これらの機能を実現するように回路図を書くと、

ALUの実装

となります。それぞれの動きは、マルチプレクサごとに切って追ってみると分かりやすいと思います。
また、回路図中にOrゲートはありませんが、NotとAndゲートによりうまく実現されていることがわかります。このように、設計の段階で非常にうまく考えられている為、今回はこのALUを使用させて頂きました。

そして、上図と、そこから更に16bitの等号比較と負判定の機能を出力に持たせたALU(out信号をさらに加工するので、上図のALU回路に変更はない) をVerilog HDLで記述すると以下のようになります。

module ALU (
    input [15:0] x, y,
    input zx, nx, zy, ny, f, no,
    output [15:0] out,
    output zr, ng
);
    wire [15:0] zxout, invxout, nxout, zyout, invyout,
                nyout, addout, andout, fout, fnout, functout, middle;
    wire lowout, highout, nzr;

    //zx
    Mux16 U0(x, 16'b0, zx, zxout);    
    //nx
    Not16 U1(zxout, invxout);
    Mux16 U2(zxout, invxout, nx, nxout);
    
    //zy
    Mux16 U3(y, 16'b0, zy, zyout);
    //ny
    Not16 U4(zyout, invyout);
    Mux16 U5(zyout, invyout, ny, nyout);
    // 入力操作はここまで

    //function_code
    Add16 U6(nxout, nyout, addout);
    And16 U7(nxout, nyout, andout);
    Mux16 U8(andout, addout, f, fout);

    //out + ng
    Not16 U9(fout, fnout);
    Mux16 U10(fout, fnout, no, middle);
    And16 U11(middle, middle, out);
    And U12(1'b1, middle[15], ng);
    
    //zr
    Or8Way U13(middle[7:0], lowout);
    Or8Way U14(middle[15:8], highout);
    Or  U15(lowout, highout, nzr);
    Not U16(nzr, zr);
endmodule

これでコンピュータの自作に用いる組み合わせ回路の大部分は実装してしまいました。
次回以降はテストベンチを用いたこの回路の検証、そして前回ちょろっと出した順序回路の実装へとシフトしていきます。

参考書籍