トップ:http://galaxy.u-aizu.ac.jp/note/wiki/CAEX2017 = マルチサイクルプロセッサの制御 = マルチサイクルプロセッサでは、ひとつの命令を複数のステップ(サイクル)に渡って実現します。 その各ステップで利用する信号、モジュールが異なります。その動作をまとめたものが以下の状態遷移図です。 状態遷移図:[http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex08%20%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E5%88%B6%E5%BE%A12017/FSM.pdf PDF] この状態遷移図では状態は0から12の13状態が定義されています。 各状態には、その時に出力されるべき信号名とその値が書いてあります。 例えばR形式命令の場合、1サイクルごとに「0→1→6→7」と遷移することがわかります。 他の命令の場合も「0→1」の遷移は共通です。状態0は命令フェッチ、状態1は命令デコード&レジスタ読み出しをおこないます。 === 状態0では、以下の動作が同時に実施されます === * メモリから現在のPCのアドレスにある命令を読み出す。 * PC+4を計算してPCを更新する。 そのためメモリのアドレスにはPCの値を入力すると同時にメモリを読み込むための信号(!MemRead)を真に(アサート)します。 またメモリから読み出す値が命令かデータかを判別する信号IoDは、偽に(ネゲート)します。 さらに、IRWriteをアサートすることで、読み出された命令がメモリレジスタ(MDR)に保持されます。 ALUの入力AにはPCの値を入力するため、それを制御する信号ALUSrcAはネゲートします。 ALUの入力Bには"4"を入力するので、それを制御する信号ALUSrcB(3 bit)は"001"となり、 ALUは加算をするため、それを制御する信号ALUOp(2 bit)は"00"とします。 その結果をPCレジスタに書き込むため、PCWriteはアサートされ、PCSource(2 bit)は"00"となります。 === 状態1では、以下の動作が同時に実施されます === * 次のサイクルで計算に利用するレジスタファイルの値を読み出す * ジャンプ先のアドレス(PC+オフセット)を計算する この時に必要な動作は、主としてALUでのアドレス計算です。 ALUの入力AにはPCの値を入力するため、それを制御する信号ALUSrcAはネゲートします。 ALUの入力Bにはアドレスのオフセットを入力するので、それを制御する信号ALUSrcBは"011"となります。 この時入力される値は、状態0で読み出された命令の下位16ビットを符号拡張して2ビット左シフトした値となります。 状態0と同様に、ALUは加算をするためALUOp(2 bit)は"00"とします。 またレジスタファイルから読み出された値は、A, Bレジスタに保持されます。読み出すレジスタの番号は命令の該当部分を利用します。 === 状態6では、以下の動作が同時に実施されます === この場合R形式命令を実行するので、ALUでレジスタ間の演算をおこないます。 * ALUにはA, Bレジスタをそれぞれ入力する * 命令に応じてALUでの演算をおこなう * 結果はALUレジスタに保持される そのためALUSrcAはアサートされ、ALUSrcBは"000"となります。ALUでのおこなう演算を制御する信号ALUOpは"10"とします。 === 状態7では、以下の動作が同時に実施されます === * ALUレジスタに保持された値を指定されたレジスタに書き込む この時、ALUは利用しません。レジスタファイルへの書き込みを制御する信号RegWriteはアサートされます。 また、書き込むレジスタファイルの番号を制御する信号RegDstもアサートされます。 レジスタファイルには、ALUレジスタの値を書き込むため、それを制御するMemtoRegはネゲートされます。 == 以上の各サイクルでR形式命令を実現できます。 == 他の命令の場合、つまりLW命令、SW命令、BEQ命令等の場合にも、同様に状態遷移をしながら、 各状態での信号が変化していくことを理解してください。 == 制御部の設計(1) == 制御部モジュールのテンプレートは以下のようになります。 {{{ module ControlUnit(PCWriteCond, PCWrite, IorD, MemRead, MemWrite, MemtoReg, IRWrite, PCSource, ALUOp, ALUSrcB, ALUSrcA, RegWrite, RegDST, Op, CK, CLR); // clock input CK; input CLR; // opcode (6 bit) input [5:0] Op; // 1 bit control signal output PCWriteCond; output PCWrite; output IorD; output MemRead; output MemWrite; output MemtoReg; output IRWrite; output RegWrite; output RegDST; output ALUSrcA; // 2 bit control signal output [1:0] PCSource; output [1:0] ALUOp; output [2:0] ALUSrcB; // register declaration reg PCWriteCond; reg PCWrite; reg IorD; reg MemRead; reg MemWrite; reg MemtoReg; reg IRWrite; reg [1:0] PCSource; reg [1:0] ALUOp; reg [2:0] ALUSrcB; reg ALUSrcA; reg RegWrite; reg RegDST; // state register reg [3:0] state; endmodule // ControlUnit }}} 入力信号はOpとCK(クロック信号)とCLR(リセット信号)で、その他は出力になります。 Op信号はMIPS命令コードの25-31ビットの部分です。各命令コードごとのOp信号を以下のテーブルに示します。 == 命令コード == || 命令の種類 || opcode(10進数) || || R形式 || 0 || || Load Word || 35 || || Store Word || 43 || || Branch on EQ|| 4 || || ADD imm || 8 || || SLT imm || 10 || || AND imm || 12 || || ORI imm || 13 || 注意:R形式命令では、命令コードの0-5ビットの部分で演算の種類を指定します。 == 例題 == 状態遷移図から、R形式命令の実行には4サイクル必要になります。 このことを、以下のファイルを使ってシミュレーションを行い確かめなさい。 状態遷移のみの制御回路 [http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex08%20%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E5%88%B6%E5%BE%A12017/ControlUnit_1.v ControlUnit_1.v] テストベンチファイル [http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex08%20%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E5%88%B6%E5%BE%A12017/CUbench_1.v CUbench_1.v] === 実行例 === それぞれのファイルをダウンロードまたは保存して、以下のコマンドを実行。 {{{ ncverilog CUbench_1.v }}} この状態遷移の回路では、always文の部分はCLKが上向きに変化する時に状態が遷移します。 また、CLR信号が真になったら状態0になります(リセット)。 そのため状態遷移を行う時にはCLR信号を適切に変化させる必要があります。 === 実行波形 === [[Image(http://galaxy.u-aizu.ac.jp/comparch2014/image/CUbench1.png, 800)]] == 課題1 == LW命令とADDI命令の場合に、例題を参考にテストベンチファイルを作成して、 シミュレーションを行い、実行波形を確認してください。 それぞれの場合、実行までに何サイクル必要かを考えること。 = 制御部の設計(2) = 各状態における出力信号を定義すると、以下のファイルのようになります。 ただし、このファイルでは、状態0と1の場合のみ記述してあります。 未完成の制御回路 [http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex08%20%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E5%88%B6%E5%BE%A12017/ControlUnit_2.v ControlUnit_2.v] == 課題2 == 全ての状態の場合の出力信号を定義して、主制御ユニット(ファイル名は"!ControlUnit.v")を完成させること。 === 制御回路の動作確認 === テストベンチファイルの例 [http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex08%20%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E5%88%B6%E5%BE%A12017/CUbench_2.v CUbench_2.v] このテストベンチファイルを実行し、各命令(LW, SW, RTYPE命令, BEQ, JMP, ADDI, SLTI, ANDI, ORI)ごとに、 状態番号stateごとに正しい信号が出力されていることを確認してください。 例えばLW命令の場合は、state=0では: {{{ state= 0: MemRead=1,ALUSrcA=0,IorD=0,IRWrite=1,ALUSrcB=001,ALUOp=00,PCWrite=1,PCSource=00 }}} と出力されます。これを状態遷移図を比べて、正しいかどうかを確認してください。 [[Image(http://galaxy.u-aizu.ac.jp/comparch2014/image/comparch_ex8.png)]] 他の命令と他のstateについても同様に確認すること。 注意:状態遷移図には各状態で変化する信号のみが書いてあります。例えばMemReadはstate = 0, 3の時は真であるべきですが、それ以外の状態では偽になっている必要があります。そのためstate = 1ではMemReadは偽になっています。他のstateの時も同様です。 == 動作確認 == RTYPE命令とJMP命令の場合の波形を表示して、TAに動作確認を受けること。