トップ:http://galaxy.u-aizu.ac.jp/note/wiki/CAEX2016 = データパスの完成 = == 課題1 == これまでに作成・利用したモジュールを組み合わせて、データパスを完成させてください。 データパスとは、ブロック図で、全体制御部とALU制御部を除いた部分のことです。 データパスの入出力は、クロック信号CK、クリア信号CLR、制御部と接続される各信号(32ビットの命令および、RegDstなどの信号)です。 制御部との接続は、例えば、RegWriteという入力ポートを宣言し、 その入力がレジスタファイルの所定の入力につながるように (レジスタファイルをインスタンス宣言し、宣言のなかの入出力ポートにRegWriteを含めておく)します。 データバスの出力は、ZeroFlag、OP(制御部に接続する)とINST_0_5(ALU制御部に接続する、命令の下位6ビット部分) データパスのテンプレートは以下になります。なお、インスタンス化するモジュールをincludeすること。 === Datapath module === {{{ ... module Datapath(PCwriteCond, PCWrite, IorD, MemRead, MemWrite, MemtoReg, IRwrite, PCSource, ALUop, ALUSrcB, ALUSrcA, RegWrite, RegDST, PCload, ZeroFlag, INST_0_5, OP, CK, CLR); input CK, CLR; // 1 bit control input PCwriteCond, PCWrite, IorD, MemRead, MemWrite, MemtoReg, IRwrite; input ALUSrcA, RegWrite, RegDST, PCload; // 2 bit control input [1:0] PCSource, ALUop; // 3 bit control input [2:0] ALUSrcB; // output ZeroFlag; // ALU zero flag output [5:0] OP; output [5:0] INST_0_5; ... endmodule }}} = 全体の完成 = == 課題2 == マルチサイクルプロセッサ全体を「MIPSmulticyle」とし、以下のテンプレートに従い、 これまで設計したモジュールをインスタンス化し、プロセッサを完成させてください。 テンプレートではCK, CLRとGenPCLに関する信号のみ接続しています。他の信号の接続は各自おこなうこと。 {{{ module MIPSmulticycle(CK, CLR); input CK, CLR; wire PCWriteCond, PCWrite, ZeroFlag, PCload; // 必要な信号をさらに加える // データパスのインスタンス化 Datapath MCDP (.CK(CK), .CLR(CLR), .ZeroFlag(ZeroFlag), .PCwriteCond(PCwriteCond), .PCWrite(PCWrite), .PCload(PCLoad)); // Three control units ALUControl alucnt (); ControlUnit cntunit (.CK(CK), .CLR(CLR)); GenPCL genpcload (PCwriteCond, PCWrite, ZeroFlag, PCload); endmodule }}} 「GenPCL」は、ブロック図左上のPCWriteCondとPCwriteとZeroFlagから、PCをロードする信号を生成するモジュールです。 それ以外のものは、入出力の信号名のみ記述します。 {{{ module GenPCL(PCWriteCond, PCWrite, ZeroFlag, PCload); input PCWriteCond, PCWrite, ZeroFlag; output PCload; assign PCload = (PCWriteCond && ZeroFlag) || PCWrite; endmodule }}} == テストベンチの例 == MIPSmulticycleモジュールのテストベンチの例は以下のようになります。 {{{ `timescale 1ns/1ps `include "MIPSmulticycle.v" module MIPStestbench; reg ck,clear; MIPSmulticycle mips(ck,clear); initial begin $dumpfile("MIPStestbench.vcd"); $dumpvars(0, mips); // memory initialization // #0 ck = 1'b1; clear = 1'b1; #110 clear = 1'b0; #90 #1000 // execute 10 cycles $finish; end always #50 CK <= ~CK; endmodule }}} == エラーチェック == テストベンチを利用して、文法エラーがないかを確認すること。 {{{ ncverilog MIPStestbench.v }}} = ブロック図の確認方法 = ncverilogコマンドでテストベンチの文法ミスがなくなり、シミュレーションが可能になったら、以下のようにしてモジュールとその間の接続を確認できます。 == PPEオプションで実行する == {{{ ncverilog +PPE MIPSmulticycle.v }}} しばらくするとSimvisionのウインドウが開きます。 [[Image(http://galaxy.u-aizu.ac.jp/g/data/8955add0bfbde43a3a3c811c70c02ccb.png)]] == マルチサイクルプロセッサのトップモジュールを選択 == [[Image(http://galaxy.u-aizu.ac.jp/g/data/e1e50afda8fa300a147053d161621c17.png)]] == 右クリックして「Send to New」から「Schematic Tracer」を選択 == [[Image(http://galaxy.u-aizu.ac.jp/g/data/e4af225341376dc74d0a7dfda80abaa7.png)]] === ブロック図のウインドウが開き、トップモジュールが表示される === [[Image(http://galaxy.u-aizu.ac.jp/g/data/12b78356bd1d1731da7fbaa1a74a547d.png)]] == モジュールをダブルクリックするとブロック図と配線が確認できます == [[Image(http://galaxy.u-aizu.ac.jp/g/data/9eedd1265793a4f18494dd7965a067c5.png)]] モジュール間の配線が間違っていないかをブロック図で把握して下さい。 = 課題3 マルチサイクルプロセッサの動作確認 = 個々の命令をひとつひとつ実行することで、マルチサイクルプロセッサをデバッグします。 テストベンチの例は以下のようになります。 {{{ `timescale 1ns/1ps `include "MIPSmulticycle.v" module MIPStestbench; reg ck,clear; MIPSmulticycle mips(ck,clear); initial begin $dumpfile("MIPStestbench.vcd"); $dumpvars(0, mips); // memory initialization #0 ck = 1'b1; clear = 1'b1; #110 clear = 1'b0; #90 #1000 // execute 10 cycles $finish; end always #50 CK <= ~CK; endmodule }}} 「memory initialization」の部分には、xspimで生成したメモリの初期化ファイルを組合せます。 == テスト用アセンブリコード == http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex09%E8%AA%B2%E9%A1%8C2016/test_instructions.s 1. xspimでプログラムをロードし「dump」ボタンを押す。"testfixture.include"というファイルが生成されます。 1. これから実行するプログラムの実行サイクルを見積ります。各命令は3 - 4サイクル必要ですので、多めにとって5サイクルで換算してください。ループがある場合には、繰り返し回数を考慮してください。 1. テストベンチのテンプレートに"testfixture.include"を挿入してください。 最初から全てのプログラムをテストするのではなく、簡単な命令から動作を確認すること。 == デバッグの方法 == === CLRとPCを確認する === CLR(リセット信号)が0になってからPCの値が0, 4, 8と増えていくはずです。 プログラムの最後はジャンプ命令のため、プログラムが終了するとPCの値は0xa0と0x9cを繰り返すはずです。 まずは、PCの値が正しく変化しているかを確認してください。 === 命令の動作を制御部から調べる === 制御部分のstate信号を値を確認してください。 これは状態遷移図にもとづいて変化するはずなので、命令ごとに状態遷移図と比べてください。 === 命令実行の詳細確認 === stateが0の時に、PCの出力が正しい命令のアドレスを指しているかを確認してください。 さらに、命令メモリの出力が正しい命令コードになっているかを確認してください。 次に、stateが1の時に命令レジスタの出力が正しいかを確認すること。 ==== 算術命令の場合の例 ==== stateは1から6に遷移します。この時に二つのレジスタにそれぞれ正しい値ロードされているかを確認すること。 また、ALUSrcA, B, ALUOpの値を、状態遷移図で定義された値と比べて確認してください。 次にALUの計算結果が正しいかを調べること。 state 6からはstate 7に遷移します。ここで!RegDst, !RegWrite, MemtoRegが正しいかを確認してください。 レジスタファイルに書き込まれたかどうかを確認するには、次のクロックでstateが0に遷移したところで、 該当するレジスタファイルの部分を調べてください。 ==== 他の命令 ==== 算術命令と同様の方針で、stateの変化毎に制御信号が正しいか、レジスタの値が正しく読み書きできているかを確認すること。 == __動作確認のチェック__ == 今週と次週の演習時間内に、TAの動作チェックをうけてください。 この動作確認は第3回レポートの点数に含みます。配点は12点(25点満点中)とします。 TAからOKがでたら、課題4をおこなうこと。 = 課題4 プログラムの実行 = 全ての命令の実行が正しくなったら、 第2回の演習で作成した乗算のプログラムが正しく動作することを確認しなさい。 なお、xpsim用にADDU命令とした部分は、ADD命令に置き換える必要があるので、注意すること。