2532545 ランダム
 HOME | DIARY | PROFILE 【お気に入りブログ登録】 【ログイン】

CPUを作ろう ~計算機教材とマイコンと電子工作~

K-COMv2(8bitCPU)


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)の記述のコメント部分に記載してあります.


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


Copyright (c) 1997-2018 Rakuten, Inc. All Rights Reserved.