オリジナル命令の追加検討
本内容を参考にして、各自オリジナル命令の追加を
検討してください。
オリジナル命令の追加例として、ここではNAND命令の追加を行ってみます。
命令仕様の定義:
NAND命令は2項演算ですから、OR、AND、EOR演算と同様に処理することができま
す。
アドレッシングモードとして、即値アドレッシングとインデクス修飾アドレッシ
ングを実現することにします。
命令コードの定義:
NAND命令の命令コード(オペレーションコード)を決定する必要があります。
KITE-1の命令セット表を眺めると、命令の上位ビットから、
“101110″
が使用されていないことがわかります。
ここを、命令コードとして使用することにします。
即値アドレッシングは“10111001″(0xB9)
インデクス修飾アドレッシングは“10111010″(0xBA)
になります。
opecode.v に命令を定義します。
...
`define IR_ROR 6'b101101
`define IR_NAND 6'b101110 // NAND命令追加
`define IR_SWP 6'b101111
...
ALUへの演算追加:
ALUへ新たなNAND演算を追加するわけですが、ALUは既に16演算が定義されており、
制御信号CBも4ビットであるため、新たな命令を追加するためには制御信号CBを5
ビットに拡張する必要があります。
また、演算処理を行う際、ALUの制御コードはそのまま演算命令の第13〜10ビッ
トに対応するように命令は定義されていました。追加しようとしているNAND 命
令は命令の第13〜10ビットが“1110″になりますが、ALUの制御信号では既
にパス演算が定義されています。
これでは不都合ですから、NAND演算を“01110″として定義し、パス演算を
“10000″として再定義することにします。
alu_op.v は以下のようになります。
//
// ALU operations
//
`define IADD 5'b00000
...
`define INAND 5'b01110 // NAND演算追加
...
`define IPAS 5'b10000 // PASS演算コードの再定義
alu.v は以下のようになります。
module alu (A, B, CB, S, F);
...
input [ 4:0] CB; // 制御コード拡張
...
always @( ... )
begin
case ( ... )
...
`INAND : tmp <= { 1'b0, ~( A & B ) }; // NAND演算追加
...
default : tmp <= { 1'b0, A }; // IPAS
endcase
end
...
endmodule
ALU制御信号配線の拡張
ALUの制御信号を4ビットから5ビットに拡張したため、ALUの制御信号に関連する
部分をすべて5ビットに拡張しておく必要があります。
kite.v 階層は、ALUとデコーダ・シーケンサとの間でALU制御信号を連結してい
ます。
...
wire [ 4:0] ALU_C; // for ALU Control (制御コード拡張)
...
デコーダ・シーケンサの拡張
最後にデコーダ・シーケンサ部(dec_seq.v)ですが、まずALUの制御信号を5ビッ
トに拡張します。
...
output [4:0] ALU; // 制御コード拡張
...
reg [4:0] ALU; // 制御コード拡張
...
命令のデコードを記述します。OR、AND、EOR命令と同じステートにより処理でき
るので、同一の処理ステートへ遷移すればOKです。
...
case ( `OP_6 )
`IR_NAND : if( `OP_M==`IMM ) STATE<=`BIOP_IMM_1; else
if( `OP_M==`IDX ) STATE<=`BIOP_IDX_1; else
STATE<=`F1;
...
即値アドレッシングの場合とインデクス修飾アドレッシングでは、命令レジスタ
からの値の呼出し方が異なります。
論理演算の即値アドレッシングではアキュムレータの上位8ビットがそのまま残
るように演算していました。NAND命令でも同様にしますが、NANDの場合は結果が
反転しますので、アキュムレータの上位8ビットの反転した値が残るようにしま
す。
インデクス修飾アドレッシングでは、命令の下位8ビットはインデクスレジスタ
の加算値として使用しますが、その際、符号拡張します。
//------------------------------------------------------------------//
// BRANCH flag & SIGN flag are made from IR and FR
//------------------------------------------------------------------//
always @( ... )
begin
...
default :
case ( `OP_6 )
...
`IR_NAND : if ( `OP_M==`IMM ) SIGN<=1; else SIGN<=IR[7];
...
endcase
endcase
end
制御信号生成については、そのまま手を加える必要がありません。
理由は、OR、AND、EORの論理演算と共通の処理で実現できるようにALUの制御信
号および命令デコーダを再定義したからです。
以下のソースにおいて、
ALU<=`OP_A;
の記述が、同一のステートで個々の演算を実現できるようにしている部分です。
但し、ALU制御信号は5ビット、`OP_A は opecode.v では IR[13:10] と4ビット
で定義されています。
代入の際に第4ビットが1ビット足りませんが、Verilog
HDLでは1ビットの0が付加されるのでこのままで大丈夫です。
気になる人は、
ALU<= { 1'b0 , `OP_A };
のように記述するか、`OP_A の定義を、
`define OP_A IR[14:10] // ALU制御コードの拡張
にすればOKです。
...
//
// BIOP Index
// ADD, SUB, OR, EOR, AND, NAND
`BIOP_IDX_1 :
begin
IXR_R<=1; AR_W1<=1;
IR_R8P2 <= !SIGN;
IR_R8M2 <= SIGN;
ALU <= `IADD;
end
`BIOP_IDX_2 : MREQ<=1;
`BIOP_IDX_3 : begin MREQ<=1; ACC_R<=1; ACC_W<=1; ALU<=`OP_A;
FR_W<=1; DBI2<=1; ICS<=1; end
...
変更箇所は以上です。
次は、 シミュレーション により追加した
NAND命令が正しく動作しているか確認します。
| CAD Home |