windowsでiverilog その153

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

# 参考にしたページ

https://github.com/chance189/I2C_Master


# サンプルコード

```
module i2c_test_bench();
	//Slave address of ADT7420
	localparam [6:0] I2C_ADDR = 7'h4B;
	reg [7:0] slave_addr,
		i_data_write;
	reg [15:0] i_sub_addr;
	reg clk,
		reset_n,
		i_sub_len;
	reg request_transmit;
	reg [23:0] i_byte_len;
	reg en_sda,
		test_sda,
		test_sda_prev;
	reg start_ind,
		stop_ind;
	reg [7:0] test_data_in,
		test_data_out;
	wire [7:0] data_out;
	wire valid_out;
	wire scl;
	wire sda;
	wire req_data_chunk,
		busy,
		nack;
	assign sda = en_sda ? test_sda : 1'bz;
	integer i;
	i2c_master u(.i_clk(clk), .reset_n(reset_n), .i_addr_w_rw(slave_addr), .i_sub_addr(i_sub_addr), .i_sub_len(i_sub_len), .i_byte_len(i_byte_len), .i_data_write(i_data_write), .req_trans(request_transmit), .data_out(data_out), .valid_out(valid_out), .scl_o(scl), .sda_o(sda), .req_data_chunk(req_data_chunk), .busy(busy), .nack(nack));
	initial
	begin
		clk = 0;
		forever #(5000000) clk = !clk;
	end
	initial
	begin
		en_sda = 0;
		reset_n = 0;
		request_transmit = 1'b0;
		test_data_in = 0;
		test_data_out = 8'hBE;
		#500;
		reset_n = 1;
		#10000;
		$display("******** Write 2 Bytes Test: ********");
		slave_addr = {I2C_ADDR, 1'b0};
		i_data_write = 8'hFE;
		i_sub_addr = 8'h2E;
		i_sub_len = 1'b0;
		i_byte_len = 23'd2;
		@(posedge clk);
		request_transmit <= 1'b1;
		@(posedge busy);
		$display("Requisition Granted!");
		request_transmit = 1'b0;
		@(posedge start_ind);
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("SLAVE ADDR: %b", test_data_in);
		$display("Desired action: %s", test_data_in[0] ? "READ" : "WRITE");
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Sub Addr MSB: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Data Written, Byte 1: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(posedge req_data_chunk);
		i_data_write <= 8'h07;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Data Written Byte 2: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		@(posedge stop_ind);
		$display("%t, STOP INDICATION! Finished Write of 2 Bytes", $time);
		@(negedge busy);
		$display("Let go of bus");
		$display("******** Read_2 Bytes Test: ********");
		slave_addr = {I2C_ADDR, 1'b1};
		i_data_write = 8'hFE;
		i_sub_addr = 8'h2E;
		i_sub_len = 1'b0;
		i_byte_len = 23'd2;
		@(posedge clk);
		request_transmit <= 1'b1;
		@(posedge busy);
		$display("Requisition Granted!");
		request_transmit = 1'b0;
		@(posedge start_ind);
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("SLAVE ADDR: %b", test_data_in);
		$display("Desired action: %s", test_data_in[0] ? "READ" : "WRITE");
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Sub Addr MSB: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		@(posedge start_ind);
		$display("REPEAT START RECEIVED!");
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("SLAVE ADDR: %b", test_data_in);
		$display("Desired action: %s", test_data_in[0] ? "READ" : "WRITE");
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(negedge scl);
			#1;
			test_sda = test_data_out[i];
		end
		@(negedge scl);
		en_sda = 0;
		@(posedge scl);
		$display("RECEIVED: %s", sda ? "NACK" : "ACK");
		test_data_out = 8'hEF;
		@(negedge scl);
		en_sda = 1;
		test_sda = test_data_out[7];
		for(i = 6; i >= 0; i = i - 1)
		begin
			@(negedge scl);
			#1;
			test_sda = test_data_out[i];
		end
		@(negedge scl);
		en_sda = 0;
		@(posedge scl);
		$display("RECEIVED: %s", sda ? "NACK" : "ACK");
		@(posedge stop_ind);
		$display("%t, STOP INDICATION! Finished read of 2 bytes", $time);
		@(negedge busy);
		$display("Let go of bus");
		$display("******** Write 3 Bytes Test, 16 bit sub addr: ********");
		slave_addr = {7'h3A, 1'b0};
		i_data_write = 8'hDE;
		i_sub_addr = 16'hBEEF;
		i_sub_len = 1'b1;
		i_byte_len = 23'd4;
		@(posedge clk);
		request_transmit <= 1'b1;
		@(posedge busy);
		$display("Requisition Granted!");
		request_transmit = 1'b0;
		@(posedge start_ind);
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("SLAVE ADDR: %b", test_data_in);
		$display("Desired action: %s", test_data_in[0] ? "READ" : "WRITE");
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Sub Addr MSB: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Sub Addr LSB: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Data Written, Byte 1: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(posedge req_data_chunk);
		i_data_write <= 8'hAD;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Data Written Byte 2: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(posedge req_data_chunk);
		i_data_write <= 8'hBE;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Data Written Byte 3: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(posedge req_data_chunk);
		i_data_write <= 8'hEF;
		@(negedge scl);
		#10;
		en_sda = 0;
		for(i = 7; i >= 0; i = i - 1)
		begin
			@(posedge scl);
			#1;
			test_data_in[i] = sda;
		end
		$display("Data Written Byte 4: %h", test_data_in);
		@(negedge scl);
		#10;
		en_sda = 1;
		test_sda = 1'b0;
		@(negedge scl);
		#10;
		en_sda = 0;
		@(posedge stop_ind);
		$display("%t, STOP INDICATION! Finished Write of 2 Bytes", $time);
		@(negedge busy);
		$display("Let go of bus");
		$display("******** Test Finished ********");
		#10
			$finish;
	end
	always@(posedge clk or negedge reset_n)
	begin
		if (!reset_n)
		begin
			{start_ind, stop_ind, test_sda_prev} <= 0;
		end
		else
		begin
			test_sda_prev <= sda;
			start_ind <= test_sda_prev & !sda & scl;
			stop_ind <= !test_sda_prev & sda & scl;
		end
	end
	initial
	begin
		$dumpfile("test.vcd");
		$dumpvars(0, u);
	end
endmodule

```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/21969ba4-169f-e908-f3a8-f7edd4e0cd4d.png)

以上。