Verilog Function คืออะไร? อธิบายพื้นฐาน วิธีเขียน และตัวอย่างใช้งานสำหรับผู้เริ่มต้น

目次

1. Verilog function คืออะไร? (แนวคิดพื้นฐานและบทบาท)

Verilog HDL (Hardware Description Language) เป็นภาษาบรรยายฮาร์ดแวร์ที่ใช้สำหรับการออกแบบและการจำลองวงจรดิจิทัล ภายในนั้น function (ฟังก์ชัน) เป็นหนึ่งในกลไกที่ช่วยทำให้โค้ดถูกจัดโมดูลและนำกลับมาใช้ซ้ำได้ง่ายขึ้น

การทำความเข้าใจ Verilog function ไม่เพียงช่วยเพิ่มความสามารถในการอ่านและการบำรุงรักษาโค้ด แต่ยังนำไปสู่การออกแบบวงจรที่มีประสิทธิภาพมากขึ้น บทความนี้จะแนะนำแนวคิดพื้นฐานของ Verilog function และอธิบายวิธีการใช้งาน

function คืออะไร?

Verilog function คือ บล็อกที่ทำการคำนวณหรือประมวลผลเฉพาะแล้วส่งค่าหนึ่งค่าออกมา การใช้ function ช่วยลดความซ้ำซ้อนของโค้ดและทำให้งานออกแบบวงจรง่ายขึ้น

