Last update $Id$
(c) 2007 BakaOyaji

インストラクションレジスタの設計

まずは、図6のブロックダイアグラムのなかのインストラクションレ ジスタです。この部分の働きはプログラムメモリから読み出されたデータ(すなわち次に実行する命令)を保持しておくことです。ただし、分岐が起きるとき や、SKIP系の命令でSKIPする場合は、データをゼロクリア(フラッシュ動作)することで、該当するサイクルではNOPを実行させます。
フラッシュ動作する具体的な場合は、
  1. GOTO命令
  2. CALL命令,Return系命令
  3. SKIP系の命令
  4. 割り込み
です。GOTO、CALL、Return系の命令は命令自体分岐なので、命令をデコードするだけで次のサイクルが強制的にNOPになることがわかります が、あとの2つはCPU内 の他のモジュールの状態に依存します。そこで、GOTOとCALLのみ内部でデコードして、インストラクションレジスタ自身でNOPにしてしまいます。残 りは、外部入力でNOPにします。


SYNOPSIS  yap16_ir モジュール

input clk_i クロック入力
input por_i パワーオンリセット
input [(`YAP16_INST_WIDTH -1):0] code_data_i プログラムメモリからのデータ入力
input skip_i 強制SKIP入力// skip
output [(`YAP16_INST_WIDTH -1):0] instruction_o 各部への命令出力
output flush_o フラッシュ発生(未使用)



//
// Instruction register
// force_nop_i signal will override the instruction fetched
// to NOP. This is used for inserting dummy cycle
// at skip, branch, call and 1st stage of interrupt services
//
// Instruction register
// (c) 2007 BakaOyaji
// $Id
//

`include "yap16_def.h"
`include "yap16_instructions.h"
module yap16_ir(
input clk_i,
input por_i ,
input [(`YAP16_INST_WIDTH -1):0] code_data_i ,
input skip_i , // skip , overriding the instruction fetched to NOP
output [(`YAP16_INST_WIDTH -1):0] instruction_o, // the instruction to execute
output flush_o
);

reg [(`YAP16_INST_WIDTH -1):0] instruction ;
reg force_nop ;

assign instruction_o = instruction ;
assign flush_o = force_nop | skip_i | por_i ;

always@ * begin
force_nop <= 1'b0 ;
(* parallel_case *)
casex( instruction )
`YAP16_INST_GOTO,
`YAP16_INST_CALL,
`YAP16_INST_RETURN,
`YAP16_INST_RETFIE,
`YAP16_INST_RETLW : begin
force_nop <= 1'b1 ;
end
default : begin
force_nop <= 1'b0 ;
end
endcase
end // always

always@( posedge clk_i ) begin
if( flush_o ) begin
// instruction <= `Inst_NOP ;
instruction <= 'b00_0000_0000_0000 ;
end // if
else begin
instruction <= code_data_i ;
end // else
end // always
endmodule // yap16_ir
// EOF yap16_ir.v

モジュールの主要な部分は2つのalwaysブロックで構成されています。最初のものが、GOTO、CALL,RETURN系の命令のデコードをしていま す。2番目は、インストラクションレジスタそのものと、強制NOPの機能を実装しています。2番めのalwaysブロックで、強制NOPのために、
            instruction <= 'b00_0000_0000_0000 ; 
という記述があります。論理合成の結果だけを考えれば、
            instruction <= `Inst_NOP ;
としたほうが回路は小さくなる可能性があります。理由は、`Inst_NOPの 定義はは、前のページに書いたように、14'b00_0000_0xx0_0000 なのでxの部分は、Don'tCareで1でも0でも構わないならば、論理合成のツールは回路規模を最小にできるほうを選択するからです(大体は0になる のですが)。
ただ、実際にシミュレーションを実行してみると、xが表示されるのは何かと鬱陶しいのでここでは、素直に「全ビット0」にしています。(この話は Verilogの小ネタで独立させたほうがいいかも)



<<前に戻る   Index へ  次へ>>