概要
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
以上