คุณสมบัติของ function

  • สามารถกำหนด input ได้มากกว่าหนึ่ง (ใช้ได้เฉพาะ input)
  • output มีเพียงหนึ่งค่า (ค่าที่ return)
  • ไม่สามารถใช้การหน่วงเวลา (delay เช่น #10)
  • ภายใน function ต้องอธิบายตรรกะการทำงานแบบ combinational logic เสมอ
  • function ต้องถูกประกาศนอก always block และจะถูกประเมินผลทันที ต่างจาก task

กรณีที่ใช้ Verilog function

Verilog function มักถูกใช้งานในกรณีดังต่อไปนี้

1. การอธิบายวงจรแบบ combinational

function จะส่งค่ากลับทันทีตาม input จึงนิยมใช้ใน combinational logic
ตัวอย่าง: การบวก การลบ encoder และ decoder

2. เพิ่มการนำโค้ดกลับมาใช้ซ้ำ

ช่วยลดโค้ดที่ซ้ำซ้อนและรวมการประมวลผลที่ต้องใช้หลายครั้งให้ง่ายขึ้น
ตัวอย่าง: สมการที่ซับซ้อนซึ่งมีการตรวจสอบเงื่อนไข สามารถทำให้เป็น function เพื่อเพิ่มความอ่านง่าย

3. ลดความผิดพลาดในการออกแบบ

การรวมการคำนวณและการดำเนินการทางตรรกะไว้ที่เดียว ช่วยลดความผิดพลาดเมื่อต้องแก้ไข
ตัวอย่าง: การคำนวณ CRC (Cyclic Redundancy Check) หรือ parity check

ความแตกต่างระหว่าง function และ task

ใน Verilog นอกจาก function ยังมี task ซึ่งมีลักษณะคล้ายกัน แต่มีความแตกต่างดังนี้

หัวข้อfunctiontask
outputมีเพียง 1 ค่ามีได้หลายค่า
inputมีมี
ตัวแปรภายในมีมี
delay (#10)ไม่อนุญาตอนุญาต
การใช้งานใน alwaysได้ไม่ได้
วิธีเรียกใช้งานชื่อฟังก์ชัน(อาร์กิวเมนต์)ชื่อตัว task(อาร์กิวเมนต์);

กรณีที่ควรใช้ function

  • เมื่อจำเป็นต้องได้ผลลัพธ์ทันที
  • ตรรกะที่ไม่ต้องมีการหน่วงเวลา
  • การประมวลผลที่เรียบง่ายและส่งค่ากลับเพียงค่าเดียว

กรณีที่ควรใช้ task

  • เมื่อมีการหน่วงเวลา (เช่น #10)
  • เมื่อจำเป็นต้องมีหลาย output
  • สำหรับการดีบักในการจำลอง (เช่น การ log ข้อมูล)

สรุป

  • Verilog function คือ ฟังก์ชันที่รับ input และคืนค่าเพียง 1 ค่า
  • เหมาะกับ combinational logic และไม่สามารถใส่ delay ได้
  • ช่วยลดโค้ดที่ซ้ำซ้อนและเพิ่มความสามารถในการอ่าน
  • function และ task มีความแตกต่าง ควรเลือกใช้งานตามวัตถุประสงค์

2. วิธีเขียน Verilog function【พร้อมตัวอย่างสำหรับผู้เริ่มต้น】

ในส่วนก่อนหน้าเราได้เรียนรู้แนวคิดพื้นฐานของ Verilog function แล้ว ที่นี่เราจะเจาะลึกวิธีการเขียน Verilog function อย่างละเอียด

โครงสร้างพื้นฐานของ function

Verilog function สามารถประกาศได้ตามโครงสร้างพื้นฐานดังนี้

function [ขนาดบิตของ output] ชื่อฟังก์ชัน;
    input [ขนาดบิตของ input] ชื่อ input1, input2, ...;
    begin
        ชื่อฟังก์ชัน = นิพจน์การคำนวณ;
    end
endfunction

จุดสำคัญ

  • ใช้คีย์เวิร์ด function เพื่อประกาศ
  • ค่าที่ return จะใช้ชื่อตัวแปรเดียวกับชื่อฟังก์ชัน
  • ต้องประกาศ input ด้วย input (ไม่สามารถใช้ output หรือ inout)
  • การประมวลผลต้องเขียนภายใน begin ... end
  • ต้องประกาศนอก always block

ตัวอย่าง Verilog function แบบง่าย

ด้านล่างนี้เป็นตัวอย่างฟังก์ชันที่ทำการบวกเลข 8 บิต

module example;
    function [7:0] add_function;
        input [7:0] a, b;
        begin
            add_function = a + b;
        end
    endfunction

    reg [7:0] x, y, sum;

    initial begin
        x = 8'b00001100; // 12
        y = 8'b00000101; // 5
        sum = add_function(x, y);
        $display("Sum: %d", sum); // Sum: 17
    end
endmodule

คำอธิบาย

  • add_function เป็น ฟังก์ชันที่รับค่า input ขนาด 8 บิตสองตัว (a, b) และคืนค่าผลบวก
  • เรียกฟังก์ชันโดยใช้ sum = add_function(x, y); และเก็บผลลัพธ์ไว้ในตัวแปร sum
  • ภายใน initial block ใช้ $display เพื่อแสดงผล

การประกาศ input และ output ใน Verilog function

การประกาศ input

Verilog function สามารถกำหนดเฉพาะ input เป็นอาร์กิวเมนต์ได้เท่านั้น

function [7:0] my_function;
    input [7:0] in1, in2;
    begin
        my_function = in1 & in2; // การดำเนินการ AND
    end
endfunction

หมายเหตุ: ไม่สามารถใช้ output ได้ ค่าที่ return จะถูกส่งกลับด้วย ตัวแปรที่มีชื่อเดียวกับฟังก์ชัน

Verilog function ที่มีการใช้เงื่อนไข

สามารถใช้ if หรือ case ภายในฟังก์ชันเพื่อทำการตรวจสอบเงื่อนไขได้

function [3:0] max_function;
    input [3:0] a, b;
    begin
        if (a > b)
            max_function = a;
        else
            max_function = b;
    end
endfunction

ฟังก์ชันนี้จะ คืนค่าที่มากกว่าระหว่าง a และ b

สรุป

  • Verilog function ต้องถูกประกาศด้วยคีย์เวิร์ด function และคืนค่าเพียงหนึ่งค่า
  • input ต้องเป็น input เท่านั้น (ไม่สามารถใช้ output)
  • ผลลัพธ์จะถูกส่งคืนด้วยตัวแปรที่มีชื่อเดียวกับฟังก์ชัน
  • สามารถใช้คำสั่งเงื่อนไข if และ case ได้

3. วิธีใช้งาน Verilog function【พร้อมโค้ดตัวอย่างจริง】

ในส่วนก่อนหน้าเราได้เรียนรู้โครงสร้างและวิธีเขียน Verilog function
ที่นี่เราจะอธิบาย วิธีการนำฟังก์ชันไปใช้จริงในการออกแบบ พร้อมตัวอย่างโค้ด

วิธีเรียกใช้ function

Verilog function ถูกเรียกใช้ในรูปแบบเดียวกับตัวแปรทั่วไป โดยใช้ ชื่อฟังก์ชัน(อาร์กิวเมนต์)
ตัวอย่างต่อไปนี้เป็นฟังก์ชัน XOR ขนาด 8 บิตและการใช้งานภายในโมดูล

module function_example;
    function [7:0] xor_function;
        input [7:0] a, b;
        begin
            xor_function = a ^ b;
        end
    endfunction

    reg [7:0] x, y, result;

    initial begin
        x = 8'b11001100;
        y = 8'b10101010;
        result = xor_function(x, y); // เรียกใช้ฟังก์ชัน
        $display("XOR Result: %b", result); // XOR Result: 01100110
    end
endmodule

จุดสำคัญ

  • เรียกฟังก์ชันด้วยรูปแบบ ตัวแปร = function(อาร์กิวเมนต์);
  • สามารถใช้ภายใน always block หรือ initial block ได้
  • ทำงานในลักษณะ combinational logic

การใช้ function ภายใน combinational logic

Verilog function จะถูก ประเมินผลทันที (immediate evaluation) จึงเหมาะสำหรับการสร้าง combinational logic
ตัวอย่างต่อไปนี้แสดงการใช้ function เพื่อสร้าง 2-to-4 decoder

module decoder_example;
    function [3:0] decoder;
        input [1:0] sel;
        begin
            case (sel)
                2'b00: decoder = 4'b0001;
                2'b01: decoder = 4'b0010;
                2'b10: decoder = 4'b0100;
                2'b11: decoder = 4'b1000;
                default: decoder = 4'b0000;
            endcase
        end
    endfunction

    reg [1:0] select;
    wire [3:0] decoded_output;

    assign decoded_output = decoder(select); // ใช้ function

    initial begin
        select = 2'b01;
        #10; // ใส่ delay เพื่อดูการเปลี่ยนแปลงในการจำลอง
        $display("Decoded Output: %b", decoded_output); // Decoded Output: 0010
    end
endmodule

คำอธิบาย

  • decoder function จะ แปลง input ขนาด 2 บิต ให้เป็น output ขนาด 4 บิต
  • ใช้คำสั่ง case เพื่อเลือก output ตาม input
  • ใช้คำสั่ง assign เพื่อนำผลลัพธ์จาก function ไปเก็บที่ decoded_output
    → function สามารถ ใช้เป็นส่วนหนึ่งของ combinational logic ได้

ความแตกต่างระหว่าง always และ function【ตารางเปรียบเทียบ】

ทั้ง Verilog function และ always block ใช้สำหรับอธิบาย logic แต่มีวัตถุประสงค์และข้อจำกัดที่แตกต่างกัน

หัวข้อfunctionalways
ตำแหน่งที่เขียนนอก always blockภายใน always block
inputใช้ได้เฉพาะ inputใช้ได้ทั้ง reg, wire
outputได้เพียงค่าเดียวอัปเดตได้หลายค่า
delay (#10)ไม่อนุญาตอนุญาต
การเก็บสถานะไม่สามารถ (ประเมินผลทันที)สามารถ (ใช้เป็น flip-flop ได้)
การใช้งานหลักcombinational logicsequential logic หรือ event-driven

แนวทางการเลือกใช้

  • function ใช้สำหรับเขียน logic ที่เป็น combinational อย่างกระชับ
  • always ใช้สำหรับวงจรที่มีสถานะ เช่น flip-flop
  • ถ้าต้องใช้ delay (#10) ต้องใช้ always ไม่ใช่ function

สรุปการใช้งาน Verilog function

✅ เรียกใช้ function ด้วยรูปแบบ ชื่อฟังก์ชัน(อาร์กิวเมนต์)
เหมาะสำหรับ combinational logic และมีบทบาทแตกต่างจาก always
✅ เขียน logic ที่ยืดหยุ่นได้ด้วย case และ if
เหมาะกับการใช้งานเช่น decoder และการคำนวณ

4. ตัวอย่างการประยุกต์ใช้ Verilog function (decoder และ ALU)

ที่ผ่านมาเราได้เรียนรู้โครงสร้างและวิธีใช้งาน Verilog function
ในส่วนนี้จะแสดง การประยุกต์ใช้ function ในการออกแบบวงจรจริง เช่น decoder และ ALU

การเขียน decoder ด้วย function (2-to-4 decoder)

decoder คือ วงจรที่แปลง input จำนวนน้อยบิตให้เป็น output ที่มีบิตมากขึ้น
เช่น input 2 บิต → output 4 บิต (2-to-4 decoder) เราสามารถเขียนได้โดยใช้ function

module decoder_example;
    function [3:0] decoder;
        input [1:0] sel;
        begin
            case (sel)
                2'b00: decoder = 4'b0001;
                2'b01: decoder = 4'b0010;
                2'b10: decoder = 4'b0100;
                2'b11: decoder = 4'b1000;
                default: decoder = 4'b0000;
            endcase
        end
    endfunction

    reg [1:0] select;
    wire [3:0] decoded_output;

    assign decoded_output = decoder(select); // เรียกใช้ function

    initial begin
        select = 2'b00; #10;
        $display("Decoded Output: %b", decoded_output);
        select = 2'b01; #10;
        $display("Decoded Output: %b", decoded_output);
        select = 2'b10; #10;
        $display("Decoded Output: %b", decoded_output);
        select = 2'b11; #10;
        $display("Decoded Output: %b", decoded_output);
    end
endmodule

การเขียน ALU ด้วย function (บวก ลบ AND OR)

ALU (Arithmetic Logic Unit) เป็นวงจรหลักใน CPU ที่ทำงานเกี่ยวกับการคำนวณ เช่น การบวก การลบ และการดำเนินการทางตรรกะ (AND, OR)
ที่นี่เราจะใช้ Verilog function เพื่อออกแบบ ALU 8 บิต แบบง่าย

module alu_example;
    function [7:0] alu;
        input [7:0] a, b;
        input [1:0] op; // สัญญาณควบคุม 2 บิต
        begin
            case (op)
                2'b00: alu = a + b; // บวก
                2'b01: alu = a - b; // ลบ
                2'b10: alu = a & b; // AND
                2'b11: alu = a | b; // OR
                default: alu = 8'b00000000;
            endcase
        end
    endfunction

    reg [7:0] x, y;
    reg [1:0] opcode;
    wire [7:0] result;

    assign result = alu(x, y, opcode); // ใช้ function

    initial begin
        x = 8'b00001100; // 12
        y = 8'b00000101; // 5

        opcode = 2'b00; #10;
        $display("Addition Result: %d", result); // 12 + 5 = 17

        opcode = 2'b01; #10;
        $display("Subtraction Result: %d", result); // 12 - 5 = 7

        opcode = 2'b10; #10;
        $display("AND Result: %b", result); // AND

        opcode = 2'b11; #10;
        $display("OR Result: %b", result); // OR
    end
endmodule

สรุป

function เหมาะสำหรับ combinational logic เช่น decoder และ ALU
สามารถใช้ case statement เพื่อกำหนดการทำงานได้อย่างยืดหยุ่น
ช่วยให้โค้ดอ่านง่ายและนำกลับมาใช้ซ้ำได้
function ใช้กับ combinational logic ได้ดี แต่ไม่เหมาะกับ sequential logic (ไม่สามารถใช้ delay ได้)

5. ข้อควรระวังในการใช้ Verilog function

Verilog function เป็นเครื่องมือที่ช่วยเพิ่มความสามารถในการอ่านและการนำโค้ดกลับมาใช้ซ้ำได้ แต่ก็มีข้อจำกัดบางอย่าง ส่วนนี้จะอธิบายรายละเอียดที่ควรระวัง

ไม่สามารถเรียกซ้ำ (recursive) ได้

ใน Verilog function ไม่อนุญาตให้เรียกซ้ำ (recursive call)
กล่าวคือ ไม่สามารถให้ function เรียกตัวเองได้

❌ ตัวอย่างที่ผิด: function แบบ recursive

function [3:0] factorial;
    input [3:0] n;
    begin
        if (n == 0)
            factorial = 1;
        else
            factorial = n * factorial(n - 1); // ❌ recursive call ไม่อนุญาต
    end
endfunction

โค้ดนี้จะทำให้ เกิด error ระหว่าง simulation

✅ วิธีแก้: ใช้ loop

ถ้าต้องการทำงานแบบ recursive ควรใช้ always block พร้อม loop หรือใช้ task

task factorial_task;
    input [3:0] n;
    output [15:0] result;
    integer i;
    begin
        result = 1;
        for (i = 1; i <= n; i = i + 1)
            result = result * i;
    end
endtask

การใช้ loop แบบนี้ช่วยหลีกเลี่ยง recursive ได้

ไม่สามารถใช้การหน่วงเวลา (delay #10) ภายใน function ได้

Verilog function จะถูก ประเมินผลทันที (ทำงานแบบ combinational logic)
ดังนั้นจึง ไม่สามารถใส่การหน่วงเวลา (เช่น #10) ได้

❌ ตัวอย่างที่ผิด: function ที่มี delay

function [7:0] delay_function;
    input [7:0] in;
    begin
        #10; // ❌ ไม่สามารถใช้ delay ภายใน function
        delay_function = in + 1;
    end
endfunction

โค้ดนี้จะทำให้เกิด compile error

✅ วิธีแก้: ใช้ always block

ถ้าต้องการใช้ delay ควรใช้ always block หรือ task

task delay_task;
    input [7:0] in;
    output [7:0] out;
    begin
        #10;
        out = in + 1;
    end
endtask

ดังนั้น หากต้องใช้ delay ต้องใช้ task แทน function

การเลือกใช้ function และ task อย่างเหมาะสม

ใน Verilog นอกจาก function ยังมีโครงสร้างที่เรียกว่า task
ทั้งสองมีความคล้ายคลึงกัน แต่มีวัตถุประสงค์ต่างกัน ต้องเลือกใช้ให้เหมาะสม

หัวข้อfunctiontask
outputเพียงค่าเดียว (return ด้วยชื่อฟังก์ชัน)ได้หลายค่า (กำหนดเป็น output ได้)
inputเฉพาะ inputใช้ได้ทั้ง input และ output
ตัวแปรภายในใช้ได้ใช้ได้
delay (#10)ไม่อนุญาตอนุญาต
การใช้งานภายใน alwaysได้ไม่ได้
วิธีเรียกใช้ชื่อฟังก์ชัน(อาร์กิวเมนต์)ชื่อตัว task(อาร์กิวเมนต์);

กรณีที่ควรใช้ function

✅ ต้องการผลลัพธ์ทันที (เช่น บวก ลบ การคำนวณทางตรรกะ)
✅ ใช้สำหรับ combinational logic ที่ไม่มี delay
✅ เหมาะกับการคืนค่าเพียง 1 ค่า

กรณีที่ควรใช้ task

✅ ต้องการใช้ delay (#10 เป็นต้น)
✅ ต้องการหลาย output
✅ ใช้สำหรับการ debug ในการจำลอง (monitoring, แสดงผล)

function ไม่สามารถประกาศภายใน always block ได้

Verilog function ไม่สามารถประกาศภายใน always block
ต้อง ประกาศภายนอกโมดูล แล้วเรียกใช้งานภายใน

❌ ตัวอย่างที่ผิด: การประกาศ function ภายใน always block

always @(a or b) begin
    function [7:0] my_function; // ❌ ห้ามประกาศ function ใน always
        input [7:0] x, y;
        begin
            my_function = x + y;
        end
    endfunction
end

โค้ดนี้จะทำให้เกิด compile error

✅ วิธีที่ถูกต้อง

ประกาศ function ภายนอก always block แล้วเรียกใช้งานภายใน

function [7:0] add_function;
    input [7:0] x, y;
    begin
        add_function = x + y;
    end
endfunction

always @(a or b) begin
    result = add_function(a, b); // ✅ เรียกใช้ function
end

ดังนั้น function ต้อง ถูกประกาศภายนอก always block เสมอ

สรุป

Verilog function มีข้อจำกัดหลายอย่าง
ไม่สามารถทำ recursive ได้ (ใช้ loop หรือ task แทน)
ไม่สามารถใช้ delay (#10) (ต้องใช้ always หรือ task แทน)
ไม่สามารถประกาศภายใน always block (ต้องประกาศภายนอก)
คืนค่าได้เพียง 1 ค่า (ถ้าต้องการหลาย output ต้องใช้ task)
ควรเลือกใช้ function และ task ให้เหมาะสม

6. 【FAQ】คำถามที่พบบ่อยเกี่ยวกับ Verilog function

ที่ผ่านมาเราได้อธิบายตั้งแต่พื้นฐานจนถึงการประยุกต์ใช้ และข้อควรระวังของ Verilog function
ในส่วนนี้คือ คำถามที่พบบ่อยและคำตอบ

ความแตกต่างระหว่าง function และ task คืออะไร?

Q. Verilog function และ task ต่างกันอย่างไร และควรใช้แบบไหน?

A. function คือ “การประมวลผลที่คืนค่าเพียงค่าเดียวทันที” ส่วน task ใช้สำหรับ “งานที่ต้องมีหลาย output หรือมี delay”

หัวข้อfunctiontask
outputเพียงค่าเดียว (คืนค่าด้วยชื่อฟังก์ชัน)ได้หลายค่า (กำหนด output ได้)
inputinput เท่านั้นใช้ได้ทั้ง input / output
ตัวแปรภายในใช้ได้ใช้ได้
delay (#10)ไม่อนุญาตอนุญาต
การใช้งานภายใน alwaysได้ไม่ได้
วิธีเรียกใช้ชื่อฟังก์ชัน(อาร์กิวเมนต์)ชื่อตัว task(อาร์กิวเมนต์);

กรณีที่ควรใช้ function

✅ ต้องการผลลัพธ์ทันที (เช่น บวก ลบ การดำเนินการทางตรรกะ)
✅ ใช้ใน combinational logic ที่ไม่มี delay
✅ ต้องการเพียงค่าเดียวเป็นผลลัพธ์

กรณีที่ควรใช้ task

✅ ต้องการใช้ delay (#10 เป็นต้น)
✅ ต้องการ output หลายค่า
✅ ใช้สำหรับการ debug ในการจำลอง (เช่น monitoring หรือ display)

สามารถใช้ reg ภายใน function ได้หรือไม่?

Q. ใน function สามารถประกาศตัวแปรแบบ reg ได้หรือไม่?

A. ไม่สามารถใช้ reg ได้ แต่สามารถใช้ integer แทนสำหรับการคำนวณ

ภายใน Verilog function ไม่อนุญาตให้ใช้ตัวแปรประเภท reg แต่สามารถใช้ integer เพื่อเก็บค่าชั่วคราวในการคำนวณได้

✅ ตัวอย่างที่ถูกต้อง (ใช้ integer)

function [7:0] multiply;
    input [3:0] a, b;
    integer temp;
    begin
        temp = a * b;
        multiply = temp;
    end
endfunction

ควรใช้ function ในสถานการณ์ใด?

Q. function เหมาะสำหรับใช้ในสถานการณ์ใด?

A. function เหมาะกับ “การคำนวณที่เรียบง่าย” และ “การอธิบาย combinational logic”

ตัวอย่างที่เหมาะสม ได้แก่:

  • การคำนวณ (บวก ลบ การดำเนินการทางตรรกะ)
  • decoder และ encoder
  • การเปรียบเทียบ (หาค่ามากสุด/น้อยสุด)
  • การตรวจสอบ error (เช่น parity check)

แต่ ไม่เหมาะกับ sequential logic (เช่น flip-flop)

สามารถเรียกใช้ function อื่นภายใน function ได้หรือไม่?

Q. สามารถเรียก function อื่นภายใน Verilog function ได้หรือไม่?

A. ได้ แต่ต้องระวังลำดับความสัมพันธ์ระหว่างฟังก์ชัน

function [7:0] add;
    input [7:0] a, b;
    begin
        add = a + b;
    end
endfunction

function [7:0] double_add;
    input [7:0] x, y;
    begin
        double_add = add(x, y) * 2; // เรียก function อื่นภายใน
    end
endfunction

การเลือกใช้ function และ always ต่างกันอย่างไร?

Q. ควรเลือกใช้ function และ always อย่างไร?

A. function ใช้กับ “combinational logic” ส่วน always ใช้กับ “sequential logic”

หัวข้อfunctionalways
delay (#10)ไม่อนุญาตอนุญาต
การเก็บสถานะไม่ได้ (ประเมินทันที)ได้ (ใช้เป็น flip-flop หรือ counter)
การใช้งานหลักcombinational logic (การคำนวณทันที)sequential logic (เช่น flip-flop, counter)

ตัวอย่าง: การบวก

✅ function (combinational)

function [7:0] add;
    input [7:0] a, b;
    begin
        add = a + b;
    end
endfunction

✅ always (sequential)

always @(posedge clk) begin
    sum <= a + b; // ทำงานเป็น flip-flop
end

สรุป

function เหมาะกับการคำนวณง่ายๆ และ combinational logic
ต้องเข้าใจความแตกต่างกับ task และเลือกใช้ให้ถูก
ต้องแยกการใช้งานกับ always ให้ชัดเจน (sequential vs combinational)
function ไม่สามารถใช้ delay (#10) หรือ array ได้ → ต้องใช้ task หรือ module