windowsでiverilog その10

#概要

windowsでiverilogやってみた。
fizzbuzz、書いてみた。

#仕組み

clkを走らせて、bcdでカウントして、15と5と3の剰余を見て、outに出す。

#サンプルコード


```

module bcd_counter(input clk, input rst, input increment, output reg [3:0] digit2, output reg [3:0] digit1, output reg [3:0] digit0);
	always @(posedge clk)
	begin
		if (rst)
		begin
			digit2 <= 4'b0;
			digit1 <= 4'b0;
			digit0 <= 4'b0;
		end
		else if (increment)
		begin
			if (digit0 != 4'd9)
			begin
				digit0 <= digit0 + 1'b1;
			end
			else
			begin
				digit0 <= 4'd0;
				if (digit1 != 4'd9)
				begin
					digit1 <= digit1 + 1'b1;
				end
				else
				begin
					digit1 <= 4'd0;
					digit2 <= digit2 + 1'b1;
				end
			end
		end
	end
endmodule

module fizzbuzz(input clk, input rst, output [7:0] out);
	reg [1:0] mod3;
	reg [2:0] mod5;
	reg [7:0] char;
	reg serial_send;
	reg [3:0] state;
	localparam NEXT = 4'b0,
		DONE = 4'b1111;
	wire increment = (state == NEXT) ? 1'b1 : 1'b0;
	wire [3:0] digit2,
		digit1,
		digit0;
	assign out = char;
	bcd_counter bcd_counter(.clk(clk), .rst(rst), .increment(increment), .digit2(digit2), .digit1(digit1), .digit0(digit0));
	always @(posedge clk)
	begin
		serial_send <= 1'b0;
		if (rst)
		begin
			mod3 <= 2'd0;
			mod5 <= 3'd0;
			state <= NEXT;
		end
		else if (state == NEXT)
		begin
			if (digit2 == 1 && digit1 == 0 && digit0 == 0)
			begin
				state <= DONE;
			end
			else
			begin
				mod3 <= (mod3 == 2) ? 2'b0 : mod3 + 1'b1;
				mod5 <= (mod5 == 4) ? 3'b0 : mod5 + 1'b1;
				state <= 1;
			end
		end
		else if (!serial_send && state != DONE)
		begin
			state <= state + 1'b1;
			serial_send <= 1'b1;
			if (mod3 == 2'b0 && mod5 == 3'b0)
			begin
				case (state)
				1:
					char <= "F";
				2:
					char <= "I";
				3:
					char <= "Z";
				4:
					char <= "Z";
				5:
					char <= "B";
				6:
					char <= "U";
				7:
					char <= "Z";
				8:
					char <= "Z";
				9:
					char <= "\r";
				10:
				begin
					char <= "\n";
					state <= NEXT;
				end
				endcase
			end
			else if (mod3 == 2'b0)
			begin
				case (state)
				1:
					char <= "F";
				2:
					char <= "I";
				3:
					char <= "Z";
				4:
					char <= "Z";
				5:
					char <= "\r";
				6:
				begin
					char <= "\n";
					state <= NEXT;
					end
				endcase
			end
			else if (mod5 == 3'b0)
			begin
				case (state)
				1:
					char <= "B";
				2:
					char <= "U";
				3:
					char <= "Z";
				4:
					char <= "Z";
				5:
					char <= "\r";
				6:
				begin
					char <= "\n";
					state <= NEXT;
				end
				endcase
			end
			else
			begin
				case (state)
				1:
				begin
					if (digit2 == 0)
					begin
						serial_send <= 0;
					end
					else
					begin
						char <= {2'b11, digit2[3:0]};
					end
				end
				2:
				begin
					if (digit2 == 0 && digit1 == 0)
					begin
						serial_send <= 0;
					end
					else
					begin
						char <= {2'b11, digit1[3:0]};
					end
				end
				3:
					char <= {2'b11, digit0[3:0]};
				4:
					char <= "\r";
				5:
				begin
					char <= "\n";
					state <= NEXT;
				end
				endcase
			end
		end
	end
endmodule

module test();
	reg clk;
	reg rst;
	wire [7:0] out;
	fizzbuzz u(.clk(clk), .rst(rst), .out(out));
	initial
	begin
		$monitor("%c", out);
		rst = 0;
		#10
			rst = 1;
		#10
			rst = 0;
		#4000
			$finish;
	end
	always
	begin
		#5
			clk = 1;
		#5
			clk = 0;
	end
endmodule





```

#結果


```


1
r


2
r


F
I
Z
r


4
r


B
U
Z
r


F
I
Z
r


7
r


8
r


F
I
Z
r


B
U
Z
r


1
r


F
I
Z
r


1
3
r


1
4
r


F
I
Z
B
U
Z
r


1
6
r


1
7
r


F
I
Z
r


1
9
r


B
U
Z
r


F
I
Z
r


2
r


2
3
r


F
I
Z
r


B
U
Z
r


2
6
r


F
I
Z
r


2
8
r


2
9
r


F
I
Z
B
U
Z
r


3
1
r


3
2
r


F
I
Z
r


3
4
r


B
U
Z
r


F
I
Z
r


3
7
r


3
8


```

以上。