概要
ilasmでstack machineやってみた。
俺cpuはstack machineなので、ilasmのニーモニックが動くように改造してみる。
verilogで書いてみた。
完成編。
改善したところ。
- コンパイラのラベルアドレスの解決がおかしいので、手作業で合わせる。
- outの出力を文字コードに変更。
intの場合、十の位、一の位の2回、出力。
stringの場合、4字のバッファを導入して、4字のみ、出力。
サンプルコード
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
rom[0] = 12'h164;// ldc.i4 100
rom[1] = 12'hf0b;
rom[2] = 12'h101;// ldc.i4 1
rom[3] = 12'hf09;
rom[4] = 12'hf0a;
rom[5] = 12'hf0c;
rom[6] = 12'h730;//>>48
rom[7] = 12'hf0a;
rom[8] = 12'h10f;// ldc.i4 15
rom[9] = 12'hf06;// rem
rom[10] = 12'ha16;//>>22
rom[11] = 12'hf0a;
rom[12] = 12'h105;// ldc.i4 5
rom[13] = 12'hf06;// rem
rom[14] = 12'ha1d;//>>29
rom[15] = 12'hf0a;
rom[16] = 12'h103;// ldc.i4 3
rom[17] = 12'hf06;// rem
rom[18] = 12'ha24;//>>36
rom[19] = 12'hf0a;
rom[20] = 12'h400;
rom[21] = 12'h92b;//>>43
rom[22] = 12'h201;
rom[23] = 12'h266;
rom[24] = 12'h269;
rom[25] = 12'h262;
rom[26] = 12'h275;
rom[27] = 12'h200;
rom[28] = 12'h92a;//>>42
rom[29] = 12'h201;
rom[30] = 12'h262;
rom[31] = 12'h275;
rom[32] = 12'h27a;
rom[33] = 12'h27a;
rom[34] = 12'h200;
rom[35] = 12'h92a;//>>42
rom[36] = 12'h201;
rom[37] = 12'h266;
rom[38] = 12'h269;
rom[39] = 12'h27a;
rom[40] = 12'h27a;
rom[41] = 12'h200;
rom[42] = 12'h500;
rom[43] = 12'hf0a;
rom[44] = 12'h101;// ldc.i4 1
rom[45] = 12'hf02;
rom[46] = 12'hf09;
rom[47] = 12'h904;//>>4
rom[48] = 12'h001;
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;
#1000
$finish;
end
always
#1
clk = ~clk;
endmodule
実行結果
>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
il1.v:343: $finish called at 1004 (1s)
以上。