今日は、ファイルレジスタコントローラです。「ファイルレジスタコントローラ」は私がテキトーにつけた名称ですが、普通のコンピュータシステムでいうところの、メモリとI/Oである、「ファイルレジスタ」への読み書きを制御する部分です。機能は3つ。
1)アドレス生成
2)ライトイネーブル生成
3)リードイネーブル生成
「アドレスの生成」は、ファイルレジスタをオペランドにする命令で、インストラクションのfスライス(下位7ビット)が0以外の場合は、fスライスがダイレクトアドレスに、0の場合はfsrレジスタによるインダイレクトアドレスを生成します。上位のビットを、ステータスレジスタのrp,irpスライスで補完します。実際にはデコーダを簡略化するため、「ファイルレジスタをオペランドにする命令」かどうかの判断は省略しています。
「ライトイネーブル」は命令をデコードして、演算結果の格納先がファイルレジスタになる場合を抽出しています。
「リードイネーブル」も同様です。当初、リードイネーブルは不要かとも思ったのですが、よく考えたら,I/Oは読み出しに「副作用」が伴う(たとえば、UARTとか)場合があるので、やっぱり必要ですね。
そろそろ、また適当プログラムを動かして、動作確認をしたいのですが、CPUと対向するレジスタファイルを用意しないといけません。(めんどくせー)
---
本日の御託
トラ技(2007/9)を買いました。実は、先月号からちょっと読みたい連載(dsPICじゃないよ、笑)があって買ったのだが、今回はあんまり面白くなかった・・・orz
//
// File Resister controler
//
//
// file register controller
// (c)2007 BakaOyaji
// $Id$
//
`include "yap16_instructions.h"
`include "yap16_def.h"
module file_reg_controller (
input [( `YAP16_INST_WIDTH -1):0] instruction_i ,
input [7:0] fsr_i , // from FSR reg
input irp_i , // from irp of STATUS reg
input [1:0] rp_i , // from rp of STATUS reg
output [(`YAP16_FA_WIDTH -1):0] fr_addr_o, // address of file registers
output we_o, // write enable to file registers
output re_o // read enable to file registers
);
reg we, re ;
wire [6:0] f ; // FILE# fireld in the instruction
assign { we_o, re_o } = {we, re};
// address generation
assign f = instruction_i[6:0] ;
assign fr_addr_o =
( f == 7'h00 )
? {irp_i, fsr_i} // Indirect addressing, status[7] is IRP
: {rp_i ,f}; // Direct addressing, status[6:5] is RP1,0
// re
always@ * begin // ( instruction_i ) begin
re <= 1'b0 ;
casex( instruction_i)
`YAP16_INST_ADDWF ,
`YAP16_INST_ANDWF ,
`YAP16_INST_COMF ,
`YAP16_INST_DECF ,
`YAP16_INST_DECFSZ ,
`YAP16_INST_INCF ,
`YAP16_INST_INCFSZ ,
`YAP16_INST_IORWF ,
`YAP16_INST_MOVF ,
`YAP16_INST_RLF ,
`YAP16_INST_RRF ,
`YAP16_INST_SUBWF ,
`YAP16_INST_SWAPF ,
`YAP16_INST_XORWF ,
`YAP16_INST_BCF ,
`YAP16_INST_BSF ,
`YAP16_INST_BTFSC ,
`YAP16_INST_BTFSS : begin
re <= 1'b1 ;
end
default : begin
re <= 1'b0 ;
end
endcase // casex
end // always
// we
always@ * begin // ( instruction_i ) begin
we <= 1'b0 ;
casex( instruction_i)
`YAP16_INST_ADDWF ,
`YAP16_INST_ANDWF ,
`YAP16_INST_CLRF ,
`YAP16_INST_DECF ,
`YAP16_INST_DECFSZ ,
`YAP16_INST_INCF ,
`YAP16_INST_INCFSZ ,
`YAP16_INST_IORWF ,
`YAP16_INST_MOVF ,
`YAP16_INST_MOVWF ,
`YAP16_INST_RLF ,
`YAP16_INST_RRF ,
`YAP16_INST_SUBWF ,
`YAP16_INST_SWAPF ,
`YAP16_INST_XORWF :
we <= instruction_i[7] ;
`YAP16_INST_BCF ,
`YAP16_INST_BSF :
we <= 1'b1 ;
default :
we <= 1'b0 ;
endcase // casex
end // always
endmodule // file_reg_controller
// EOF file_reg_controller.v