概要
ilasmでstack machineやってみた。
練習問題やってみた。
検証編
練習問題
elixirでilasmをアセンブルしてROM化せよ。
verilogでcpu書いて検証せよ。
サンプルコード
module cpu12(input clk, input rst, output [7:0] outport);
parameter N = 6;
integer i;
reg [7:0] q[0:N - 1];
reg [11:0] rom[64:0];
reg [7:0] ram[2:0];
reg [7:0] str[3:0];
reg jpflg;
reg [1:0] po1;
reg [1:0] po2;
reg [7:0] pc;
reg [7:0] out;
reg [7:0] rnd;
wire [11:0] code;
wire [3:0] op;
wire [7:0] opland;
wire [7:0] qtop;
wire [7:0] qnext;
assign code = rom[pc];
assign op = code[11:8];
assign opland = code[7:0];
assign outport = out;
assign qtop = q[0];
assign qnext = q[1];
task push;
begin
for (i = 1; i < N; i = i + 1)
q[i] <= q[i - 1];
end
endtask
task pop;
begin
for (i = 1; i < N - 1; i = i + 1)
q[i] <= q[i + 1];
end
endtask
always @(posedge clk)
begin
if (rst)
begin
// ldc.i4 100
rom[0] <= 12'h1_64;
// stloc b
rom[1] <= 12'hf_0b;
// ldc.i4 1
rom[2] <= 12'h1_01;
// stloc a
rom[3] <= 12'hf_09;
//loop:
// ldloc a
rom[4] <= 12'hf_0a;
// ldloc b
rom[5] <= 12'hf_0c;
// bgt bye
rom[6] <= 12'h7_30;
// ldloc a
rom[7] <= 12'hf_0a;
// ldc.i4 15
rom[8] <= 12'h1_0F;
// rem
rom[9] <= 12'hf_06;
// brfalse fb
rom[10] <= 12'ha_16;
// ldloc a
rom[11] <= 12'hf_0a;
// ldc.i4 5
rom[12] <= 12'h1_05;
// rem
rom[13] <= 12'hf_06;
// brfalse bb
rom[14] <= 12'ha_1D;
// ldloc a
rom[15] <= 12'hf_0a;
// ldc.i4 3
rom[16] <= 12'h1_03;
// rem
rom[17] <= 12'hf_06;
// brfalse ff
rom[18] <= 12'ha_24;
// ldloc a
rom[19] <= 12'hf_0a;
// call void [mscorlib] System.Console::WriteLine(int32)
rom[20] <= 12'h4_00;
// br tugi
rom[21] <= 12'h9_2B;
//fb:
// ldstr 'fibu'
rom[22] <= 12'h2_01;
rom[23] <= 12'h2_66;
rom[24] <= 12'h2_69;
rom[25] <= 12'h2_62;
rom[26] <= 12'h2_75;
rom[27] <= 12'h2_00;
// br print
rom[28] <= 12'h9_2A;
//bb:
// ldstr 'buzz'
rom[29] <= 12'h2_01;
rom[30] <= 12'h2_62;
rom[31] <= 12'h2_75;
rom[32] <= 12'h2_7A;
rom[33] <= 12'h2_7A;
rom[34] <= 12'h2_00;
// br print
rom[35] <= 12'h9_2A;
//ff:
// ldstr 'fizz'
rom[36] <= 12'h2_01;
rom[37] <= 12'h2_66;
rom[38] <= 12'h2_69;
rom[39] <= 12'h2_7A;
rom[40] <= 12'h2_7A;
rom[41] <= 12'h2_00;
//print:
// call void [mscorlib] System.Console::WriteLine(string)
rom[42] <= 12'h5_00;
//tugi:
// ldloc a
rom[43] <= 12'hf_0a;
// ldc.i4 1
rom[44] <= 12'h1_01;
// add
rom[45] <= 12'hf_02;
// stloc a
rom[46] <= 12'hf_09;
// br loop
rom[47] <= 12'h9_04;
//bye:
// ret
rom[48] <= 12'h0_01;
//
for (i = 0; i < N; i = i + 1)
q[i] <= 0;
jpflg <= 0;
pc <= 0;
ram[0] <= 0;
ram[1] <= 0;
ram[2] <= 0;
po1 <= 0;
po2 <= 0;
str[0] <= 0;
str[1] <= 0;
str[2] <= 0;
str[3] <= 0;
rnd <= 234;
end
else
begin
case (op)
4'h0:
begin
case (opland)
8'h00://nop
begin
end
8'h01://ret
begin
jpflg = 1;
end
endcase
end
4'h1://idc.i4
begin
push;
q[0] <= opland;
end
4'h2://ldstr
begin
case (opland)
8'h00:
begin
po2 <= 0;
end
8'h01:
begin
po2 <= 0;
end
default:
begin
str[po2] <= opland;
po2 <= po2 + 1;
end
endcase
end
4'h4://out
begin
case (po1)
2'h0:
begin
out <= ((q[0] / 10) % 10) + 48;
jpflg = 1;
po1 <= po1 + 1;
end
2'h1:
begin
out <= (q[0] % 10) + 48;
pop;
po1 <= 0;
end
endcase
end
4'h5://out
begin
case (po2)
2'h0:
begin
out <= str[po2];
jpflg = 1;
po2 <= po2 + 1;
end
2'h1:
begin
out <= str[po2];
jpflg = 1;
po2 <= po2 + 1;
end
2'h2:
begin
out <= str[po2];
jpflg = 1;
po2 <= po2 + 1;
end
2'h3:
begin
out <= str[po2];
po2 <= po2 + 1;
end
endcase
end
4'h6://beq
begin
if (q[1] == q[0])
begin
jpflg = 1;
pc <= opland;
end
pop;
pop;
end
4'h7://>bgt
begin
if (q[1] > q[0])
begin
jpflg = 1;
pc <= opland;
end
pop;
pop;
end
4'h8://>blt
begin
if (q[1] < q[0])
begin
jpflg = 1;
pc <= opland;
end
pop;
pop;
end
4'h9://br
begin
jpflg = 1;
pc <= opland;
end
4'ha://brture
begin
if (q[0] == 0)
begin
jpflg = 1;
pc <= opland;
end
pop;
end
4'hb://brfalse
begin
if (q[0] == 1)
begin
jpflg = 1;
pc <= opland;
end
pop;
end
4'hf:
begin
case (opland)
8'h00://dup
begin
push;
end
8'h01://pop
begin
pop;
end
8'h02://add
begin
q[0] <= q[1] + q[0];
pop;
end
8'h03://sub
begin
q[0] <= q[1] - q[0];
pop;
end
8'h04://mul
begin
q[0] <= q[1] * q[0];
pop;
end
8'h05://div
begin
q[0] <= q[1] / q[0];
pop;
end
8'h06://rem
begin
q[0] <= q[1] % q[0];
pop;
end
8'h07://rnd
begin
rnd <= rnd * 5 + 1;
push;
q[0] <= rnd;
end
8'h09://stloc a
begin
ram[0] <= q[0];
pop;
end
8'h0a://ldloc a
begin
push;
q[0] <= ram[0];
end
8'h0b://stloc b
begin
ram[1] <= q[0];
pop;
end
8'h0c://ldloc b
begin
push;
q[0] <= ram[1];
end
endcase
end
endcase
if (jpflg == 0)
pc <= pc + 1;
else
jpflg <= 0;
end
end
initial
begin
//$display(" pc, qtop, jpflg, ram, str, out");
//$monitor(" %d %d %d %d %d %s", pc, qtop, jpflg, ram[0], str[0], out);
end
endmodule
module test;
reg clk,
rst;
wire [7:0] outport;
cpu12 u(.clk(clk), .rst(rst), .outport(outport));
initial
begin
$monitor(" %s", outport);
clk = 0;
rst = 0;
#2
rst = 1;
#2
rst = 0;
#5500
$finish;
end
always
#1
clk = ~clk;
endmodule
実行結果
>iverilog il3.v
>vvp a.out
0
1
0
2
f
i
z
0
4
b
u
z
f
i
z
0
7
0
8
f
i
z
b
u
z
1
f
i
z
1
3
1
4
f
i
b
u
1
6
1
7
f
i
z
1
9
b
u
z
f
i
z
2
3
f
i
z
b
u
z
2
6
f
i
z
2
8
2
9
f
i
b
u
3
1
3
2
f
i
z
3
4
b
u
z
f
i
z
3
7
3
8
f
i
z
b
u
z
4
1
f
i
z
4
3
4
f
i
b
u
4
6
4
7
f
i
z
4
9
b
u
z
f
i
z
5
2
5
3
f
i
z
b
u
z
5
6
f
i
z
5
8
5
9
f
i
b
u
6
1
6
2
f
i
z
6
4
b
u
z
f
i
z
6
7
6
8
f
i
z
b
u
z
7
1
f
i
z
7
3
7
4
f
i
b
u
7
6
7
f
i
z
7
9
b
u
z
f
i
z
8
2
8
3
f
i
z
b
u
z
8
6
f
i
z
8
9
f
i
b
u
9
1
9
2
f
i
z
9
4
b
u
z
f
i
z
9
7
9
8
f
i
z
b
u
z
il3.v:387: $finish called at 5504 (1s)
以上。