windowsでiverilog その146

# 概要　
windowsでiverilogやってみた。
cpu見つけたので、テストベンチ書いてみた。

# 参考にしたページ

https://github.com/kamaboko123/kanade32/tree/develop

# サンプルコード

```
module KANADE32(input reset_n, input clk);
	wire pc_wren;
	wire fd_wren;
	wire ram_addr_src;
	reg [31:0] ram_addr;
	always @*
	begin
		if (ram_addr_src == 0)
		begin
			ram_addr = pc_data;
		end
		else
		begin
			if (mw_dec_mem_read | mw_dec_mem_write)
			begin
				ram_addr = mw_alu_result;
			end
		end
	end
	wire [31:0] pc_data;
	wire [31:0] pc_data_inc;
	wire [31:0] ram_data;
	wire [31:0] fd_ins_data;
	wire [31:0] fd_next_pc;
	reg [4:0] fd_dst_reg;
	always @*
	begin
		if (fd_dec_pc_to_ra == 1)
		begin
			fd_dst_reg = 5'd31;
		end
		else
		begin
			fd_dst_reg = (fd_dec_reg_dst == 0) ? (fd_ins_data[20:16]) : (fd_ins_data[15:11]);
		end
	end
	wire de_wren;
	wire fd_dec_reg_dst;
	wire fd_dec_alu_src;
	wire fd_dec_mem_to_reg;
	wire fd_dec_reg_write;
	wire fd_dec_mem_read;
	wire fd_dec_mem_write;
	wire fd_dec_branch;
	wire fd_dec_jmp;
	wire fd_dec_pc_to_ra;
	wire fd_dec_alu_result_to_pc;
	wire [3:0] fd_dec_alu_op;
	wire [31:0] reg0;
	wire [31:0] reg1;
	wire [31:0] de_ins_data;
	wire em_wren;
	wire em_dec_alu_src;
	wire [3:0] em_alu_op;
	wire em_alu_result_zero;
	wire em_dec_mem_to_reg;
	wire em_dec_reg_write;
	wire em_dec_mem_read;
	wire em_dec_mem_write;
	wire em_dec_branch;
	wire em_dec_jmp;
	wire em_dec_alu_result_to_pc;
	wire em_dec_pc_to_ra;
	wire [31:0] em_reg0;
	wire [31:0] em_reg1;
	wire [31:0] em_data0;
	wire [31:0] em_data1;
	wire [31:0] em_imm;
	assign em_imm = {{16{em_ins_data[15]}}, em_ins_data[15:0]};
	assign em_data0 = em_reg0;
	assign em_data1 = (em_alu_src == 0) ? (em_reg1) : (em_imm);
	wire [4:0] em_dst_reg;
	wire [31:0] em_next_pc;
	wire [31:0] em_branch_pc;
	wire [31:0] em_alu_result;
	wire [31:0] em_ins_data;
	wire mw_wren;
	wire mw_alu_result_zero;
	wire mw_dec_mem_read;
	wire mw_dec_mem_write;
	wire mw_dec_branch;
	wire mw_dec_jmp;
	wire mw_dec_alu_result_to_pc;
	wire mw_mem_wren;
	wire mw_dec_pc_to_ra;
	wire mem_wren;
	assign mem_wren = (mw_mem_wren & mw_dec_mem_write);
	wire mw_pc_src;
	assign mw_pc_src = (mw_dec_branch & mw_alu_result_zero);
	wire mw_dec_mem_to_reg;
	wire mw_dec_reg_write;
	wire [31:0] _mw_next_pc;
	wire [31:0] mw_branch_pc;
	wire [31:0] mw_alu_result;
	wire [31:0] mw_mem_write_data;
	wire [31:0] mw_ins_data;
	reg [31:0] mw_next_pc;
	always @*
	begin
		if (mw_dec_jmp == 1)
		begin
			if (mw_dec_alu_result_to_pc)
			begin
				mw_next_pc = mw_alu_result;
			end
			else
			begin
				if (mw_dec_pc_to_ra == 1'b1)
				begin
					mw_next_pc = {4'b0, mw_ins_data[25:0], 2'b0};
				end
				else
				begin
					mw_next_pc = ({mw_next_pc[31:28], 28'b0} | {4'b0, mw_ins_data[25:0], 2'b0});
				end
			end
		end
		else
		begin
			mw_next_pc = (mw_pc_src == 0) ? (_mw_next_pc) : (mw_branch_pc);
		end
	end
	wire [31:0] mw_return_pc;
	assign mw_return_pc = _mw_next_pc;
	wire [4:0] mw_dst_reg;
	wire reg_wren;
	wire w_dec_reg_write;
	wire w_dec_mem_to_reg;
	wire _reg_wren;
	assign _reg_wren = (reg_wren & w_dec_reg_write);
	wire [31:0] w_alu_result;
	wire [31:0] w_mem_data;
	wire [4:0] w_dst_reg;
	wire w_dec_pc_to_ra;
	wire [31:0] w_return_pc;
	reg [31:0] w_reg_write_data;
	always @*
	begin
		if (w_dec_pc_to_ra)
		begin
			w_reg_write_data = w_return_pc;
		end
		else
		begin
			w_reg_write_data = (w_dec_mem_to_reg == 0) ? (w_alu_result) : (w_mem_data);
		end
	end
	wire stage_refresh_n;
	CONTROL ctrl(.reset_n(reset_n), .clk(clk), .pc_wren(pc_wren), .ram_addr_src(ram_addr_src), .fd_wren(fd_wren),
		.de_wren(de_wren), .em_wren(em_wren), .mw_wren(mw_wren), .mw_mem_wren(mw_mem_wren), .reg_wren(reg_wren), .refresh_n(stage_refresh_n));
	STAGE_REG_FD fd(.reset_n(stage_refresh_n), .clk(clk), .wren(fd_wren), .in_ins(ram_data),
		.in_next_pc(pc_data + 4), .ins(fd_ins_data), .next_pc(fd_next_pc));
	STAGE_REG_DE de(.reset_n(stage_refresh_n), .clk(clk), .wren(de_wren), .in_next_pc(fd_next_pc), .in_data0(reg0), .in_data1(reg1),
		.in_dst_reg(fd_dst_reg), .in_dec_alu_src(fd_dec_alu_src), .in_dec_mem_to_reg(fd_dec_mem_to_reg), .in_dec_reg_write(fd_dec_reg_write),
		.in_dec_mem_read(fd_dec_mem_read), .in_dec_mem_write(fd_dec_mem_write), .in_dec_branch(fd_dec_branch), .in_dec_jmp(fd_dec_jmp),
		.in_dec_alu_op(fd_dec_alu_op), .in_ins(fd_ins_data), .in_dec_alu_result_to_pc(fd_dec_alu_result_to_pc), .in_dec_pc_to_ra(fd_dec_pc_to_ra),
		.next_pc(em_next_pc), .data0(em_reg0), .data1(em_reg1), .dst_reg(em_dst_reg), .ins(em_ins_data), .dec_alu_src(em_alu_src),
		.dec_alu_op(em_alu_op), .dec_mem_to_reg(em_dec_mem_to_reg), .dec_reg_write(em_dec_reg_write), .dec_mem_read(em_dec_mem_read),
		.dec_mem_write(em_dec_mem_write), .dec_branch(em_dec_branch), .dec_jmp(em_dec_jmp), .dec_alu_result_to_pc(em_dec_alu_result_to_pc), .dec_pc_to_ra(em_dec_pc_to_ra));
	STAGE_REG_EM em(.reset_n(stage_refresh_n), .clk(clk), .wren(em_wren), .in_next_pc(em_next_pc), .in_branch_pc(em_branch_pc), .in_alu_result(em_alu_result),
		.in_mem_write_data(em_reg1), .in_dst_reg(em_dst_reg), .in_ins(em_ins_data), .in_dec_mem_to_reg(em_dec_mem_to_reg), .in_dec_reg_write(em_dec_reg_write),
		.in_dec_mem_read(em_dec_mem_read), .in_dec_mem_write(em_dec_mem_write), .in_dec_branch(em_dec_branch), .in_dec_jmp(em_dec_jmp),
		.in_alu_result_zero(em_alu_result_zero), .in_dec_alu_result_to_pc(em_dec_alu_result_to_pc), .in_dec_pc_to_ra(em_dec_pc_to_ra),
		.next_pc(_mw_next_pc), .branch_pc(mw_branch_pc), .alu_result(mw_alu_result), .mem_write_data(mw_mem_write_data), .dst_reg(mw_dst_reg),
		.ins(mw_ins_data), .dec_mem_to_reg(mw_dec_mem_to_reg), .dec_reg_write(mw_dec_reg_write), .dec_mem_read(mw_dec_mem_read), .dec_mem_write(mw_dec_mem_write),
		.dec_branch(mw_dec_branch), .dec_jmp(mw_dec_jmp), .alu_result_zero(mw_alu_result_zero), .dec_alu_result_to_pc(mw_dec_alu_result_to_pc), .dec_pc_to_ra(mw_dec_pc_to_ra));
	STAGE_REG_MW mw(.reset_n(stage_refresh_n), .clk(clk), .wren(mw_wren), .in_mem_data(ram_data), .in_alu_result(mw_alu_result), .in_dst_reg(mw_dst_reg),
		.in_return_pc(mw_return_pc), .in_dec_mem_to_reg(mw_dec_mem_to_reg), .in_dec_reg_write(mw_dec_reg_write), .in_dec_pc_to_ra(mw_dec_pc_to_ra),
		.mem_data(w_mem_data), .alu_result(w_alu_result), .dst_reg(w_dst_reg), .dec_mem_to_reg(w_dec_mem_to_reg), .dec_reg_write(w_dec_reg_write),
		.return_pc(w_return_pc), .dec_pc_to_ra(w_dec_pc_to_ra));
	REGFILE regfile(.reset_n(reset_n), .clk(clk), .reg_wren(_reg_wren), .r_reg0(fd_ins_data[25:21]), .r_reg1(fd_ins_data[20:16]),
		.w_reg0(w_dst_reg), .w_data(w_reg_write_data), .reg0(reg0), .reg1(reg1));
	DECODER dec(.ins_op(fd_ins_data[31:26]), .func_code(fd_ins_data[5:0]), .alu_src(fd_dec_alu_src), .reg_dst(fd_dec_reg_dst), .mem_to_reg(fd_dec_mem_to_reg),
		.reg_write(fd_dec_reg_write), .mem_read(fd_dec_mem_read), .mem_write(fd_dec_mem_write), .branch(fd_dec_branch), .jmp(fd_dec_jmp), .alu_op(fd_dec_alu_op),
		.pc_to_ra(fd_dec_pc_to_ra), .alu_result_to_pc(fd_dec_alu_result_to_pc));
	ALU alu(.op(em_alu_op), .a(em_data0), .b(em_data1), .x(em_alu_result), .zero(em_alu_result_zero));
	ALU pc_alu_branch(.op(`ALU_OP_ADD), .a(em_next_pc), .b({em_imm[29:0], 2'b00}), .x(em_branch_pc));
	PC pc(.reset_n(reset_n), .clk(clk), .wren(pc_wren), .jmp_to(mw_next_pc), .pc_data(pc_data));
	RAM ram(.clk(clk), .address(ram_addr[31:2]), .q(ram_data), .data(mw_mem_write_data), .wren(mem_wren));
	initial
	begin
		$display("   adr    pc    reg0   reg1");
		$monitor("%d %d %d %d ", ram_addr, pc_data, reg0, reg1);
	end
endmodule

`timescale 1 ns/ 100 ps

module TEST_KANADE32();
	parameter CLK = 10;
	reg reset_n;
	reg clk;
	KANADE32 kanade(.reset_n(reset_n), .clk(clk));
	always
	begin
		#(CLK)
			clk <= ~clk;
	end
	initial
	begin
		#0;
			reset_n <= 1;
			clk <= 0;
		#1
			reset_n <= 0;
		#(CLK * 4)
			reset_n <= 1;
		#2000
			$finish;
	end
endmodule





```

# 実行結果

```
>vvp a.out
WARNING: KANADE32.v:690: $readmemh: The behaviour for reg[...] mem[N:0]; $readmemh("...", mem); changed in the 1364-2005 standard. To avoid ambiguity, use mem[0:N] or explicit range parameters $readmemh("...", mem, start, stop);. Defaulting to 1364-2005 behavior.
WARNING: KANADE32.v:690: $readmemh(fibonacci.mem): Not enough words in the file for the requested range [0:255].
WARNING: KANADE32.v:453: $readmemh: The behaviour for reg[...] mem[N:0]; $readmemh("...", mem); changed in the 1364-2005 standard. To avoid ambiguity, use mem[0:N] or explicit range parameters $readmemh("...", mem, start, stop);. Defaulting to 1364-2005 behavior.
WARNING: KANADE32.v:453: $readmemh(test4.mem): Not enough words in the file for the requested range [0:2047].
   adr    pc    reg0   reg1
         x          x          x          x
         0          0          x          x
         0          0          0          0
         4          4          0          0
         8          8          0          0
         8          8          0          0
         8          8        255          1
        12         12        255          1
        12         12          0          0
KANADE32.v:1068: $finish called at 20410 (100ps)





```

以上。