HOME > AHDLによるK-COMの設計

 AHDLによるK-COMの設計 

K-COMの全回路構成を図1のように設計した.そのAHDLによる記述例をリスト1に示す.

k-com-block

図1 K-COMの全回路構成

クロック

クロックはボードに装備された発振器(OSC)により供給した.クロックはD-FFを二つを用いて分周され, 半周期ずれた正論理の信号が作られている.選択信号とトリガ信号が,それぞれs_clkとt_clkの出力である.
強制終了(halt)のため,二つのD-FFのクロック信号にはhaltの反転との論理積を供給している.

ALUおよびアキュームレータ

ALUおよびアキュームレータについて説明する.
データのビット数は8ビットであり,論理演算時は8ビットのデータにより各ビットの計算を行えばよいが, 算術演算時の桁上がりを得るため1ビット足して,合計9ビットの算術演算回路を作成し, 8ビットまでを計算結果とし,9ビットめをキャリー信号に接続している.
命令レジスタの上位3ビットで場合分けして,CASE文により演算処理を記述した. shift命令時は命令レジスタの下位5ビットがシフトの方向を決めるので, 更にIF文によりシフト方向別の記述を行った.
STORE命令時はアキュームレータのデータがALUを素通りするが, この場合はCASE文のWHEN OTHERSの項で記述している.
その他,keygu,keygl信号は,FPGAボードの入力キーを動作させるための信号である.

プログラムカウンタおよび命令レジスタ

次に,プログラムカウンタおよび命令レジスタのについて説明する.
プロプログラムカウンタは,通常クロックによりカウントアップしているが, ジャンプ時(ロード信号発生時)に命令レジスタの下位5ビットがプログラムカウンタに転送される.
命令レジスタの全ビットが1の時は強制停止信号(halt)が生成される.

メモリおよびI/Oポート

メモリおよびI/Oポートについて説明する.
K-COMの仕様ではメモリ領域は特にROM,RAMの区別がされていないが, 全てのメモリ領域をRAMとするとプログラム書き込みのための回路が別途必要なので, メモリ領域をプログラム格納と定数データ用のROM領域と変数データ用のRAM領域に分けて記述した. CASE文でアドレスに応じた領域の記述を行い,ROM領域を選択された時は固定データを返す. ROM領域にはあらかじめプログラムを書き込んである. RAM領域はD-FFにより作成し,8ビット×RAM領域のバイト数で使用するD-FFのビット数をのみを宣言して, 不要な回路の生成を省いた.

コントローラ

コントローラはステートマシンとして記述される.
フェッチサイクルが2サイクル,実行サイクルが最大2サイクルであるので合計4状態となり, S0からS3のステートマシンとして記述されている. データ転送を行うためのレジスタ及びメモリのイネーブル信号が選択信号(select)の値により制御される. 合計8本の選択信号でK-COMの全メモリ及びレジスタの制御が可能で,選択信号の割り当ては, コメントブロックに記述されている.
ステートマシンの状態遷移がTABLE文によって記述され,フェッチ動作,実行動作及び, その時の選択信号が同一のTABLE文で記述されている. feはフェッチまたは実行動作を外部に示す出力線である. K-COMでは,ALU出力とメモリ出力の双方がトライステートバッファによりデータバスに接続される構造を とっているが,それらの接続制御もコントローラにより行われる. その他,ledclkl信号は,FPGAボードのLEDを動作させるための信号である.

リスト1 K-COMのAHDL記述


SUBDESIGN k_com
(
	clock	 		: INPUT;    % clock assigned as OSC 				%
	reset 			: INPUT;  	% reset assigned as TS4 			%
	in_port[7..0] 		: INPUT;  	% input port assigned as KU7-KU0 		%
	keygu			: OUTPUT;	% KEYGU used to enable KU7-KU0 		% 
	out_port[7..0]		: OUTPUT;	% output port assigned as SG4 and SG3 	% 
	pc[4..0]		: OUTPUT;	% program counter assigned as SG2 and SG1 %
	halt			: OUTPUT;	% halt assigned as LED4 			% 
	fe			: OUTPUT;   % fe=(1:fetch, 0:exec) assigned as LED3 	%
	c			: OUTPUT;   % carry flag assigned as LED2 			%
 	z			: OUTPUT;   % zero flag assigned as LED1 			%
)
VARIABLE 
% Clock generatior %
	s_clk 			: DFF;		% select clock for controller 			%
	t_clk 			: DFF;		% trigger clock for register and flag latch 	%
