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

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

K-COM16(Verilog)作成


VerilogによるK-COMの設計

本で書いた16ビット版のK-COM16のVerilogによる設計例です.
サブルーチンコール,割り込み機能の追加,命令とアドレス空間を拡張しています.
(仕様の詳細は書籍をご参照いただければ幸いです)


クロックジェネレータ

module clock16(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


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

module pcir16(reset, tclk, halt, pc, ir, a_bus, d_bus, select);
input reset, tclk;
input [9:0] select;
input [15:0] d_bus;
output halt;
output [11:0] a_bus;
output [11:0] pc;
output [15:0] ir;
reg [11:0] pc, as;
reg [15:0] ir;

always @(posedge tclk or posedge reset) begin
if (reset) begin pc<=0; ir<=0; end
else begin
if(select[4]) begin
if(~select[8] & ~select[7]) pc<=pc+12'b1;
if(~select[8] & select[7]) pc<=ir[11:0];
if(select[8] & ~select[7]) pc<=as;
if(select[8] & select[7]) pc<=12'hf00;
end
else if(select[9]) as<=pc;
else if(select[3]) ir<=d_bus;
end
end
assign a_bus=(select[0]) ? pc: ir[11:0];
assign halt=(ir==12'hfff);

endmodule


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

module alu16(reset, tclk, ir, select, acc, latch, c, z, d_bus);
input reset, tclk;
input [9:0] select;
input [15:0] ir;
output [15:0] acc, latch;
output z, c;
inout [15:0] d_bus;
reg c, sc, z, sz;
reg [15:0] acc, sacc, 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[15:12])
4'b0000: begin {c,latch}<=acc + d_bus; z<=((acc + d_bus)==16'h0000); end
4'b0001: begin {c,latch}<=acc - d_bus; z<=((acc - d_bus)==16'h0000); end
4'b0010: begin {c,latch}<=~(acc & d_bus); z<=(~(acc & d_bus)==16'h0000); end
4'b0011: begin {c,latch}<=acc << 1; z<=((acc <<1 )==16'h0000); end
4'b1110: begin sacc<=acc; sc<=c; sz<=z; end
4'b1111: begin acc<=sacc; c<=sc; z<=sz; end
default: latch<=acc;
endcase
end
if(select[6]) acc<=d_bus;
end
end
assign d_bus= (select[1]) ? latch: 16'bz;
endmodule


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

module mem16(tclk, a_bus, inp, oup, select, d_bus);
input tclk;
input [11:0] a_bus;
input [15:0] inp;
input [9:0] select;
output [15:0] oup;
inout [15:0] d_bus;
reg [15:0] mem[6:6] ; // max size ... [0:4095]
reg [15:0] oup;

function [15:0] memout; // memory read
input [11:0] a_bus;
case(a_bus)
0:memout =16'h8FFE; // LD FFEH ROM area
1:memout =16'h0006; // ADD 006H
2:memout =16'h9FFF; // ST FFFH
3:memout =16'h2006; // NAND 005H
4:memout =16'hB000; // JPNZ 000H
5:memout =16'h0000; // DB 00 00H
3840:memout =16'hE000; // PUSH interupt routine
3841:memout =16'h8FFE; // LD FFEH
3842:memout =16'h9006; // ST 006H
3843:memout =16'hF000; // PULL
3844:memout =16'hD000; // RET
4094:memout =inp; // input port
default: memout = mem[a_bus];
endcase
endfunction

always @(posedge tclk) begin
if(select[2] & select[1]) // memory write
if (a_bus==4095) oup<=d_bus; // output port
else mem[a_bus]<=d_bus;
end
assign d_bus = (~select[2] & ~select[1])? memout(a_bus): 16'bz;

endmodule


コントローラ

module control16(reset, ipt, sclk, ir, c, z, select, i);
input reset, ipt, sclk, c, z;
input [15:0] ir;
output i;
output [9:0] select;
reg i;
reg [2:0] ss;
reg [9:0] select;

// details of select signals
// select9: AS latch
// select8: Return from sub-routine or interrupt
// select7: PC count-up or PC load (jump)
// select6: ACC latch
// select5: ALU latch
// select4: PC count up or load enable
// select3: IR latch
// select2: memory read(0)/write(1)
// select1: ACC data select from ALU or memory
// select0: address select PC(1) or IR_L(0)

always @(posedge sclk or posedge reset) begin
if (reset) begin ss<=3'b000; i<=0; end
else case (ss)
3'b000:
if(ipt & ~i) begin select<=10'b1000000000; ss<=3'b100; i<=1; end // interupt 1: as<-pc
else begin select<=10'b0000001001; ss<=3'b001; end // fetch cycle 1

3'b001: begin select<=10'b0000010000; ss<=3'b010; end // fetch cycle 2
3'b010:
casex (ir[15:12]) // exec cycle 1
4'b0XXX: begin select<=10'b0000100000; ss<=3'b011; end // alu operation 1
4'b1000: begin select<=10'b0001000000; ss<=3'b000; end // LD
4'b1001: begin select<=10'b0000100000; ss<=3'b011; end // ST
4'b1010: begin
if(~c) begin select<=10'b0000000000; ss<=3'b000; end // JPC: c=0, nop
if(c) begin select<=10'b0010010000; ss<=3'b000; end // JPC: c=1, jump
end
4'b1011: begin
if(~z) begin select<=10'b0010010000; ss<=3'b000; end // JPNZ: z=0, jump
if(z) begin select<=10'b0000000000; ss<=3'b000; end // JPNZ: z=1, nop
end
4'b1100: begin select<=10'b1000000000; ss<=3'b011; end // CALL 1
4'b1101: begin select<=10'b0100010000; ss<=3'b000; i<=0; end // RET
4'b1110: begin select<=10'b0000100000; ss<=3'b000; end // PUSH
4'b1111: begin select<=10'b0001100000; ss<=3'b000; end // PULL
endcase
3'b011:
casex (ir[15:12]) // exec cycle 2
4'b0XXX: begin select<=10'b0001000010; ss<=3'b000; end // alu operation 2
4'b1001: begin select<=10'b0000000110; ss<=3'b000; end // ST 2
4'b1100: begin select<=10'b0010010000; ss<=3'b000; end // CALL 2
endcase
3'b100: begin select<=10'b0110010000; ss<=3'b000; end // interupt 2: pc<-F000H
endcase
end

endmodule


K-COM16のトップモジュール

module kcom16(reset,ipt,clk,tclk,sclk,a_bus,pc,d_bus,ir,acc,latch,c,z,select,inp,oup,halt,i);
input reset, ipt, clk;
input [15:0] inp;
output tclk, sclk, c, z, halt, i;
output [11:0] a_bus, pc;
output [9:0] select;
output [15:0] d_bus, ir, acc, latch, oup;
wire gclk;

assign gclk= clk & ~halt;
clock16 clock16(reset, gclk, tclk, sclk);
pcir16 pcir16(reset, tclk, halt, pc, ir, a_bus, d_bus, select);
alu16 alu16(reset, tclk, ir, select, acc, latch, c, z, d_bus);
mem16 mem16(tclk, a_bus, inp, oup, select, d_bus);
control16 control16(reset, ipt, sclk, ir, c, z, select, i);

endmodule



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