ChatGPTでVerilogのコードを生成してみた

ChatGPTで8段のFIFOを生成してみました。プロンプトは次のとおりです。

write a 8-bit, 8-depth synchronous fifo in verilog

次のコードが生成されました。ほぼ問題のない、期待どおりのコードが生成されました。論理合成を行う場合、メモリ(mem)の初期化に問題がありそうですが、FIFOの動作としては問題なさそうです。

module fifo_8bit_8depth (
    input wire clk,            // Clock
    input wire reset,          // Reset
    input wire wr_en,          // Write enable
    input wire rd_en,          // Read enable
    input wire [7:0] din,      // Data input
    output reg [7:0] dout,     // Data output
    output wire full,          // FIFO full
    output wire empty          // FIFO empty
);

    reg [7:0] mem [7:0];       // FIFO memory array
    reg [2:0] wr_ptr;          // Write pointer
    reg [2:0] rd_ptr;          // Read pointer
    reg [3:0] fifo_cnt;        // FIFO count

    // Write operation
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            wr_ptr <= 3'b0;
        end else if (wr_en && !full) begin
            mem[wr_ptr] <= din;
            wr_ptr <= wr_ptr + 1;
        end
    end

    // Read operation
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            rd_ptr <= 3'b0;
            dout <= 8'b0;
        end else if (rd_en && !empty) begin
            dout <= mem[rd_ptr];
            rd_ptr <= rd_ptr + 1;
        end
    end

    // FIFO count
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            fifo_cnt <= 4'b0;
        end else begin
            case ({wr_en, rd_en})
                2'b01: fifo_cnt <= fifo_cnt - 1;  // Read operation
                2'b10: fifo_cnt <= fifo_cnt + 1;  // Write operation
                default: fifo_cnt <= fifo_cnt;    // No operation or simultaneous read/write
            endcase
        end
    end

    // FIFO full and empty flags
    assign full = (fifo_cnt == 4'b1000);
    assign empty = (fifo_cnt == 4'b0000);

endmodule

FPGA and Verilog Export Custom ChatGPT

次のコードは、”FPGA and Verilog Export”というカスタム版のChatGPTで生成したコードです。プロンプトは、先ほどと同じ”write a 8-bit, 8-depth synchronous fifo in verilog”です。FullやEmptyの信号がレジスタ出力になっている点が、ノーマルのChatGPTの出力と異なります。論理合成を行う場合、メモリ(fifo_mem)の初期化に問題がありそうですが、プロンプトで指定を行えば、論理合成に対応したコードが出力されるのかもしれません。

module fifo_8x8 (
    input wire clk,           // Clock input
    input wire rst,           // Reset input (active high)
    input wire wr_en,         // Write enable
    input wire rd_en,         // Read enable
    input wire [7:0] din,     // Data input
    output reg [7:0] dout,    // Data output
    output reg full,          // FIFO full flag
    output reg empty          // FIFO empty flag
);

    reg [7:0] fifo_mem [0:7];  // FIFO memory array
    reg [2:0] wr_ptr = 3'b0;   // Write pointer
    reg [2:0] rd_ptr = 3'b0;   // Read pointer
    reg [3:0] count = 4'b0;    // FIFO count

    // Write operation
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            wr_ptr <= 3'b0;
        end else if (wr_en && !full) begin
            fifo_mem[wr_ptr] <= din;
            wr_ptr <= wr_ptr + 1;
        end
    end

    // Read operation
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            rd_ptr <= 3'b0;
            dout <= 8'b0;
        end else if (rd_en && !empty) begin
            dout <= fifo_mem[rd_ptr];
            rd_ptr <= rd_ptr + 1;
        end
    end

    // FIFO count and flags
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            count <= 4'b0;
            full <= 1'b0;
            empty <= 1'b1;
        end else begin
            // Update count
            if (wr_en && !full && (!rd_en || empty)) begin
                count <= count + 1;
            end else if (rd_en && !empty && (!wr_en || full)) begin
                count <= count - 1;
            end

            // Update flags
            full <= (count == 4'd8);
            empty <= (count == 4'd0);
        end
    end

endmodule

テストベンチについても、”create a testbench for the fifo.”とプロンプトを入力するだけで、申し分のないコードが生成されました。

module tb_fifo_8x8;

    // Parameters
    localparam CLK_PERIOD = 10; // Clock period in time units

    // Testbench signals
    reg clk;
    reg rst;
    reg wr_en;
    reg rd_en;
    reg [7:0] din;
    wire [7:0] dout;
    wire full;
    wire empty;

    // Instantiate the FIFO module
    fifo_8x8 uut (
        .clk(clk),
        .rst(rst),
        .wr_en(wr_en),
        .rd_en(rd_en),
        .din(din),
        .dout(dout),
        .full(full),
        .empty(empty)
    );

    // Generate clock signal
    initial begin
        clk = 0;
        forever #(CLK_PERIOD / 2) clk = ~clk;
    end

    // Testbench procedure
    initial begin
        // Initialize signals
        rst = 1;
        wr_en = 0;
        rd_en = 0;
        din = 8'b0;

        // Release reset after a few cycles
        #(2 * CLK_PERIOD);
        rst = 0;

        // Write data to the FIFO
        @(negedge clk);
        wr_en = 1;
        din = 8'hA1; // Write 0xA1
        @(negedge clk);
        din = 8'hB2; // Write 0xB2
        @(negedge clk);
        din = 8'hC3; // Write 0xC3
        @(negedge clk);
        din = 8'hD4; // Write 0xD4
        @(negedge clk);
        din = 8'hE5; // Write 0xE5
        @(negedge clk);
        din = 8'hF6; // Write 0xF6
        @(negedge clk);
        din = 8'h07; // Write 0x07
        @(negedge clk);
        din = 8'h18; // Write 0x18
        @(negedge clk);
        wr_en = 0; // Stop writing

        // Attempt to write when FIFO is full
        @(negedge clk);
        wr_en = 1;
        din = 8'h99;
        @(negedge clk);
        wr_en = 0;

        // Read data from the FIFO
        @(negedge clk);
        rd_en = 1;
        @(negedge clk);
        @(negedge clk);
        @(negedge clk);
        @(negedge clk);
        @(negedge clk);
        @(negedge clk);
        @(negedge clk);
        @(negedge clk);
        rd_en = 0; // Stop reading

        // Attempt to read when FIFO is empty
        @(negedge clk);
        rd_en = 1;
        @(negedge clk);
        rd_en = 0;

        // End of simulation
        #(2 * CLK_PERIOD);
        $finish;
    end

    // Monitor signals
    initial begin
        $monitor("Time: %0t | rst: %b | wr_en: %b | rd_en: %b | din: %h | dout: %h | full: %b | empty: %b",
                 $time, rst, wr_en, rd_en, din, dout, full, empty);
    end

endmodule
タイトルとURLをコピーしました