// synthesis attribute slice_utilization_ratio of IRQ_CTL is 7; module IRQ_CTL (CLK_I, RST_I, IRQ_O, IADR_O, IACK_I, ADR_I, DAT_I, DAT_O, STB_I, WE_I, SEL_I, ACK_O, IRQ7, IRQ6, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0); // Address layout (bytes): // 0x00..0x03 IADR0 // 0x04..0x07 IADR1 // 0x08..0x0B IADR2 // 0x0C..0x0F IADR3 // 0x10..0x13 IADR4 // 0x14..0x17 IADR5 // 0x18..0x1B IADR6 // 0x1C..0x1F IADR7 // 0x20 polarity[irq7..irq0] // 0x21 trigger[irq7..irq0] // 0x22 mask[irq7..irq0] // 0x23 status[irq7..irq0] // 0x24..0x3F reserved (0) // Triggers `define TR_LEVEL 1'b0 `define TR_EDGE 1'b1 // Polarities `define PL_LOW 1'b0 `define PL_HIGH 1'b1 `define PE_FALLING 1'b0 `define PE_RISING 1'b1 input CLK_I, RST_I, IACK_I, STB_I, WE_I; output IRQ_O, ACK_O; output [31:0] IADR_O; input [3:0] ADR_I; input [31:0] DAT_I; output [31:0] DAT_O; input [3:0] SEL_I; input IRQ7, IRQ6, IRQ5, IRQ4; input IRQ3, IRQ2, IRQ1, IRQ0; // synthesis attribute ram_style of IADR is distributed; reg [31:0] IADR[0:7]; reg [7:0] TRIGGER = 8'h00; reg [7:0] POLARITY = 8'hFF; reg [7:0] MASK = 8'h00; reg [7:0] STATUS = 8'h00; reg [7:0] PREV_IRQS = 8'h00; reg [7:0] DELIVERED = 8'h00; wire [7:0] PRIO_MASK = ~( DELIVERED | (DELIVERED<<1) | (DELIVERED<<2) | (DELIVERED<<3) | (DELIVERED<<4) | (DELIVERED<<5) | (DELIVERED<<6) | (DELIVERED<<7) ); wire [7:0] IRQS = { IRQ7, IRQ6, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 }; wire [7:0] MASKED_IRQS = STATUS & MASK & PRIO_MASK; // synthesis attribute priority_extract of HIGHEST_IRQ is force; reg [2:0] HIGHEST_IRQ; always @* begin if (MASKED_IRQS[0]) HIGHEST_IRQ <= 3'b000; else if (MASKED_IRQS[1]) HIGHEST_IRQ <= 3'b001; else if (MASKED_IRQS[2]) HIGHEST_IRQ <= 3'b010; else if (MASKED_IRQS[3]) HIGHEST_IRQ <= 3'b011; else if (MASKED_IRQS[4]) HIGHEST_IRQ <= 3'b100; else if (MASKED_IRQS[5]) HIGHEST_IRQ <= 3'b101; else if (MASKED_IRQS[6]) HIGHEST_IRQ <= 3'b110; else if (MASKED_IRQS[7]) HIGHEST_IRQ <= 3'b111; else HIGHEST_IRQ <= 3'bXXX; end // synthesis attribute decoder_extract of HIGHEST_BIT is yes; reg [7:0] HIGHEST_BIT; always @* begin case (HIGHEST_IRQ) 3'b000: HIGHEST_BIT <= 8'b00000001; 3'b001: HIGHEST_BIT <= 8'b00000010; 3'b010: HIGHEST_BIT <= 8'b00000100; 3'b011: HIGHEST_BIT <= 8'b00001000; 3'b100: HIGHEST_BIT <= 8'b00010000; 3'b101: HIGHEST_BIT <= 8'b00100000; 3'b110: HIGHEST_BIT <= 8'b01000000; default: HIGHEST_BIT <= 8'b10000000; endcase end wire [7:0] CLEAR_IRQS = (STB_I & WE_I & (ADR_I == 4'b1000) & SEL_I[0]) ? DAT_I[7:0] : 8'h00; // T[x] P[x] PIRQ[x] IRQ[x] | triggered // 0 0 0 0 | 1 // 0 0 0 1 | 0 // 0 0 1 0 | 1 // 0 0 1 1 | 0 // // 0 1 0 0 | 0 // 0 1 0 1 | 1 // 0 1 1 0 | 0 // 0 1 1 1 | 1 // // 1 0 0 0 | 0 // 1 0 0 1 | 0 // 1 0 1 0 | 1 // 1 0 1 1 | 0 // // 1 1 0 0 | 0 // 1 1 0 1 | 1 // 1 1 1 0 | 0 // 1 1 1 1 | 0 wire [7:0] TRIGGERED_IRQS; generate genvar i; for (i=0; i<=7; i=i+1) begin : trigger_luts LUT4 #( .INIT(16'b0010_0100_1010_0101) ) TriggerLUT ( .I3(TRIGGER[i]), .I2(POLARITY[i]), .I1(PREV_IRQS[i]), .I0(IRQS[i]), .O(TRIGGERED_IRQS[i]) ); end endgenerate always @(posedge CLK_I) begin if (RST_I) begin TRIGGER <= 8'h00; POLARITY <= 8'hFF; MASK <= 8'h00; STATUS <= 8'h00; PREV_IRQS <= 8'h00; DELIVERED <= 8'h00; end else begin STATUS <= (STATUS & ~CLEAR_IRQS) | TRIGGERED_IRQS; PREV_IRQS <= IRQS; if (IACK_I) DELIVERED <= (DELIVERED & ~CLEAR_IRQS) | HIGHEST_BIT; else DELIVERED <= (DELIVERED & ~CLEAR_IRQS); if (STB_I & WE_I & ~ADR_I[3]) IADR[ADR_I[2:0]] <= DAT_I; if (STB_I & WE_I & (ADR_I == 4'b1000)) begin if (SEL_I[3]) TRIGGER <= DAT_I[31:24]; if (SEL_I[2]) POLARITY <= DAT_I[23:16]; if (SEL_I[1]) MASK <= DAT_I[15: 8]; end end end wire [31:0] IADR_DATA, TPMS_DATA; assign IADR_O = IADR[HIGHEST_IRQ]; assign IADR_DATA = IADR[ADR_I[2:0]]; assign IRQ_O = |MASKED_IRQS; assign ACK_O = STB_I; assign TPMS_DATA = { TRIGGER, POLARITY, MASK, STATUS }; assign DAT_O = ~ADR_I[3] ? IADR_DATA : TPMS_DATA; endmodule