ilasmでstack machine その60

# 概要
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)

```

以上。