mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-12-22 23:08:39 +00:00
378 lines
14 KiB
Plaintext
378 lines
14 KiB
Plaintext
|
//------------------------------------------------------------
|
|||
|
// Block Level Interrupt Register
|
|||
|
//------------------------------------------------------------
|
|||
|
|
|||
|
reg block_int_r {
|
|||
|
name = "Example Block Interrupt Register";
|
|||
|
desc = "This is an example of an IP Block with 3 int events. 2 of these
|
|||
|
are non-fatal and the third event multi_bit_ecc_error is fatal";
|
|||
|
|
|||
|
default hw=w; // HW can Set int only
|
|||
|
default sw=rw; // SW can clear
|
|||
|
default woclr; // Clear is via writing a 1
|
|||
|
|
|||
|
field {
|
|||
|
desc = "A Packet with a CRC Error has been received";
|
|||
|
level intr;
|
|||
|
} crc_error = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "A Packet with an invalid length has been received";
|
|||
|
level intr;
|
|||
|
} len_error = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc="An uncorrectable multi-bit ECC error has been received";
|
|||
|
level intr;
|
|||
|
} multi_bit_ecc_error = 0 ;
|
|||
|
|
|||
|
field {
|
|||
|
desc="Master who was active when ECC Error Occurred";
|
|||
|
sticky;
|
|||
|
} active_ecc_master[7:4] = 0; // Example of multi-bit sticky field
|
|||
|
// This field is not an intr
|
|||
|
}; // End of Reg: block_int_r
|
|||
|
|
|||
|
reg block_int_en_r {
|
|||
|
name = "Example Block Interrupt Enable Register";
|
|||
|
desc = "This is an example of an IP Block with 3 int events";
|
|||
|
|
|||
|
default hw=na; // HW can't access the enables
|
|||
|
default sw=rw; // SW can control them
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Enable: A Packet with a CRC Error has been received";
|
|||
|
} crc_error = 0x1;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Enable: A Packet with an invalid length has been received";
|
|||
|
} len_error = 0x1;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Enable: A multi-bit error has been detected";
|
|||
|
} multi_bit_ecc_error = 0x0;
|
|||
|
}; // End of Reg: block_int_en_r
|
|||
|
|
|||
|
reg block_halt_en_r {
|
|||
|
name = "Example Block Halt Enable Register";
|
|||
|
desc = "This is an example of an IP Block with 3 int events";
|
|||
|
|
|||
|
default hw=na; // HW can't access the enables
|
|||
|
default sw=rw; // SW can control them
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Enable: A Packet with a CRC Error has been received";
|
|||
|
} crc_error = 0x0; // not a fatal error do not halt
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Enable: A Packet with an invalid length has been received";
|
|||
|
} len_error = 0x0; // not a fatal error do not halt
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Enable: A Packet with an invalid length has been received";
|
|||
|
} multi_bit_ecc_error = 0x1; // fatal error that will
|
|||
|
// cause device to halt
|
|||
|
}; // End of Reg: block_halt_en_r
|
|||
|
|
|||
|
//------------------------------------------------------------
|
|||
|
// Master Interrupt Status Register
|
|||
|
//------------------------------------------------------------
|
|||
|
|
|||
|
reg master_int_r {
|
|||
|
name = "Master Interrupt Status Register";
|
|||
|
desc = "This register contains the status of the 4 lower Module interrupts.
|
|||
|
Also an interrupt signal (myMasterInt) is generated which is the 'OR'
|
|||
|
of the four Module interrupts. A Halt signal is also generated which
|
|||
|
represents the bitwise or the masked/enabled halt bits";
|
|||
|
|
|||
|
default nonsticky intr; // Unless we want to have to clear this separately
|
|||
|
// from the leaf intr this should be non sticky
|
|||
|
|
|||
|
default hw=w; // HW normally won't want to access this but it could
|
|||
|
default sw=r; // Software can just read this. It clears the leaf intr's
|
|||
|
// to clear this
|
|||
|
field {
|
|||
|
desc = "An interrupt has occurred with ModuleD.
|
|||
|
Software must read the ModuleD Master Interrupt Register
|
|||
|
in order to determine the source of the interrupt.";
|
|||
|
} module_d_int[3:3] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "An interrupt has occurred with ModuleC.
|
|||
|
Software must read the ModuleC Master Interrupt Register
|
|||
|
in order to determine the source of the interrupt.";
|
|||
|
} module_c_int[2:2] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "An interrupt has occurred with ModuleB.
|
|||
|
Software must read the ModuleB Interrupt Register
|
|||
|
in order to determine the source of the interrupt.";
|
|||
|
} module_b_int[1:1] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "An interrupt has occurred with ModuleA.
|
|||
|
Software must read the ModuleA Master Interrupt Register
|
|||
|
in order to determine the source of the interrupt.";
|
|||
|
} module_a_int[0:0] = 0x0;
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
// The following is the accompanying enable register. Since the combinatorial
|
|||
|
// logic for processing the interrupt is internal to the generated verilog,
|
|||
|
// there's no need for an external port - which is realized by assigning "na"
|
|||
|
// to the hw attribute of the specific field. This could have been defined as
|
|||
|
// a mask register just as easily...
|
|||
|
//
|
|||
|
|
|||
|
//------------------------------------------------------------
|
|||
|
// Interrupt Enable Register
|
|||
|
//------------------------------------------------------------
|
|||
|
|
|||
|
reg master_int_en_r {
|
|||
|
name = "Master Interrupt Enable Register";
|
|||
|
desc = "Configurable register used in order to enable the corresponding
|
|||
|
interrupts found in myMasterInt register.";
|
|||
|
|
|||
|
default hw = na;
|
|||
|
default sw = rw;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Interrupt enable for ModuleD Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_d_int_en[3:3] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Interrupt enable for ModuleC Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_c_int_en[2:2] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Interrupt enable for ModuleB Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_b_int_en[1:1] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Interrupt enable for ModuleA Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_a_int_en[0:0] = 0x0;
|
|||
|
};
|
|||
|
|
|||
|
//------------------------------------------------------------
|
|||
|
// Halt Enable Register
|
|||
|
//------------------------------------------------------------
|
|||
|
|
|||
|
// The halt en is another enable or mask that could be used to generate an
|
|||
|
// alternate signal like a halt that represents a fatal error in the system or
|
|||
|
// some other event NOTE: It does not have to mean fatal as the name implies
|
|||
|
// its just another priority level for interrupts...
|
|||
|
|
|||
|
reg master_halt_en_r {
|
|||
|
name = "Master Halt Enable Register";
|
|||
|
desc = "Configurable register used in order to enable the corresponding
|
|||
|
interrupts found in myMasterInt register.";
|
|||
|
|
|||
|
default hw = na;
|
|||
|
default sw = rw;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Halt enable for ModuleD Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_d_halt_en[3:3] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Halt enable for ModuleC Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_c_halt_en[2:2] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Halt enable for ModuleB Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_b_halt_en[1:1] = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Halt enable for ModuelA Interrupts. 1 = enable, 0 = disable";
|
|||
|
} module_a_halt_en[0:0] = 0x0;
|
|||
|
};
|
|||
|
|
|||
|
//------------------------------------------------------------
|
|||
|
// Global Interrupt Status Register
|
|||
|
//------------------------------------------------------------
|
|||
|
|
|||
|
// This takes the block int which feeds the master int and then distills it
|
|||
|
// down one more level so we end up with a single bit intr and single bit halt...
|
|||
|
|
|||
|
//------------------------------------------------------------
|
|||
|
// Global Interrupt/Halt Enable Register
|
|||
|
//------------------------------------------------------------
|
|||
|
reg final_en_r {
|
|||
|
name = "My Final Enable Register";
|
|||
|
desc = "This enable allows all interrupts/halts to be suppressed
|
|||
|
with a single bit";
|
|||
|
|
|||
|
default hw = na;
|
|||
|
default sw = rw;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Global Interrupt Enable. 1 = enable, 0 = disable";
|
|||
|
} global_int_en = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Global Halt Enable. 1 = enable, 0 = disable";
|
|||
|
} global_halt_en = 0x0;
|
|||
|
};
|
|||
|
|
|||
|
reg final_int_r {
|
|||
|
name = "My Final Int/Halt Register";
|
|||
|
desc = "This distills a lower level interrupts into a final bit than can be
|
|||
|
masked";
|
|||
|
|
|||
|
default sw = r; // sw does not need to clear global_int
|
|||
|
// (global_int is of type final_int_r)
|
|||
|
// instead it clears itself when all master_int intr
|
|||
|
// bits get serviced
|
|||
|
|
|||
|
default nonsticky intr;
|
|||
|
default hw = w; // w needed since dyn assign below implies interconnect to hw
|
|||
|
// global_int.global_int->next = master_int->intr;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Global Interrupt";
|
|||
|
} global_int = 0x0;
|
|||
|
|
|||
|
field {
|
|||
|
desc = "Global Halt";
|
|||
|
} global_halt = 0x0;
|
|||
|
};
|
|||
|
|
|||
|
addrmap interrupt_hierarchy {
|
|||
|
signal { activelow; async; field_reset;} field_reset_n;
|
|||
|
|
|||
|
name = "Sample ASIC Interrupt Registers";
|
|||
|
desc = "This register map is designed how one can use interrupt concepts
|
|||
|
effectively in SystemRDL";
|
|||
|
|
|||
|
// Leaf Interrupts
|
|||
|
|
|||
|
// Block A Registers
|
|||
|
|
|||
|
block_int_r block_a_int; // Instance the Leaf Int Register
|
|||
|
block_int_en_r block_a_int_en; // Instance the corresponding Int Enable
|
|||
|
// Register
|
|||
|
block_halt_en_r block_a_halt_en; // Instance the corresponding halt enable
|
|||
|
// register
|
|||
|
|
|||
|
// This block connects the int bits to their corresponding
|
|||
|
// int enables and halt enables
|
|||
|
//
|
|||
|
block_a_int.crc_error->enable = block_a_int_en.crc_error;
|
|||
|
block_a_int.len_error->enable = block_a_int_en.len_error;
|
|||
|
block_a_int.multi_bit_ecc_error->enable = block_a_int_en.multi_bit_ecc_error;
|
|||
|
block_a_int.crc_error->haltenable = block_a_halt_en.crc_error;
|
|||
|
block_a_int.len_error->haltenable = block_a_halt_en.len_error;
|
|||
|
block_a_int.multi_bit_ecc_error->haltenable = block_a_halt_en.multi_bit_ecc_error;
|
|||
|
|
|||
|
// Block B Registers
|
|||
|
block_int_r block_b_int @0x100;
|
|||
|
block_int_en_r block_b_int_en;
|
|||
|
block_halt_en_r block_b_halt_en;
|
|||
|
|
|||
|
block_b_int.crc_error->enable = block_b_int_en.crc_error;
|
|||
|
block_b_int.len_error->enable = block_b_int_en.len_error;
|
|||
|
block_b_int.multi_bit_ecc_error->enable = block_b_int_en.multi_bit_ecc_error;
|
|||
|
block_b_int.crc_error->haltenable = block_b_halt_en.crc_error;
|
|||
|
block_b_int.len_error->haltenable = block_b_halt_en.len_error;
|
|||
|
block_b_int.multi_bit_ecc_error->haltenable = block_b_halt_en.multi_bit_ecc_error;
|
|||
|
|
|||
|
// Block C Registers
|
|||
|
block_int_r block_c_int @0x200;
|
|||
|
block_int_en_r block_c_int_en;
|
|||
|
block_halt_en_r block_c_halt_en;
|
|||
|
|
|||
|
block_c_int.crc_error->enable = block_c_int_en.crc_error;
|
|||
|
block_c_int.len_error->enable = block_c_int_en.len_error;
|
|||
|
block_c_int.multi_bit_ecc_error->enable = block_c_int_en.multi_bit_ecc_error;
|
|||
|
block_c_int.crc_error->haltenable = block_c_halt_en.crc_error;
|
|||
|
block_c_int.len_error->haltenable = block_c_halt_en.len_error;
|
|||
|
block_c_int.multi_bit_ecc_error->haltenable = block_c_halt_en.multi_bit_ecc_error;
|
|||
|
|
|||
|
// Block D Registers
|
|||
|
block_int_r block_d_int @0x300;
|
|||
|
block_int_en_r block_d_int_en;
|
|||
|
block_halt_en_r block_d_halt_en;
|
|||
|
|
|||
|
block_d_int.crc_error->enable = block_d_int_en.crc_error;
|
|||
|
block_d_int.len_error->enable = block_d_int_en.len_error;
|
|||
|
block_d_int.multi_bit_ecc_error->enable = block_d_int_en.multi_bit_ecc_error;
|
|||
|
block_d_int.crc_error->haltenable = block_d_halt_en.crc_error;
|
|||
|
block_d_int.len_error->haltenable = block_d_halt_en.len_error;
|
|||
|
block_d_int.multi_bit_ecc_error->haltenable = block_d_halt_en.multi_bit_ecc_error;
|
|||
|
|
|||
|
//
|
|||
|
// Master Interrupts
|
|||
|
//
|
|||
|
|
|||
|
master_int_r master_int @0x01000;
|
|||
|
master_int_r master_halt;
|
|||
|
master_int_en_r master_int_en;
|
|||
|
master_halt_en_r master_halt_en;
|
|||
|
|
|||
|
// Associate the INT’s with the EN’s
|
|||
|
master_int.module_d_int->enable = master_int_en.module_d_int_en;
|
|||
|
master_int.module_c_int->enable = master_int_en.module_c_int_en;
|
|||
|
master_int.module_b_int->enable = master_int_en.module_b_int_en;
|
|||
|
master_int.module_a_int->enable = master_int_en.module_a_int_en;
|
|||
|
|
|||
|
// Associate the HALT’s with the EN’s
|
|||
|
master_halt.module_d_int->haltenable = master_halt_en.module_d_halt_en;
|
|||
|
master_halt.module_c_int->haltenable = master_halt_en.module_c_halt_en;
|
|||
|
master_halt.module_b_int->haltenable = master_halt_en.module_b_halt_en;
|
|||
|
master_halt.module_a_int->haltenable = master_halt_en.module_a_halt_en;
|
|||
|
|
|||
|
// Now hook the lower level leaf interrupts to the higher level interrupts
|
|||
|
|
|||
|
// This connects the Implicit Or from Block A's INT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_int.module_a_int->next = block_a_int->intr;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block B's INT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_int.module_b_int->next = block_b_int->intr;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block C's INT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_int.module_c_int->next = block_c_int->intr;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block D's INT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_int.module_d_int->next = block_d_int->intr;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block A's HALT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_halt.module_a_int->next = block_a_int->halt;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block B's HALT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_halt.module_b_int->next = block_b_int->halt;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block C's HALT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_halt.module_c_int->next = block_c_int->halt;
|
|||
|
|
|||
|
// This connects the Implicit Or from Block D's HALT reg after
|
|||
|
// masking/enable to the next level up (master)
|
|||
|
master_halt.module_d_int->next = block_d_int->halt;
|
|||
|
|
|||
|
final_int_r global_int @0x1010;
|
|||
|
// Inst the global int/halt register
|
|||
|
|
|||
|
final_en_r global_int_en @0x1014;
|
|||
|
// Inst the global int/halt enable register
|
|||
|
|
|||
|
global_int.global_int->enable = global_int_en.global_int_en;
|
|||
|
// Associate the INT with the EN
|
|||
|
|
|||
|
global_int.global_halt->haltenable = global_int_en.global_halt_en;
|
|||
|
// Associate the HALT with the EN
|
|||
|
|
|||
|
global_int.global_int->next = master_int->intr;
|
|||
|
// Take the or of the 4 blocks in the master
|
|||
|
// Int and create one final interrupt
|
|||
|
|
|||
|
global_int.global_halt->next = master_halt->halt;
|
|||
|
// Take the or of the 4 blocks in the master
|
|||
|
// Int and create one final halt
|
|||
|
};
|