HOME > Verilogによる8ビットCPUの設計例その2(K-COMv2)

 Verilogによる8ビットCPUの設計例その2(K-COMv2) 

 論理回路の基礎を学んだ方が,その知識をもとに簡単なCPUの構造について学ぶことを目的として, 論理ICを使ったCPU設計からHDLによる設計の手順で教材を作成してきました.
 しかし,直接HDLで回路設計する場合には,論理ICのイメージにとらわれる必要はありません.  ここでは,同じアーキテクチャのCPUを少し違った考え方で記述した例をK-COMv2と名づけ,簡単に説明します.
 K-COMはフェッチ2サイクル,実行2サイクルの計4状態を持つ状態遷移回路として記述し, 個々のパーツをコントローラからの制御信号で制御するように設計しましたが,K-COMv2では, フェッチ2サイクルは同じで実行サイクルは命令ごとにことなる状態をとる状態遷移回路とし, 個々の状態に応じた制御を記述することで,K-COMと同じ動作を実現しました.
 状態の割り当てについては,ステートマシン(statemachine)の記述のコメント部分に記載してあります.

Verilog記述

module kcomv2(reset,osc,inp,oup,halt,ss,a_bus,d_bus,pc,ir,acc,latch,c,z);
input reset, osc;
input [7:0] inp; 
output c, z, halt;
output [2:0] ss;
output [4:0] a_bus, pc;
output [7:0] d_bus, ir, acc, latch, oup;

reg [7:0] ir, acc, latch, oup;
reg [7:0] mem[0:31];
reg [4:0] pc;
reg [2:0] ss;
reg	c,z;

wire clk;
wire [4:0] a_bus;
wire [7:0] d_bus;

// clock //
assign clk = osc & ~halt;

// state machine //
// s0, ss==000: fetch 1, ir<-mem(pc)
// s1, ss==001: fetch 2, pc<-pc+1
// s2, ss==010: exec 1, ADD,SUB,NAND,SHIFT, ST, latch <- result  
// s3, ss==011: exec 2, write back, acc <- latch 
// s4, ss==100: exec 2, ST, mem(ir[4:0]) <- latch
// s5, ss==101: exec 1, LD, acc <- mem(ir[4:0])  
// s6, ss==110: exec 1, JPC, JPNZ, pc <- ir[4:0] 

always @(negedge clk or posedge reset) begin
	if (reset) ss<=0;
	else case (ss)	
		3'b000: ss<=3'b001;  
		3'b001: begin   
			if (ir[7:5]==3'b100) ss<=3'b101;  	 // LD
			else if (ir[7:6]==2'b11) ss<=3'b110; // JPC, JPNZ
			else ss<=3'b010;			 // ADD,SUB,NAND,SHIFT, ST
			end	
		3'b010: if (ir[7:5]==3'b101) ss<=3'b100; 	 // ST
				else ss<=3'b011;		 // ADD,SUB,NAND,SHIFT
		default: ss<=3'b000;				 // initial state
	endcase
end

// pc, ir //
always @(posedge clk or posedge reset) begin
	if (reset) begin pc<=0; ir<=0; end 
	else begin
		if (ss==3'b000) ir<=d_bus; 
		else if (ss==3'b001) pc<=pc+5'b1; 
		else if(ss==3'b110)
		 	if ((ir[7:5]==3'b110 & c) | (ir[7:5]==3'b111 & ~z)) pc<=ir[4:0];
	end
end
assign halt = (ir==8'hff);
assign a_bus = (ss==3'b000)? pc: ir[4:0];

// alu, acc, latch //
always @(posedge clk or posedge reset) begin
	if (reset) begin acc<=0; latch<=0; c<=0; z<=0; end
	else if(ss==3'b010) 
		casex(ir[7:5])
			3'b000: begin {c,latch}<=acc + d_bus;    z<=((acc + d_bus)==8'b0); end
			3'b001: begin {c,latch}<=acc - d_bus;    z<=((acc - d_bus)==8'b0); end
			3'b010: begin {c,latch}<=~(acc & d_bus); z<=((~(acc & d_bus))==8'b0); end
			3'b011: begin {c,latch}<=acc << 1;       z<=((acc <<1 )==8'b0); end
			3'b101: latch<=acc;
		endcase
	else if (ss==3'b011 | ss==3'b101) acc<=d_bus;
end

// memory //
function [7:0] memout;  // memory read
input [4:0] a_bus;
	case(a_bus) 
		0:memout =8'h9e;
		1:memout =8'hbf;
		2:memout =8'h44;
		3:memout =8'he0;
		4:memout =8'h00;
		30:memout =inp;
		default: memout =mem[a_bus];
	endcase
endfunction 
always @(posedge clk) begin
	if(ss==3'b100)
		if (a_bus==31) oup<=d_bus; else mem[a_bus] <=d_bus;
end
	
//data bus //
assign d_bus= (ss==3'b011 | ss==3'b100)? latch: memout(a_bus);

endmodule

< 前の記事へ


ページトップに戻る



ESP32 Wifi Bluetooth開発ボード

Arduino Nano Every
​​
Raspberry Pi pico

FPGA XILINX Artix-7