`timescale 1ns / 1ps
//-------------------------------------------------------
// File name    : plic_simple.v
// Title        : Platform-Level Interrupt Controller (ย่อ)
// Library      : RISC-V SoC, ตัวอย่างประกอบบทที่ 9
// Purpose      : Computer Architecture, Design and Verification
// Developers   : Krerk Piromsopa, Ph.D.
//              : Chulalongkorn University.
module plic_simple(
    input         clk,
    input         nreset,
    input  [3:0]  irq_in,           // 4 แหล่ง interrupt (bit 0 ไม่ใช้)
    input  [3:0]  addr,
    input  [31:0] wdata,
    input         we,
    output reg [31:0] rdata,
    output        meip              // ส่งไปยัง CPU
);
    // priority ของแต่ละแหล่ง (3 บิต = 0..7) แหล่ง 0 ไม่ใช้
    reg [2:0] prio[1:3];
    reg [2:0] threshold;
    reg [3:0] enable;
    reg [1:0] claimed_id;
    reg       has_claim;

    integer i;
    reg [2:0] best_prio;
    reg [1:0] best_id;

    // หา interrupt ที่ priority สูงสุดและสูงกว่า threshold
    always @(*) begin
        best_prio = 3'b0;
        best_id   = 2'b0;
        for (i = 1; i <= 3; i = i + 1) begin
            if (irq_in[i] && enable[i] && prio[i] > best_prio) begin
                best_prio = prio[i];
                best_id   = i[1:0];
            end
        end
    end

    assign meip = (best_prio > threshold);

    // อ่าน register
    always @(*) begin
        case (addr)
            4'h0: rdata = {29'b0, prio[1]};
            4'h4: rdata = {29'b0, prio[2]};
            4'h8: rdata = {29'b0, prio[3]};
            4'hC: rdata = {28'b0, enable};
            // claim/complete: อ่าน = claim, เขียน = complete
            default: rdata = {30'b0, best_id};
        endcase
    end

    always @(posedge clk) begin
        if (nreset == 0) begin
            prio[1]    <= 3'b0;
            prio[2]    <= 3'b0;
            prio[3]    <= 3'b0;
            threshold  <= 3'b0;
            enable     <= 4'b0;
            has_claim  <= 1'b0;
            claimed_id <= 2'b0;
        end else if (we) begin
            case (addr)
                4'h0: prio[1] <= wdata[2:0];
                4'h4: prio[2] <= wdata[2:0];
                4'h8: prio[3] <= wdata[2:0];
                4'hC: enable  <= wdata[3:0];
                // ในความเป็นจริง claim/complete มี register ของตัวเอง
            endcase
        end
    end
endmodule
