LoginSignup
1
0

More than 1 year has passed since last update.

windowsでiverilog その125

Last updated at Posted at 2021-12-16

概要 

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

練習問題

cpuを実装せよ。

方針

スタックマシンを作る
スタックは、8bit×4
命令は、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





以上

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0