ilasmでstack machine その44

# 概要
ilasmでstack machineやってみた。
俺cpuはstack machineなので、ilasmのニーモニックが動くように改造してみる。
verilogで書いてみた。
完成編。

# 改善したところ。

- コンパイラのラベルアドレスの解決がおかしいので、手作業で合わせる。
- outの出力を文字コードに変更。
intの場合、十の位、一の位の２回、出力。
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)

```


以上。