Sim's blog

電子工作はじめてみました

MAX II マイクロキットで「CPUの創りかた」

2008-11-13 02:14:22 | FPGA
ALTERA MMK (MAXII Micro Kit)で「CPUの創りかた」という本に載っているTD4を作ってみました。出版が2003年なんですね。当時は実際に作られた方もおられたようです。
CPLDで作られた方もいます(ページ)。閉鎖されたfpga-lab.orgさんも作られていました。

Quartus IIの論理合成結果は83LEでした。速度はどうやって調べればいいのか、まだ分かっていません。
module main(
    output [7:0] led,
    input [3:0] key,
    input iclk);

    wire [3:0] cpuout;
    reg clk = 1'b0;

    // clock generator (1Hz)
    reg [24:0] clkctr = 25'h0;

    always @(posedge iclk)
        clkctr <= clkctr == 25'd24999999 ? 25'h0 : clkctr + 1'b1;

    always @(posedge iclk)
        if(clkctr == 0) clk <= ~clk;

    // LED
    assign led = {4'hf, ~cpuout};

    // TD4
    td4 cpu(cpuout, key[3:0], key[3], clk);

endmodule


module td4(
    output reg [3:0] out = 4'h0,
    input [3:0] in,
    input rst, clk);
    
    reg [3:0] a = 4'h0;
    reg [3:0] b = 4'h0;
    reg [3:0] pc = 4'h0;
    reg c = 0;
    reg [3:0] selout;
    reg [7:0] op;
    wire [3:0] aluout;
    wire cout;

    // ROM (LEDちかちか)
    always @(*)
        case(pc)
        4'h0 : op = 8'b1011_0011;
        4'h1 : op = 8'b1011_0110;
        4'h2 : op = 8'b1011_1100;
        4'h3 : op = 8'b1011_1000;
        4'h4 : op = 8'b1011_1000;
        4'h5 : op = 8'b1011_1100;
        4'h6 : op = 8'b1011_0110;
        4'h7 : op = 8'b1011_0011;
        4'h8 : op = 8'b1011_0001;
        4'h9 : op = 8'b1111_0000;
        default : op = 8'hx;
        endcase

/*
    // ROM (ラーメンタイマー)
    always @(*)
        case(pc)
        4'h0 : op = 8'b1011_0111; // out 0111
        4'h1 : op = 8'b0000_0001; // add a, 0001
        4'h2 : op = 8'b1110_0001; // jnc 0001
        4'h3 : op = 8'b0000_0001; // add a, 0001
        4'h4 : op = 8'b1110_0011; // jnc 0011
        4'h5 : op = 8'b1011_0110; // out 0110
        4'h6 : op = 8'b0000_0001; // add a, 0001
        4'h7 : op = 8'b1110_0110; // jnc 0110
        4'h8 : op = 8'b0000_0001; // add a, 0001
        4'h9 : op = 8'b1110_1000; // jnc 1000
        4'ha : op = 8'b1011_0000; // out 0000
        4'hb : op = 8'b1011_0100; // out 0100
        4'hc : op = 8'b0000_0001; // add 0001
        4'hd : op = 8'b1110_1010; // jnc 1010
        4'he : op = 8'b1011_1000; // out 1000
        4'hf : op = 8'b1111_1111; // jmp 1111
        endcase
*/

    // decoder
    reg sela, selb, load0, load1, load2, load3;

    always @(*)
        case(op[7:4])
        4'b0000 : {selb, sela, load0, load1, load2, load3} = 6'b000111; // ADD A, n
        4'b0001 : {selb, sela, load0, load1, load2, load3} = 6'b010111; // MOV A, B
        4'b0010 : {selb, sela, load0, load1, load2, load3} = 6'b100111; // IN  A
        4'b0011 : {selb, sela, load0, load1, load2, load3} = 6'b110111; // MOV A, n
        4'b0100 : {selb, sela, load0, load1, load2, load3} = 6'b001011; // MOV B, A
        4'b0101 : {selb, sela, load0, load1, load2, load3} = 6'b011011; // ADD B, n
        4'b0110 : {selb, sela, load0, load1, load2, load3} = 6'b101011; // IN  B
        4'b0111 : {selb, sela, load0, load1, load2, load3} = 6'b111011; // MOV B, n
        4'b1001 : {selb, sela, load0, load1, load2, load3} = 6'b011101; // OUT B
        4'b1011 : {selb, sela, load0, load1, load2, load3} = 6'b111101; // OUT n
        4'b1110 : {selb, sela, load0, load1, load2, load3} = c ? 6'bxx1111 : 6'b111110; // JNC n
        4'b1111 : {selb, sela, load0, load1, load2, load3} = 6'b111110; // JMP
        default : {sela, selb, load0, load1, load2, load3} = 6'bxxxxxx;
        endcase

    // selector
    always @(*)
        case({selb, sela})
        2'b00 : selout = a;
        2'b01 : selout = b;
        2'b10 : selout = in;
        2'b11 : selout = 4'h0;
        endcase

    // ALU
    assign {cout, aluout} = selout + op[3:0];

    // register
    always @(posedge clk or negedge rst)
        if(~rst)
            {a, b, out, pc, c} <= 0;
        else begin
            if(~load0) a <= aluout;
            if(~load1) b <= aluout;
            if(~load2) out <= aluout;
            pc <= ~load3 ? aluout : pc + 1'b1;
            c <= cout;
        end

endmodule

ROMは組み合わせ回路で作っています。トラ技と同じようにフラッシュメモリブロック(UFM)を使うことにすれば、もっと縮みそうです。UFMを使うにはメガファンクションというIP生成ツールを使うみたいですが、使い方は分かっていません。クロックの分周なんかもあったりしないかな。

たぶん、論理合成するときのオプションとかつけると、速くなったり縮んだりすると思うのですが、どこで設定すればいいのかすら分かっていません(笑)

デコーダはp.242の真理値表そのものです。本のように論理縮小とかしないで、ツールにおまかせです。

最新の画像もっと見る

コメントを投稿