Verilog-HDLによる教育用小規模計算機(K-COM4)の設計
1. 機能分解
教育用計算機K-COMを小規模な回路で実現するために,K-COMのアーキテクチャをもとに4ビットCPUを設計した. これをK-COM4と名づけ,Verlilog-HDLによる設計ついて以下に説明する.初学者が理解しやすいように計算機を5つの機能に分けて設計し,最後にそれらを統合する手順で設計を行った. 機能の分割については以下の通りである.
(1)クロックジェネレータ
(2)ALUおよびアキュームレータ
(3)プログラムカウンタおよび命令レジスタ
(4)メモリおよびI/Oポート
(5)コントローラ
2.1 クロックジェネレータの構成
入力された標準クロック(gclk)をもとに半周期ずれた2種類の2分周クロック(tclk,sclk)を出力する。tclkはgclkの立ち下がりで反転するようにし,sclkはgclkの立ち上がりで反転するように作成した.
sclkは計算機の動作時のレジスタ転送の設定を行うクロックで,sclkにより転送準備ができた後に tclkの入力でレジスタの転送が行われるように2つのクロックを他の回路で使用する.
動作波形を図1に示す.
module clock4(reset, gclk, tclk, sclk ); input reset, gclk; output tclk, sclk; reg tclk, sclk; always @(posedge gclk or posedge reset) if (reset) sclk <=0; else sclk <= ~sclk; always @(negedge gclk or posedge reset) if (reset) tclk <=0; else tclk <= ~tclk; endmodule
図1 クロックジェネレータ実行波形
2.2 ALUおよびアキュームレータの構成
Acc,latchおよびデータバス幅は4ビットである.命令レジスタ(ir)は8ビット,選択信号(select)は9ビットである.ALUの動作は,コントローラのselect[5]が1のとき,tclkのタイミングで計算結果をラッチする(latchにデータを保持する).演算は,アキュームレータ(acc)の値とデータバスの値を用いて行い,演算の種類は命令レジスタの上位3ビット(ir[7:5])によって制御される.図2に実行結果を示す.ADD,SUB,NAND命令を順に実行している.
module alu4(reset, tclk, ir, select, acc, latch, c, z, d_bus); input reset, tclk; input [8:0] select; input [7:0] ir; output [3:0] acc, latch; output z,c; inout [3:0] d_bus; reg c,z; reg [3:0] acc, latch; always @(posedge tclk or posedge reset) begin if (reset) begin acc<=0; latch<=0; c<=0; z<=0; end else begin if(select[5]) begin casex(ir[7:5]) 3'b000: begin {c,latch}<=acc + d_bus; z<=((acc + d_bus)==4'b0); end 3'b001: begin {c,latch}<=acc - d_bus; z<=((acc - d_bus)==4'b0); end 3'b010: begin {c,latch}<=~(acc & d_bus); z<=(~(acc & d_bus)==4'b0); end 3'b011: begin {c,latch}<=acc << 1; z<=((acc << 1 )==4'b0); end default: latch<=acc; endcase end if(select[6]) acc<=d_bus; end end assign d_bus= (select[1]) ? latch: 4'bz; endmodule
図2 ALUおよびアキュームレータの実行波形
2.3 プログラムカウンタおよび命令レジスタの構成
プログラムカウンタは5ビットで構成し,通常1ずつカウントアップするが,ジャンプ命令実行時は命令レジスタの下位5ビットの値によってプログラムカウンタの値が直接書き換えられる.命令レジスタは8ビットである.下位4ビット,上位4ビットの順で,4ビットずつデータを読み込んで,8ビットの命令長としている.アドレスバスには,プログラムの読み出しまたは命令実行時のいずれかで,プログラムカウンタの値または命令レジスタの下位5ビットの値のいずれかが出力される.これらの動作は選択信号(select)のいずれかのビットの値によって制御される. この回路の実行波形を図3に示す.pcのカウントアップ動作と,irの下位5ビットの値がアドレスバスに出力する様子が確認できる.
module pcir4(reset, tclk, halt, pc, ir, a_bus, d_bus, select); input reset, tclk; input [3:0] d_bus; input [8:0] select; output halt; output [4:0] a_bus; output [4:0] pc; output [7:0] ir; reg [4:0] pc; reg [7:0] ir; always @(posedge tclk or posedge reset) begin if (reset) begin pc<=0; ir<=0; end else begin if(select[7]) pc<=ir[4:0]; else if(select[4]) pc<=pc+5'b1; else if(select[3]) ir[3:0]<=d_bus; else if(select[8]) ir[7:4]<=d_bus; end end assign a_bus=(select[0])? pc: ir[4:0]; assign halt=(ir==8'hff); endmodule
図3 プログラムカウンタおよび命令レジスタの実行波形
2.4. メモリおよびI/Oポート
メモリは,アドレスバスで指定されたメモリ内容の呼び出し,または指定されたアドレスへのデータの書き込みを行う. メモリの定義は,4ビット×32バイトを宣言しているが,ROM領域と入出力ポート使用時は別に処理を記述している. メモリの0番地~9番地をROMとして9EH,BFH,44H,E0H,00Hを下位4ビット,上位4ビットの順であらかじめプログラムを書き込んでいる. また,I/Oポートはメモリの30番地を入力ポート,31番地を出力ポートとしている.動作波形例について図4に示す.10番地へのデータの書き込みおよび読み出しの確認,入出力ポートの動作確認を行っている.
module mem4(tclk, a_bus, inp, oup, select, d_bus); input tclk; input [4:0] a_bus; input [3:0] inp; input [8:0] select; output [3:0] oup; inout [3:0] d_bus; reg [3:0] mem[0:31]; reg [3:0] oup; function [3:0] memout; // memory read input [4:0] a_bus; case(a_bus) 0:memout =4'hE; 1:memout =4'h9; 2:memout =4'hF; 3:memout =4'hB; 4:memout =4'h4; 5:memout =4'h4; 6:memout =4'h0; 7:memout =4'hE; 8:memout =4'h0; 9:memout =4'h0; 30:memout =inp; default: memout =mem[a_bus]; endcase endfunction always @(posedge tclk) begin if(select[2] & select[1]) // memory write if (a_bus==31) oup <= d_bus; else mem[a_bus] <= d_bus; end assign d_bus = (~select[2] & ~select[1])? memout(a_bus): 4'bz; endmodule
図4 メモリおよびI/Oポートの実行波形
2.5 コントローラ
K-COM4のフェッチ動作は,命令レジスタの下位4ビット分の取り込み,PCをカウントアップ,上位4ビット分の取り込み,PCをカウントアップまでの計4サイクルである.実行サイクルは最大2サイクルなので合計6サイクルとなり,3ビットの状態変数を定義して状態遷移回路を記述した.選択信号selectはクロックと非同期でも良いが,この回路ではsclkの同期回路として記述している.実行波形の例を図5に示す.module control4(reset, sclk, ir, c, z, select); input reset, sclk,c,z; input [7:0] ir; output [8:0] select; reg [2:0] ss; reg [8:0] select; always @(posedge sclk or posedge reset) begin if (reset) ss<=3'b000; else case (ss) 3'b000: begin select<=9'b000001001; ss<=3'b001; end // fetch cycle 1 3'b001: begin select<=9'b000010000; ss<=3'b010; end // fetch cycle 2 3'b010: begin select<=9'b100000001; ss<=3'b011; end // fetch cycle 3 3'b011: begin select<=9'b000010000; ss<=3'b100; end // fetch cycle 4 3'b100: // exec cycle 1 casex (ir[7:5]) 3'b0XX: begin select<=9'b000100000; ss<=3'b101; end 3'b100: begin select<=9'b001000000; ss<=3'b000; end 3'b101: begin select<=9'b000100000; ss<=3'b101; end 3'b110: begin if(~c) begin select<=9'b000000000; ss<=3'b000; end if(c) begin select<=9'b010000000; ss<=3'b000; end end 3'b111: begin if(~z) begin select<=9'b010000000; ss<=3'b000; end if(z) begin select<=9'b000000000; ss<=3'b000; end end endcase 3'b101: // exec cycle 2 casex (ir[7:5]) 3'b0XX: begin select<=9'b001000010; ss<=3'b000; end 3'b101: begin select<=9'b000000110; ss<=3'b000; end endcase endcase end endmodule
図5 コントローラの実行波形
3. 全回路
これまで説明した回路を統合する.モジュール間の配線はwireとして宣言して結線すれば良いのだが,ここでは動作波形を確認するため,レジスタ宣言を行ってレジスタの値を出力させている.halt動作は,clk信号とhalt信号との論理積をとってクロックジェネレータにgclkとして供給することにより実現している.
動作波形例について説明する. ROM領域に入力されたプログラムの実行動作を示している.これは,入力ポートの値をアキュームレータに読み込み,その値を出力ポートに出力し,NAND命令とJPNZ命令を組み合わせて0番地に強制ジャンプして動作を繰り返すものである.入力ポートに与えられたFHが出力ポートに出力されていることが確認できる.
module kcom4(reset,clk,tclk,sclk,a_bus,pc,d_bus,ir,acc,latch,c,z,select,inp,oup,halt); input reset, clk; input [3:0] inp; output tclk, sclk, c, z, halt; output [3:0] d_bus, acc, latch, oup; output [4:0] a_bus, pc; output [7:0] ir; output [8:0] select; wire gclk; assign gclk= clk & ~halt; clock4 clock4(reset, gclk, tclk, sclk); pcir4 pcir4(reset, tclk, halt, pc, ir, a_bus, d_bus, select); alu4 alu4(reset, tclk, ir, select, acc, latch, c, z, d_bus); mem4 mem4(tclk, a_bus, inp, oup, select, d_bus); control4 control4(reset, sclk, ir, c, z, select); endmodule
図6 全回路の実行波形
ご注意:
回路を完全に検証したわけではないです,あくまでご参考まで.
本を数冊読んだだけの独学の自己流の記述スタイルです,参考にされない方が良いかもです
ESP32 Wifi Bluetooth開発ボード |
Arduino Nano Every |
Raspberry Pi pico |
FPGA XILINX Artix-7 |