概要
windowsでiverilogやってみた。
4bitCPUで、何ができる。
数9を4個使って、1から15まで、求める式を実行できる。
ちょっと自慢。
4bit CPUの仕様
stackマシーン
stackは、4bitで6個搭載
命令は、8bit
ROMは、16個
RAMは、3個
プログラムカウンタ(pc) 4bit
- 命令一覧
ジャンプ命令->無し
RAMアクセス->無し
フラグ->無し
| ニーモニック | 動作 | 機械語 |
|---|---|---|
| end | 停止 | 00 |
| out | スタックTOPを出力 | 50 |
| dup | スタックTOPを複写 | 80 |
| drop | スタックTOPを廃棄 | 90 |
| push 9 | スタックに9を積む | 29 |
| + | スタックTOPをNEXTで加算 | F0 |
| - | スタックTOPをNEXTで減算 | F1 |
| * | スタックTOPをNEXTで乗算 | F2 |
| / | スタックTOPをNEXTで除算 | F3 |
| % | スタックTOPをNEXTで剰余 | F4 |
サンプルコード
module cpu4(input clk, input rst, output [3:0] outport);
integer i;
reg [3:0] q[0:5];
reg [7:0] rom[15:0];
reg [3:0] ram[2:0];
reg jpflg;
reg [3:0] pc;
reg [3:0] out;
wire [7:0] code;
wire [3:0] op;
wire [3:0] opland;
wire [3:0] qtop;
wire [3:0] qnext;
assign code = rom[pc];
assign op = code[7:4];
assign opland = code[3:0];
assign outport = out;
assign qtop = q[0];
assign qnext = q[1];
task push;
begin
for (i = 1; i < 6; i = i + 1)
q[i] <= q[i - 1];
end
endtask
task pop;
begin
for (i = 1; i < 5; i = i + 1)
q[i] <= q[i + 1];
end
endtask
initial
begin
$monitor(" %d %d %d %d", pc, qtop, qnext, out);
end
always @(posedge clk)
begin
if (rst)
begin
/*1
push 9
push 9
/
push 9
push 9
-
+
out
rom[0] <= 8'h2_9;
rom[1] <= 8'h2_9;
rom[2] <= 8'hf_3;
rom[3] <= 8'h2_9;
rom[4] <= 8'h2_9;
rom[5] <= 8'hf_1;
rom[6] <= 8'hf_0;
rom[7] <= 8'h5_0;
rom[8] <= 8'h0_0;
*2
push 9
push 9
/
push 9
push 9
/
+
out
*/
rom[0] <= 8'h2_9;
rom[1] <= 8'h2_9;
rom[2] <= 8'hf_3;
rom[3] <= 8'h2_9;
rom[4] <= 8'h2_9;
rom[5] <= 8'hf_3;
rom[6] <= 8'hf_0;
rom[7] <= 8'h5_0;
rom[8] <= 8'h0_0;
/*3
push 9
push 9
+
push 9
+
push 9
/
out
rom[16] <= 8'h2_9;
rom[17] <= 8'h2_9;
rom[18] <= 8'hf_0;
rom[19] <= 8'h2_9;
rom[20] <= 8'hf_0;
rom[21] <= 8'h2_9;
rom[22] <= 8'hf_3;
rom[23] <= 8'h5_0;
*4
push 9
push 9
push 9
+
push 9
/
dup
+
out
rom[24] <= 8'h2_9;
rom[25] <= 8'h2_9;
rom[26] <= 8'h2_9;
rom[27] <= 8'hf_0;
rom[28] <= 8'h2_9;
rom[29] <= 8'hf_3;
rom[30] <= 8'h8_0;
rom[31] <= 8'hf_0;
rom[32] <= 8'h5_0;
*5
push 9
push 9
push 9
+
push 9
/
dup
+
-
out
rom[33] <= 8'h2_9;
rom[34] <= 8'h2_9;
rom[35] <= 8'h2_9;
rom[36] <= 8'hf_0;
rom[37] <= 8'h2_9;
rom[38] <= 8'hf_3;
rom[39] <= 8'h8_0;
rom[40] <= 8'hf_0;
rom[41] <= 8'hf_1;
rom[42] <= 8'h5_0;
*6
push 9
dup
push 9
+
push 9
+
push 9
/
-
out
rom[43] <= 8'h2_9;
rom[44] <= 8'h8_0;
rom[45] <= 8'h2_9;
rom[46] <= 8'hf_0;
rom[47] <= 8'h2_9;
rom[48] <= 8'hf_0;
rom[49] <= 8'h2_9;
rom[50] <= 8'hf_3;
rom[51] <= 8'hf_1;
rom[52] <= 8'h5_0;
*7
push 9
push 9
push 9
+
push 9
/
-
out
rom[53] <= 8'h2_9;
rom[54] <= 8'h2_9;
rom[55] <= 8'h2_9;
rom[56] <= 8'hf_0;
rom[57] <= 8'h2_9;
rom[58] <= 8'hf_3;
rom[59] <= 8'hf_1;
rom[60] <= 8'h5_0;
*8
push 9
push 9
push 9
drop
push 9
/
-
out
rom[61] <= 8'h2_9;
rom[62] <= 8'h2_9;
rom[63] <= 8'h2_9;
rom[64] <= 8'h9_0;
rom[65] <= 8'h2_9;
rom[66] <= 8'hf_3;
rom[67] <= 8'hf_1;
rom[68] <= 8'h5_0;
*9
push 9
push 9
-
push 9
*
push 9
+
out
rom[69] <= 8'h2_9;
rom[70] <= 8'h2_9;
rom[71] <= 8'hf_1;
rom[72] <= 8'h2_9;
rom[73] <= 8'hf_2;
rom[74] <= 8'h2_9;
rom[75] <= 8'hf_0;
rom[76] <= 8'h5_0;
*10
push 9
push 9
/
push 9
dup
push 9
/
+
out
rom[77] <= 8'h2_9;
rom[78] <= 8'h2_9;
rom[79] <= 8'hf_3;
rom[80] <= 8'h2_9;
rom[81] <= 8'h8_0;
rom[82] <= 8'h2_9;
rom[83] <= 8'hf_3;
rom[84] <= 8'hf_0;
rom[85] <= 8'h5_0;
*11
push 9
push 9
push 9
+
push 9
/
+
out
rom[86] <= 8'h2_9;
rom[87] <= 8'h2_9;
rom[88] <= 8'h2_9;
rom[89] <= 8'hf_0;
rom[90] <= 8'h2_9;
rom[91] <= 8'hf_3;
rom[92] <= 8'hf_0;
rom[93] <= 8'h5_0;
*12
push 9
dup
push 9
push 9
+
+
push 9
/
+
out
rom[94] <= 8'h2_9;
rom[95] <= 8'h8_0;
rom[96] <= 8'h2_9;
rom[97] <= 8'h2_9;
rom[98] <= 8'hf_0;
rom[99] <= 8'hf_0;
rom[100] <= 8'h2_9;
rom[101] <= 8'hf_3;
rom[102] <= 8'hf_0;
rom[103] <= 8'h5_0;
*13
push 9
push 9
push 9
+
push 9
/
dup
+
+
out
rom[104] <= 8'h2_9;
rom[105] <= 8'h2_9;
rom[106] <= 8'h2_9;
rom[107] <= 8'hf_0;
rom[108] <= 8'h2_9;
rom[109] <= 8'hf_3;
rom[110] <= 8'h8_0;
rom[111] <= 8'hf_0;
rom[112] <= 8'hf_0;
rom[113] <= 8'h5_0;
*14
push 9
dup
push 9
push 9
+
push 9
/
dup
+
-
+
out
rom[114] <= 8'h2_9;
rom[115] <= 8'h8_0;
rom[116] <= 8'h2_9;
rom[117] <= 8'h2_9;
rom[118] <= 8'hf_0;
rom[119] <= 8'h2_9;
rom[120] <= 8'hf_3;
rom[121] <= 8'h8_0;
rom[122] <= 8'hf_0;
rom[123] <= 8'hf_1;
rom[124] <= 8'hf_0;
rom[125] <= 8'h5_0;
*15
push 9
dup
dup
push 9
+
push 9
+
push 9
/
-
+
out
rom[126] <= 8'h2_9;
rom[127] <= 8'h8_0;
rom[128] <= 8'h8_0;
rom[129] <= 8'h2_9;
rom[130] <= 8'hf_0;
rom[131] <= 8'h2_9;
rom[132] <= 8'hf_0;
rom[133] <= 8'h2_9;
rom[134] <= 8'hf_3;
rom[135] <= 8'hf_1;
rom[136] <= 8'hf_0;
rom[137] <= 8'h5_0;
rom[138] <= 8'h0_0;
*/
for (i = 0; i < 6; i = i + 1)
q[i] <= 0;
jpflg <= 0;
out <= 0;
pc <= 0;
ram[0] <= 0;
ram[1] <= 0;
ram[2] <= 0;
end
else
begin
case (op)
4'h0://end
begin
jpflg = 1;
end
4'h2://push
begin
push;
q[0] <= opland;
end
4'h5://out
begin
out <= q[0];
pop;
end
4'h8://dup
begin
push;
end
4'h9://drop
begin
pop;
end
4'hf:
begin
case (opland)
4'h0://+
begin
q[0] <= q[1] + q[0];
pop;
end
4'h1://-
begin
q[0] <= q[1] - q[0];
pop;
end
4'h2://*
begin
q[0] <= q[1] * q[0];
pop;
end
4'h3:///
begin
q[0] <= q[1] / q[0];
pop;
end
4'h4://%
begin
q[0] <= q[1] % q[0];
pop;
end
endcase
end
endcase
if (jpflg == 0)
pc <= pc + 1;
else
jpflg <= 0;
end
end
endmodule
module test;
reg clk,
rst;
wire [3:0] outport;
cpu4 u(.clk(clk), .rst(rst), .outport(outport));
initial
begin
//$monitor(" %d", outport);
clk = 0;
rst = 0;
#2
rst = 1;
#2
rst = 0;
#280
$finish;
end
always
#1
clk = ~clk;
endmodule
実行結果
>iverilog stack4.v
>vvp a.out
x x x x
0 0 0 0
1 9 0 0
2 9 9 0
3 1 0 0
4 9 1 0
5 9 9 0
6 1 1 0
7 2 0 0
8 2 0 2
stack4.v:468: $finish called at 284 (1s)
以上。