174 lines
4.7 KiB
Verilog
174 lines
4.7 KiB
Verilog
// 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
|