LoginSignup
0
0

More than 3 years have passed since last update.

windowsでiverilog その10

Last updated at Posted at 2020-06-01

概要

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


以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0