windowsでiverilog その125

# 概要　

windowsでiverilogやってみた。
練習問題やってみた。

# 練習問題

cpuを実装せよ。

# 方針

スタックマシンを作る
スタックは、8bit×４
命令は、12bit固定長
romは、16
ramは、3

- 命令セット

|ニーモニック	|意味		|			stackの状態|	code
|:--|:--|:--|:--|
|nop		|何もしない。			|変化無し	|000
|jp i		|無条件でiへ飛ぶ。			|変化無し	|1nn
|push 1		|stackに整数を積む。			|1個増える	|2nn
|get i		|stackに変数iの値を入れる。		|1個増える	|3nn
|set i		|変数iにstackを入れる。			|1個減る		|4nn
|out		|stackをbyteで出力する。		|1個減る		|500
|if i		|stackが真ならiへ飛ぶ。			|1個減る	|	6nn
|if! i		|stackが偽ならiへ飛ぶ。			|1個減る|	7nn
|dup		|stackにコピーを積む。		|1個増える	|800
|drop		|stackを一個減らす。			|1個減る		|900
|+		|stack-1,stackの加算を求める。	|1個減る		|f00
|-		|stack-1,stackの減算を求める。	|1個減る		|f01
|*		|stack-1,stackの乗算を求める。	|1個減る		|f02
|/		|stack-1,stackの除算を求める。	|1個減る		|f03
|%		|stack-1,stackの剰余を求める。	|1個減る		|f04
|=		|stack-1,stackの等しいを求める。	|1個減る		|f05
|>		|stack-1,stackの大小を求める。	|1個減る		|f06




# サンプルコード

```

module cpu12(input clk, input rst, output [7:0] outport);
	parameter N = 4;
	integer i;
	reg [7:0] q[0:N - 1];
	reg [11:0] rom[15:0];
	reg [7:0] ram[2:0];
	reg jpflg;
	reg [7:0] pc;
	reg [7:0] out;
	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'h0_00;
			rom[1] <= 12'h2_01;
			rom[2] <= 12'h2_02;
			rom[3] <= 12'h4_01;
			rom[4] <= 12'h3_01;
			rom[5] <= 12'h5_00;
			rom[6] <= 12'h1_00;
			for (i = 0; i < N; i = i + 1)
				q[i] <= 0;
			jpflg <= 0;
			pc <= 0;
			ram[0] <= 0;
			ram[1] <= 0;
			ram[2] <= 0;
		end
		else
		begin
			case (op)
			4'h0://end
			begin
			end
			4'h1://jp
			begin
				jpflg = 1;
				pc <= opland;
			end
			4'h2://push
			begin
				push;
				q[0] <= opland;
			end
			4'h3://get
			begin
				push;
				q[0] <= ram[opland];
			end
			4'h4://set
			begin
				ram[opland] <= q[0];
				pop;
			end
			4'h5://out
			begin
				out <= q[0];
				pop;
			end
			4'h6://if
			begin
				if (q[0] == 1)
				begin
					jpflg <= 1;
					pc <= opland;
				end
			end
			4'h7://if!
			begin
				if (q[0] == 0)
				begin
					jpflg <= 1;
					pc <= opland;
				end
			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
				4'h5://=
				begin
					if (q[1] == q[0])
						q[0] <= 1;
					else
						q[0] <= 0;
					pop;
				end
				4'h6://>
				begin
					if (q[1] > q[0])
						q[0] <= 1;
					else
						q[0] <= 0;
					pop;
				end
				endcase
			end
			endcase
			if (jpflg == 0)
				pc <= pc + 1;
			else
				jpflg <= 0;
		end
	end
	initial
	begin
		$monitor("%d %d %d", pc, qtop, 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;
		#20
			$finish;
	end
	always
		#1
			clk = ~clk;
endmodule





```





以上