% Register %
	pc[4..0]		: DFFE; 	% Program counter 				%
	ir[7..0]	   		: DFFE; 	% Instruction register 			%
	acc[7..0]		: DFFE; 	% Accumlator 					%
	alu[7..0]		: DFFE; 	% ALU latch 					%
% flag register %
	c			: DFFE; 	% carry flag 					%
	z			: DFFE; 	% Zero flag 					%
% memory I/O %
 	mem[7..0]		: DFFE;  % if use RAM, define mem[] and modify memory section %
	out_port[7..0]		: DFFE;	% output port mapped on memory map 	%
% NODE %
	mem_in[7..0], mem_out[7..0]	 : NODE;	% memory input and output nodes 	%
	acc_c[8..0], mem_c[8..0], alu_c[8..0] : NODE;  % for arith. cal. in ALU section  %
	a_bus[4..0]		: NODE;	% address bus from PC or IR_L 		%
	select[7..0] 		: NODE;	% control signal to select active resgister 	%
% state machine %
 	ss: MACHINE OF BITS(state[1..0])
     	WITH STATES(s0 = B"00",		% fetch cycle: IR <- mem(PC) 		%
                 	s1 = B"01",			% fetch cycle: pc <- pc +1   			%
                 	s2 = B"10",			% exec cycle 1					%
                 	s3 = B"11");			% exec cycle 2					%

BEGIN
% key enable %
	keygu = GND;

% Clock generator %
	s_clk.clrn = !reset;
	t_clk.clrn = !reset;
	s_clk.d = !s_clk.q;
	t_clk.d = !t_clk.q;
	s_clk.clk = !halt & clock;		% trigger delayed half period 			%
	t_clk.clk = !halt & !clock;		% clock disenabled with halt  			%

% Register  %
	acc[].clrn = !reset;
	acc[].clk = t_clk.q;
	acc[].ena = select[6];
	ir[].clrn = !reset;
	ir[].clk = t_clk.q;
	ir[].ena = select[3];
	halt = (ir[].q == H"FF");		% IR=FF means halt 				%

% PC IR %
	pc[].clrn = !reset;
	pc[].clk = t_clk.q;
	pc[].ena = select[4];
	IF select[7] THEN pc[].d = ir[4..0].q;		% Jump: JPC or JPNZ			%
		 ELSE pc[].d = pc[].q + 1;		% count up PC				%
	END IF;
	IF select[0] THEN a_bus[] = pc[].q;		%fetch cycle: read instruction  	%
		 ELSE a_bus[] = ir[4..0].q; 		% exec cycle: read opeland      	% 
	END IF;

% ALU %
	acc_c[7..0] =acc[7..0].q;			% add 1 bit for arithmetic cal. 	% 
	acc_c[8] = GND;
	mem_c[7..0] = mem_out[7..0];
	mem_c[8] = GND;
	alu[].clk = t_clk.q;
	alu[].ena = select[5];
	c.clk = t_clk.q;
	z.clk = t_clk.q;
	c.clrn = !reset;
	z.clrn = !reset;
	CASE ir[7..5].q IS
		WHEN 0 => 	alu_c[] = acc_c[] + mem_c[];	% arithmetic add		%
				  alu[7..0].d=alu_c[7..0];
				  c.d = alu_c[8];
				  z.d = (alu_c[7..0] == 0);
				  c.ena = select[5];
				  z.ena = select[5];
		WHEN 1 => 	alu_c[] = acc_c[] - mem_c[]; % arithmetic sub		%
				  alu[7..0].d = alu_c[7..0];
				  c.d = alu_c[8];
				  z.d = (alu_c[7..0] == 0);
			      	c.ena = select[5];
				 z.ena = select[5];
		WHEN 2 =>   alu_c[] = acc_c[] !& mem_c[]; % logic NAND 			%
				  alu[7..0].d = alu_c[7..0]; 
				  c.d = alu_c[8];
				z.d = (alu_c[7..0] == 0);
				  c.ena = select[5];
				  z.ena = select[5];
		WHEN 3 => 	IF ( ir[4..0].q ==1 ) THEN
					alu[6..0].d = acc[7..1].q;	% Right shift		%
				  	alu[7].d = GND;				
				  	c.d = acc[0].q;
				  	z.d = (acc[7..1].q == 0);
				ELSE
					alu[7..1].d = acc[6..0].q;	% left shift		%
				  	alu[0].d = GND;				
				  	c.d = acc[7].q;
				  	z.d = (acc[6..0].q == 0);	
				END IF;
				  c.ena = select[5];
				  z.ena = select[5];
	WHEN OTHERS => 	alu[7..0].d = acc[7..0].q;	% store also useing ALU 	%
				c.ena = GND;
				  z.ena = GND;            
	END CASE;

