リセットには同期リセットと非同期リセットがあります。同期リセットと非同 期リセットのどちらを選択するかは、設計思想に関わるため一概にどちらがい いとはいい切れません。一般的にはディジタルシステムの電源投入時のように、 システム全体のリセット(スーパーリセットということもある)は非同期リセッ トにするといわれています。また、今回は Xilinx 社の FPGA を実装対象デバ イスとしていますが、このデバイスでは非同期リセットを使用した方が回路が 小さくなります。そこで今回は非同期リセットを使用します。
KITEマイクロプロセッサでは、プロセッサ内部のレジスタの内容を常時チップ 外に出力しておき、それを観測できるようにしています。そのため、アキュム レータ、スタックポインタ、インデクスレジスタ、プログラムカウンタの各レ ジスタは常時内容を出力しておく出力端子を用意しておいて下さい。(プロセッ サの動作には直接関係ありません。)命令レジスタ、フラグレジスタおよびア ドレスレジスタは常に値を出力しておく必要がありますが、観測用にはこの出 力を利用しています。
レジスタの記述は以下を参考にして下さい。
module acc (I, T, O, CLK, RST, W, R); input [15:0] I; output [15:0] T; output [15:0] O; input CLK; input RST; input W; input R; reg [15:0] tmp; // for Register always @( posedge RST or posedge CLK ) begin if ( RST == 1'b1 ) tmp <= ... else if ( W == 1'b1 ) tmp <= ... end assign O = ... ; assign T = ( ... ) ? ... : ... ; endmodule
12ビットのレジスタですが、内部バスは16ビットであるため、バスへの入
出力は16ビットにします。出力時はレジスタの12ビットに加え上位4ビッ
トは"0000"にしておきます。
インデクスレジスタとスタックポインタは記述が全く同じなので、ファイルも
1つだけ用意すれば事足ります。
module r12 (I, T, O, CLK, RST, W, R); input [11:0] I; output [15:0] T; output [11:0] O; input CLK; input RST; input W; input R; reg [11:0] tmp; // for Register always @( posedge RST or posedge CLK ) begin if ( RST == 1 ) tmp <= ... ; else if ( W == 1 ) tmp <= ... ; end assign O = ... ; assign T = ( ... ) ? ... : ... ; endmodule
12ビットのレジスタですが、内部バスは16ビットであるため、バスへの入 出力は16ビットにします。出力時はレジスタの12ビットに加え上位4ビッ トは"0000"にしておきます。次の命令をフェッチするためにプログラムカウン タを+1するための機能を入れておく必要があります。
module pc (I, T, O, CLK, RST, W, R, P); input [11:0] I; output [15:0] T; output [11:0] O; input CLK; input RST; input W; input R; input P; reg [11:0] tmp; // for Register always @( posedge RST or posedge CLK ) begin if ( RST == 1 ) tmp <= ... ; else if ( W == 1 ) tmp <= ... ; else if ( P == 1 ) tmp <= ... ; end assign O = ... ; assign T = ( ... ) ? ... : ... ; endmodule
レジスタの内容は常時出力しておきます。レジスタへの書き込みにおいては、 3バス構成の場合2つのバスから書換えられるようにしておく必要があります。 外部からのリセット信号はセット信号として取り扱います。 つまり、リセット時はレジスタの内容がすべて"1"になるようにします。
module ar (I1, I2, O, CLK, SET, W1, W2); input [11:0] I1; input [11:0] I2; output [11:0] O; input CLK; input SET; input W1; input W2; reg [11:0] tmp; // for Register always @( posedge SET or posedge CLK ) begin if ( SET == 1 ) tmp <= ... ; else if ( W1 == 1 ) tmp <= ... ; else if ( W2 == 1 ) tmp <= ... ; end assign O = ... ; endmodule
レジスタの内容は常時出力しておきます。
module fr (I, O, CLK, RST, W); input [3:0] I; output [3:0] O; input CLK; input RST; input W; reg [3:0] tmp; // for Register always @( posedge RST or posedge CLK ) begin if ( RST == 1'b1 ) tmp <= ... ; else if ( W == 1'b1 ) tmp <= ... ; end assign O = ... ; endmodule
レジスタの内容は常時出力とバスへの出力が2つあります。さらに、バスへの 出力はそれぞれ2通りの出力の仕方があります。
// // Instruction Register // module ir (I, T1, T2, O, CLK, RST, W, R12, R8P1, R8P2, R8M2); input [15:0] I; output [15:0] T1; output [15:0] T2; output [15:0] O; input CLK; input RST; input W; input R12, R8P1, R8P2, R8M2; reg [15:0] tmp; // for Register reg [15:0] ..., ...; // always による組み合わせ回路で必要な宣言 always @( posedge RST or posedge CLK ) begin if ( RST == 1'b1 ) tmp <= ... ; else if ( W == 1'b1 ) tmp <= ... ; end assign O = ... ; // // Output Control for 1st DATA Bus // always @( tmp or R12 or R8P1 ) begin if ( R12 == 1'b1 ) ... <= ... ; else if ( R8P1 == 1'b1 ) ... <= ... ; else ... <= ... ; end // // Output Control for 2nd DATA Bus // always @( tmp or R8P2 or R8M2 ) begin if ( R8P2 == 1'b1 ) ... <= ... ; else if ( R8M2 == 1'b1 ) ... <= ... ; else ... <= ... ; end endmodule
レジスタは構成が簡単なので、まず間違えることはないと思います。
シミュレーションをスキップしてデコーダ・シーケンサの設計に進む場合はこちらへ。
レジスタの動作をシミュレーションによりチェックする場合はこちらへ。