ALTERA MMK (MAXII Micro Kit)で「CPUの創りかた」という本に載っているTD4を作ってみました。出版が2003年なんですね。当時は実際に作られた方もおられたようです。
CPLDで作られた方もいます(ページ)。閉鎖されたfpga-lab.orgさんも作られていました。
Quartus IIの論理合成結果は83LEでした。速度はどうやって調べればいいのか、まだ分かっていません。
ROMは組み合わせ回路で作っています。トラ技と同じようにフラッシュメモリブロック(UFM)を使うことにすれば、もっと縮みそうです。UFMを使うにはメガファンクションというIP生成ツールを使うみたいですが、使い方は分かっていません。クロックの分周なんかもあったりしないかな。
たぶん、論理合成するときのオプションとかつけると、速くなったり縮んだりすると思うのですが、どこで設定すればいいのかすら分かっていません(笑)
デコーダはp.242の真理値表そのものです。本のように論理縮小とかしないで、ツールにおまかせです。
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の真理値表そのものです。本のように論理縮小とかしないで、ツールにおまかせです。
※コメント投稿者のブログIDはブログ作成者のみに通知されます