% Control %
% 	select7: PC load                            			%
%  	select6: ACC latch                          			%
%  	select5: ALU latch                          			%
%  	select4: PC count up or load enable         		%
%  	select3: IR latch                           			%
%  	select2: memory read/write                  		%
%  	select1: ACC data select from ALU or memory 	%
%  	select0: address select PC(1) or IR_L(0)    		%

	ss.clk = s_clk.q;
 	ss.reset = reset;
 	TABLE
  		ss,  ir[7..5].q, c,  z => select[7..0], ss, fe;
  		s0,    B"XXX",   X,  X => B"00001001",  s1,  1;
  		s1,    B"XXX",   X,  X => B"00010000",  s2,  0;
  		s2,    B"0XX",   X,  X => B"00100000",  s3,  0;
  		s3,    B"0XX",   X,  X => B"01000010",  s0,  1;
  		s2,    B"100",   X,  X => B"01000000",  s0,  1;
  		s2,    B"101",   X,  X => B"00100000",  s3,  0;
  		s3,    B"101",   X,  X => B"00000110",  s0,  1;
  		s2,    B"110",   0,  X => B"00000000",  s0,  1;
  		s2,    B"110",   1,  X => B"10010000",  s0,  1;
  		s2,    B"111",   X,  0 => B"10010000",  s0,  1;
  		s2,    B"111",   X,  1 => B"00000000",  s0,  1;
 	END TABLE;

	CASE select[2..1] IS
		WHEN 0 => acc[].d = mem_out[]; 	% ACC & IR read from memory 	%    
		WHEN 1 => acc[].d = alu[].q;	% ACC read from ALU 	% 
		WHEN 2 => mem_in[] = alu[].q;   % ALU write to memory 	%
		WHEN 3 => mem_in[] = alu[].q;   % ALU write to memory 	%
	END CASE;
	
% Memory %
	mem[].clk = t_clk.q;
	out_port[].clk = t_clk.q;
	ir[].d=mem_out[];
	CASE a_bus[] IS
% ROM section %
		WHEN 0 => mem_out[] = H"84";	
		WHEN 1 => mem_out[] = H"05";
		WHEN 2 => mem_out[] = H"BF";
		WHEN 3 => mem_out[] = H"FF";
		WHEN 4 => mem_out[] = H"01";	
		WHEN 5 => mem_out[] = H"02";	
% RAM section %
	WHEN 6 => mem[7..0].d = mem_in[]; mem[7..0].ena = select[2]; mem_out[] = mem[7..0].q;
% Input / Output prot %
		WHEN 30 => mem_out[] = in_port[];
		WHEN 31 => out_port[].d = mem_in[]; out_port[].ena = select[2]; 
% data fix to FF, when ther addres accessed %
	    	WHEN OTHERS =>mem_out[] = H"FF"; 
	END CASE;

END;

< 前の記事へ次の記事へ >


ページトップに戻る



ESP32 Wifi Bluetooth開発ボード

Arduino Nano Every
​​
Raspberry Pi pico

FPGA XILINX Artix-7