//------------------------------------------------------------ // 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 };