| | 1 | トップ:http://galaxy.u-aizu.ac.jp/note/wiki/CAEX2016 |
| | 2 | |
| | 3 | = 準備 = |
| | 4 | 今週から、MIPSプロセッサを設計します。 |
| | 5 | そのために、VerilogHDLを用いた記述方法、シミュレータ、波形ビューアなどの各種CADツールの使いかたを習得します。 |
| | 6 | |
| | 7 | == シミュレーションのためのログイン == |
| | 8 | {{{ |
| | 9 | ssh -X hdw1dc |
| | 10 | }}} |
| | 11 | |
| | 12 | simvisionのウインドウが開かない場合には、 |
| | 13 | |
| | 14 | {{{ |
| | 15 | /bin/ssh -X hdw1dc |
| | 16 | }}} |
| | 17 | でログインすること。 |
| | 18 | |
| | 19 | hostnameは各自の目の前の計算機にすること。 |
| | 20 | |
| | 21 | |
| | 22 | = ALUモジュールの設計と検証 = |
| | 23 | 算術論理演算ユニット(arithmetic logic unit, ALU)は、加算や減算などの算術演算や、 |
| | 24 | ANDやORなどの論理演算を行うプロセッサの中枢部分です。 |
| | 25 | 今週はMIPSプロセッサで使われる32ビットのALUを作成し、 |
| | 26 | さらにシミュレーションによって動作検証をします。 |
| | 27 | |
| | 28 | 今回設計するALUの入出力信号は次の図の通りです。 |
| | 29 | AとBは入力でどちらも32ビット幅です。 |
| | 30 | ALU制御入力(ALUoperation)は4ビット幅の入力で、演算の種類を指定します。 |
| | 31 | 演算結果(ALUresult)も32ビットで出力されます。 |
| | 32 | ゼロ判定出力(Zero)は演算結果が32ビットとも0であるときに1となる信号です。 |
| | 33 | |
| | 34 | [[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex04%E8%AA%B2%E9%A1%8C2015/alu.gif)]] |
| | 35 | |
| | 36 | このALUでは下に示す6種類の演算をサポートします。第4版上巻p.290参照。 |
| | 37 | |
| | 38 | || ALU制御入力 || 機能 || |
| | 39 | || 0b0000 || AND || |
| | 40 | || 0b0001 || OR || |
| | 41 | || 0b0010 || 加算 || |
| | 42 | || 0b0110 || 減算 || |
| | 43 | || 0b0111 || Set on less than || |
| | 44 | || 0b1100 || NOR || |
| | 45 | |
| | 46 | ANDは2つの入力の各ビットの論理積、ORは論理和を実行することを意味します。 |
| | 47 | Set on less than は比較命令で利用される演算で、2つの入力の大小関係によって 0 または 1 を次の表のように出力します。 |
| | 48 | |
| | 49 | || || ALUの出力 || |
| | 50 | || A < B || 0x00000001 || |
| | 51 | || A ≧ B || 0x00000000 || |
| | 52 | |
| | 53 | 今回作成するプロセッサでは、加算、減算実行時にはオーバフローは想定しません。 |
| | 54 | オーバフローが発生した場合でも、下位のbitは正しい値が出力されるように設計します。 |
| | 55 | |
| | 56 | == ALUモジュールの作成 == |
| | 57 | ALUは3つの入力A,B,ALUoperation、2つの出力ALUresultとZeroをもちます。 |
| | 58 | |
| | 59 | 以下は、ALUモジュールのVerilog HDL記述です。 |
| | 60 | {{{ |
| | 61 | module ALU(A,B,ALUoperation,ALUresult,Zero); |
| | 62 | |
| | 63 | input [31:0] A; |
| | 64 | input [31:0] B; |
| | 65 | input [3:0] ALUoperation; |
| | 66 | output [31:0] ALUresult; |
| | 67 | output Zero; |
| | 68 | |
| | 69 | reg [31:0] ALUresult; |
| | 70 | wire [32:0] tmp; |
| | 71 | |
| | 72 | // Output Zero is defined by assign statement |
| | 73 | assign Zero = (ALUresult == 0)? 1'b1 : 1'b0; |
| | 74 | |
| | 75 | // tmp is the result of A - B, in 33bit |
| | 76 | assign tmp = {A[31], A} - {B[31], B}; |
| | 77 | |
| | 78 | // Output ALUresult is defined by always statement |
| | 79 | always @(A or B or ALUoperation or tmp) |
| | 80 | begin case( ALUoperation ) |
| | 81 | 4'b0000 : ALUresult <= A & B; |
| | 82 | 4'b0001 : ALUresult <= A | B; |
| | 83 | 4'b0010 : ALUresult <= A + B; |
| | 84 | 4'b0110 : ALUresult <= A - B; |
| | 85 | 4'b0111 : ALUresult <= {31'b0, tmp[32]}; |
| | 86 | 4'b1100 : ALUresult <= (~A) & (~B); |
| | 87 | default : ALUresult <= 32'b0; |
| | 88 | endcase |
| | 89 | end |
| | 90 | |
| | 91 | endmodule |
| | 92 | }}} |
| | 93 | |
| | 94 | 上記の記述をファイル名「ALU.v」として保存します。 |
| | 95 | 以下の演習では、ファイル名は「(モジュール名).v」としてください。 |
| | 96 | また、1つのファイルには1つのモジュールを定義します。 |
| | 97 | |
| | 98 | VerilogHDLの記述方法は、参考図書を参考にしてください。 |
| | 99 | この記述では、抽象度の高いBehaviorレベルでの設計が行われています。 |
| | 100 | |
| | 101 | このALU記述では、assign文とalways文を用いています。 |
| | 102 | 両方をalways文で設計することもできます. |
| | 103 | 加減算、大小比較は、VerilogHDLの算術演算を用いて実現しています。 |
| | 104 | |
| | 105 | 加減算における入力AとBは2の補数で表された符号付き32bitデータです。 |
| | 106 | 下位31ビットが数をあらわし、最上位ビットが符号を表します。 |
| | 107 | |
| | 108 | == インスタンス化について == |
| | 109 | VerilogHDLでモジュールを利用するには、その定義をするだけでなく、その実体を作り出す必要があります。 |
| | 110 | これをインスタンス化といいます。 |
| | 111 | |
| | 112 | 参考書では、18ページ「3.1.2 全加算器のHDL記述」に説明があります。 |
| | 113 | 図3.4がその例となっていて、ここではfull_adder回路の定義の中で、half_adder回路を2つインスタンス化しています。 |
| | 114 | "i0"と"i1"はインスタンスの名前で、他のインスタンスと重ならない任意の名前をつけることができます。 |
| | 115 | |
| | 116 | 図3.4では、明示的に信号の接続を記述していますが、以下のように省略して記述できます。 |
| | 117 | この場合には、並んでいる順番に信号が接続されます。 |
| | 118 | {{{ |
| | 119 | module full_adder(a, b, ci, s, co); |
| | 120 | input a, b, ci; |
| | 121 | output s, co; |
| | 122 | wire w0, w1, w2; |
| | 123 | |
| | 124 | assign co = w1 | w2; |
| | 125 | half_adder i0 (w1, w0, a, b); // half_adder i0 (.co(w1), .s(w0), .a(a), .b(b)); |
| | 126 | half_adder i1 (w2, s, w0, ci); // half_adder i1 (.co(w2), .s(s), .a(w0), .b(ci)); |
| | 127 | endmodule |
| | 128 | }}} |
| | 129 | |
| | 130 | == テストベンチの作成 == |
| | 131 | 作成したALUが正しく動作するかどうかシミュレーションによって確認します。 |
| | 132 | すべての入力値の組み合わせについてチェックするのは 不可能ですから(非常に時間がかかる)、 |
| | 133 | 下の表に示されている入力の組み合わせについてシミュレーションを行い、出力が期待値と一致することを確認します。 |
| | 134 | |
| | 135 | まず、テストパターンをシミュレーションするためのテストベンチのテンプレートを示します。 |
| | 136 | {{{ |
| | 137 | `timescale 1ns/1ps |
| | 138 | |
| | 139 | `include "ALU.v" // Include statement of ALU module |
| | 140 | |
| | 141 | module ALUtestbench; // testbench module ALUtestbench do not have inputs and output |
| | 142 | |
| | 143 | reg [31:0] inA; |
| | 144 | reg [31:0] inB; |
| | 145 | reg [3:0] inALUop; |
| | 146 | wire [31:0] outALUresult; |
| | 147 | wire outZero; |
| | 148 | |
| | 149 | ALU alu(inA,inB,inALUop,outALUresult,outZero); // Instance definition |
| | 150 | |
| | 151 | initial |
| | 152 | begin |
| | 153 | |
| | 154 | $dumpfile("ALUtestbench.vcd"); //Function call for the save of execution results as VCD format to |
| | 155 | $dumpvars(0, alu); //Function call to specify the top module |
| | 156 | |
| | 157 | #0 inALUop = 4'b0000; inA= 32'h00000000; inB = 32'h00000000; //Setting of inputs |
| | 158 | |
| | 159 | #100 //Time passes. ALU operates for inputs. |
| | 160 | |
| | 161 | $display( $time, " ALUoperation=%h, A=%h, B=%h, ALUresult=%h, Zero=%h",inALUop,inA,inB,outALUresult,outZero); |
| | 162 | // Display of inputs and outputs |
| | 163 | |
| | 164 | inALUop = 4'b0000; inA= 32'h0F0F0F0F; inB = 32'hF0F0F0F0; |
| | 165 | |
| | 166 | #100 |
| | 167 | |
| | 168 | $display( $time, " ALUoperation=%h, A=%h, B=%h, ALUresult=%h, Zero=%h",inALUop,inA,inB,outALUresult,outZero); |
| | 169 | |
| | 170 | .... |
| | 171 | // In this space, describe other testbench descriptions |
| | 172 | .... |
| | 173 | |
| | 174 | inALUop = 4'b0000; inA= 32'h00000000; inB = 32'h00000000; // dummy input |
| | 175 | $finish; |
| | 176 | end |
| | 177 | endmodule |
| | 178 | }}} |
| | 179 | |
| | 180 | このテストベンチ記述を完成させます。ファイル名は「ALUtestbench.v」とします。 |
| | 181 | |
| | 182 | このテストベンチを実行すると、$DISPLAY文により結果がテキスト形式で表示され、 |
| | 183 | 同時に$dumpfileと$dumpvars文によりVCD形式でファイル「ALUtestbench.vcd」に保存されます。 |
| | 184 | |
| | 185 | {{{ |
| | 186 | ALU alu(inA,inB,inALUop,outALUresult,outZero); // Instance definition |
| | 187 | }}} |
| | 188 | の行で、ALUモジュールをインスタンス化しています。接続は省略記法でおこなっていることに注意してください。 |
| | 189 | |
| | 190 | == テストベンチの実行 == |
| | 191 | シミュレータは「nverilog」コマンドを使います。 |
| | 192 | |
| | 193 | {{{ |
| | 194 | ncverilog ALUtestbench.v |
| | 195 | }}} |
| | 196 | |
| | 197 | というコマンドで、テストベンチを実行することができます。 |
| | 198 | 最初に文法チェックが行われるので,そこでエラーが発生したら、ファイルを修正してください。 |
| | 199 | エラーがなくなったら、テストベンチが実行されます。 |
| | 200 | $display文による実行結果を確認してください。 |
| | 201 | 実行途中の全ての信号の状態は「ALUtestbench.vcd」に保存されます。 |
| | 202 | |
| | 203 | 波形ビューアsimvisionを用いて実行結果を確認します。 |
| | 204 | simvision起動後、File -> Open Database で、シミュレーションで作成したVCDファイル「ALUtestbench.vcd」を選択します。 |
| | 205 | ファイルの種類をVCD Fileにして、ファイルを選択すること。 |
| | 206 | これ以降は、今までCadenceの統合環境icdsでの作業と同じです。 |
| | 207 | 確認したい信号名を選んで、右上の波形マークをクリックして、波形を確認します。 |
| | 208 | |
| | 209 | = 今週の課題 = |
| | 210 | 下の入力パターンを全て「ALUtestbench.v」に追加して、ALUの動作を確認してください。 |
| | 211 | 演習時間内に動作確認をおこなうので、挙手してTAまたは教員に動作を示すこと。 |
| | 212 | |
| | 213 | [[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex04%E8%AA%B2%E9%A1%8C2015/test.png)]] |