概要
windowsでiverilogやってみた。
練習問題やってみた。
練習問題
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 jpflg;
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
// 1
rom[0] <= 12'h2_01;
// set a
rom[1] <= 12'h4_00;
// 1
rom[2] <= 12'h2_01;
// set b
rom[3] <= 12'h4_01;
//loop get a
rom[4] <= 12'h3_00;
// get b
rom[5] <= 12'h3_01;
// *
rom[6] <= 12'hf_02;
// out3
rom[7] <= 12'h5_03;
// out2
rom[8] <= 12'h5_02;
// out1
rom[9] <= 12'h5_01;
// drop
rom[10] <= 12'h9_00;
// ' '
rom[11] <= 12'h2_20;
// out
rom[12] <= 12'h5_00;
// get a
rom[13] <= 12'h3_00;
// 1
rom[14] <= 12'h2_01;
// +
rom[15] <= 12'hf_00;
// set a
rom[16] <= 12'h4_00;
// 10
rom[17] <= 12'h2_0A;
// get a
rom[18] <= 12'h3_00;
// >
rom[19] <= 12'hf_06;
// if loop
rom[20] <= 12'h6_04;
// 10
rom[21] <= 12'h2_0A;
// out
rom[22] <= 12'h5_00;
// get b
rom[23] <= 12'h3_01;
// 1
rom[24] <= 12'h2_01;
// +
rom[25] <= 12'hf_00;
// set b
rom[26] <= 12'h4_01;
// 1
rom[27] <= 12'h2_01;
// set a
rom[28] <= 12'h4_00;
// 10
rom[29] <= 12'h2_0A;
// get b
rom[30] <= 12'h3_01;
// >
rom[31] <= 12'hf_06;
// if loop
rom[32] <= 12'h6_04;
//lup jmp lup
rom[33] <= 12'h1_21;
//
rom[34] <= 12'h2_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;
rnd <= 234;
end
else
begin
case (op)
4'h0://end
begin
end
4'h1://jmp
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
case (opland)
4'h0://out
begin
out <= q[0];
pop;
end
4'h1://out1
begin
out <= (q[0] % 10) + 48;
pop;
end
4'h2://out2
begin
out <= ((q[0] / 10) % 10) + 48;
pop;
end
4'h3:///out3
begin
out <= (q[0] / 100) + 48;
pop;
end
endcase
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'h8://dup
begin
push;
end
4'h9://drop
begin
pop;
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
4'h7://rnd
begin
rnd <= rnd * 5 + 1;
push;
q[0] <= rnd;
end
endcase
end
endcase
if (jpflg == 0)
pc <= pc + 1;
else
jpflg <= 0;
end
end
initial
begin
//$display("pc, ram0, out");
//$monitor(" %d %d %d %d %d %s", pc, qtop, jpflg, ram[0], rnd, 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;
#2950
$finish;
end
always
#1
clk = ~clk;
endmodule
実行結果
>iverilog cpu16.v
>vvp a.out
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0
9
0
2
0
4
0
6
0
8
0
1
0
0
1
2
0
1
4
0
1
6
0
1
8
0
3
0
6
0
9
0
1
2
0
1
5
0
1
8
0
2
1
0
2
4
0
2
7
0
4
0
8
0
1
2
0
1
6
0
2
0
0
2
4
0
2
8
0
3
2
0
3
6
0
5
0
1
0
0
1
5
0
2
0
0
2
5
0
3
0
0
3
5
0
4
0
0
4
5
0
6
0
1
2
0
1
8
0
2
4
0
3
0
0
3
6
0
4
2
0
4
8
0
5
4
0
7
0
1
4
0
2
1
0
2
8
0
3
5
0
4
2
0
4
9
0
5
6
0
6
3
0
8
0
1
6
0
2
4
0
3
2
0
4
0
0
4
8
0
5
6
0
6
4
0
7
2
0
9
0
1
8
0
2
7
0
3
6
0
4
5
0
5
4
0
6
3
0
7
2
0
8
1
以上。