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 |