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


以上。