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の真理値表そのものです。本のように論理縮小とかしないで、ツールにおまかせです。
ジャンル:
ウェブログ
コメント   この記事についてブログを書く
この記事をはてなブックマークに追加
« トラ技12月号 | トップ | 「FRマイコン基板アプリケー... »
最近の画像もっと見る

コメントを投稿


コメント利用規約に同意の上コメント投稿を行ってください。

数字4桁を入力し、投稿ボタンを押してください。

あわせて読む

トラックバック

この記事のトラックバック  Ping-URL
  • 送信元の記事内容が半角英数のみのトラックバックは受け取らないよう設定されております。
  • このブログへのリンクがない記事からのトラックバックは受け取らないよう設定されております。
  • ※ブログ管理者のみ、編集画面で設定の変更が可能です。