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
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
以上。
Author And Source
この問題について(windowsでiverilog その10), 我々は、より多くの情報をここで見つけました https://qiita.com/ohisama@github/items/5acac9cfe674fba544d4著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .