概要
windowsでiverilogやってみた。
74181なverilog見つけたので、やってみた。
74181使って、4bitCPU書いてみた。
cpu仕様
レジスタマシン
- レジスタ
4bitレジスタj,k
プログラムカウンタpc,4bit
alu,74181 - メモリ
8bit、16個 - 命令
4'h0://nop
4'h1://if (k > 0) pc = adr
4'h2://j = v
4'h3://k = v
4'h4://j = j + 1
4'h5://k = k - 1
4'h6://out
4'h7://jmp
1から10まで数えよ
mem[0] <= 8'h2_1; //j = 1
mem[1] <= 8'h3_A; //k = 10
mem[2] <= 8'h4_1; //j = j + 1
mem[3] <= 8'h6_0; //out
mem[4] <= 8'h5_1; //k = k - 1
mem[5] <= 8'h1_2; //if (k > 0) pc = 2
mem[6] <= 8'h7_6; //jmp 6
mem[7] <= 8'h0_0; //
mem[8] <= 8'h0_0; //
mem[9] <= 8'h0_0; //
サンプルコード
module alu(output wire f, output wire co_x, input wire a, input wire b, input wire ci_x, input wire [3:0] s, input wire m);
wire g;
wire h;
assign g = !(a | (b & s[0]) | (!b & s[1]));
assign h = !((!b & s[2] & a) | (a & s[3] & b));
assign co_x = (g | (h & ci_x));
assign f = !(!m & ci_x) ^ g ^ h;
endmodule
module alu74181 #(parameter WIDTH = 4) (output wire [WIDTH - 1:0] f, output wire co_x, input wire [WIDTH - 1:0] a, input wire [WIDTH - 1:0] b, input wire ci_x, input wire [3:0] s, input wire m);
genvar i;
wire [WIDTH:0] c_x;
assign c_x[0] = ci_x;
assign co_x = c_x[WIDTH];
generate
for (i = 0; i < WIDTH; i = i + 1)
begin
alu lu(.f(f[i]), .co_x(c_x[i + 1]), .a(a[i]), .b(b[i]), .ci_x(c_x[i]), .s(s), .m(m));
end
endgenerate
endmodule
module neos(input clk, input rst, output [3:0] outport);
wire [3:0] f;
reg [3:0] a;
reg [3:0] b;
reg cy;
reg [3:0] s;
reg m;
reg [3:0] j,
k,
pc;
reg w;
reg [7:0] mem[9:0];
wire [7:0] code;
wire [3:0] op;
wire [3:0] opland;
assign code = mem[pc];
assign op = code[7:4];
assign opland = code[3:0];
assign outport = j;
alu74181 u(.f(f), .a(a), .b(b), .ci_x(cy), .s(s), .m(m));
always @(posedge clk, negedge rst)
begin
if (!rst)
begin
mem[0] <= 8'h2_1; //j = 1
mem[1] <= 8'h3_A; //k = 10
mem[2] <= 8'h4_1; //j = j + 1
mem[3] <= 8'h6_0; //out
mem[4] <= 8'h5_1; //k = k - 1
mem[5] <= 8'h1_2; //if (k > 0) pc = 2
mem[6] <= 8'h7_6; //jmp 6
mem[7] <= 8'h0_0; //
mem[8] <= 8'h0_0; //
mem[9] <= 8'h0_0; //
j <= 4'h0;
k <= 4'h0;
pc <= 4'h0;
w <= 0;
end
else if (w == 1)
begin
j <= f;
w <= 0;
end
else
begin
case (op)
4'h0://nop
begin
end
4'h1://if (k > 0) pc = adr
begin
if (k > 0)
pc = opland - 1;
end
4'h2://j = v
begin
j <= opland;
end
4'h3://k = v
begin
k <= opland;
end
4'h4://j = j + 1
begin
a <= j;
b <= opland;
cy <= 1;
s <= 'h9;
m <= 0;
//j <= f;
w <= 1;
//j <= j + opland;
end
4'h5://k = k - 1
begin
k <= k - opland;
end
4'h6://out
begin
end
4'h7://jmp
begin
pc = opland - 1;
end
endcase
pc = pc + 1;
end
end
initial
begin
//$monitor("%d %d %d %d %d %d %d", pc, j, k, a, b, f, w);
end
endmodule
module test;
reg clk,
rst;
wire [3:0] outport;
neos u(.clk(clk), .rst(rst), .outport(outport));
initial
begin
clk = 0;
rst = 1;
#2
rst = 0;
#2
rst = 1;
#110
$finish;
end
always
#1
clk = ~clk;
initial
begin
$monitor("%d", outport);
end
endmodule
実行結果
>vvp a.out
x
0
1
2
3
4
5
6
7
8
9
10
11
neos4.v:135: $finish called at 114 (1s)
以上。