⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 中断控制器.txt

📁 这是一个中断控制器的IP
💻 TXT
字号:
// This is a simple Programmable Interrupt Controller.
// The number of interrupts is depending on the databus size.
// There's one interrupt input per databit (i.e. 16 interrupts for a 16
// bit databus).
// All attached devices share the same CPU priority level.
//
//
//
// Registers:
//
// 0x00: EdgeEnable Register
//       bits 7:0 R/W  Edge Enable '1' = edge triggered interrupt source
//                                 '0' = level triggered interrupt source
// 0x01: PolarityRegister
//       bits 7:0 R/W Polarity     '1' = high level / rising edge
//                                 '0' = low level / falling edge
// 0x02: MaskRegister
//       bits 7:0 R/W Mask         '1' = interrupt masked (disabled)
//                                 '0' = interrupt not masked (enabled)
// 0x03: PendingRegister
//       bits 7:0 R/W Pending      '1' = interrupt pending
//                                 '0' = no interrupt pending
//
// A CPU interrupt is generated when an interrupt is pending and its
// MASK bit is cleared.
//
//
//
// HOWTO:
//
// Clearing pending interrupts:
// Writing a '1' to a bit in the interrupt pending register clears the
// interrupt. Make sure to clear the interrupt at the source before
// writing to the interrupt pending register. Otherwise the interrupt
// will be set again.
//
// Priority based interrupts:
// Upon reception of an interrupt, check the interrupt register and
// determine the highest priority interrupt. Mask all interrupts from the
// current level to the lowest level. This negates the interrupt line, and
// makes sure only interrupts with a higher level are triggered. After
// completion of the interrupt service routine, clear the interrupt source,
// the interrupt bit in the pending register, and restore the MASK register
// to it's previous state.
//
// Addapt the core for fewer interrupt sources:
// If less than 8 interrupt sources are required, than the 'is' parameter
// can be set to the amount of required interrupts. Interrupts are mapped
// starting at the LSBs. So only the 'is' LSBs per register are valid. All
// other bits (i.e. the 8-'is' MSBs) are set to zero '0'.
// Codesize is approximately linear to the amount of interrupts. I.e. using
// 4 instead of 8 interrupt sources reduces the size by approx. half.
//


// synopsys translate_off
`include "timescale.v"
// synopsys translate_on

module simple_pic(
  clk_i, rst_i, cyc_i, stb_i, adr_i, we_i, dat_i, dat_o, ack_o, int_o,
  irq
);

  parameter is = 8;            // Number of interrupt sources

  //
  // Inputs & outputs
  //

  // 8bit WISHBONE bus slave interface
  input         clk_i;         // clock
  input         rst_i;         // reset (asynchronous active low)
  input         cyc_i;         // cycle
  input         stb_i;         // strobe  (cycle and strobe are the same signal)
  input  [ 2:1] adr_i;         // address
  input         we_i;          // write enable
  input  [ 7:0] dat_i;         // data output
  output [ 7:0] dat_o;         // data input
  output        ack_o;         // normal bus termination

  output        int_o;         // interrupt output

  //
  // Interrupt sources
  //
  input  [is:1] irq;           // interrupt request inputs


  //
  //  Module body
  //
  reg  [is:1] pol, edgen, pending, mask;   // register bank
  reg  [is:1] lirq, dirq;                  // latched irqs, delayed latched irqs


  //
  // perform parameter checks
  //
  // synopsys translate_off
  initial
  begin
      if(is > 8)
        $display("simple_pic: max. 8 interrupt sources supported.");
  end
  // synopsys translate_on

  //
  // latch interrupt inputs
  always @(posedge clk_i)
    lirq <= #1 irq;

  //
  // generate delayed latched irqs
  always @(posedge clk_i)
    dirq <= #1 lirq;


  //
  // generate actual triggers
  function trigger;
    input edgen, pol, lirq, dirq;

    reg   edge_irq, level_irq;
  begin
      edge_irq  = pol ? (lirq & ~dirq) : (dirq & ~lirq);
      level_irq = pol ? lirq : ~lirq;

      trigger = edgen ? edge_irq : level_irq;
  end
  endfunction

  reg  [is:1] irq_event;
  integer n;
  always @(posedge clk_i)
    for(n=1; n<=is; n=n+1)
      irq_event[n] <= #1 trigger(edgen[n], pol[n], lirq[n], dirq[n]);

  //
  // generate wishbone register bank writes
  wire wb_acc = cyc_i & stb_i;                   // WISHBONE access
  wire wb_wr  = wb_acc & we_i;                   // WISHBONE write access

  always @(posedge clk_i or negedge rst_i)
    if (~rst_i)
      begin
          pol   <= #1 {{is}{1'b0}};              // clear polarity register
          edgen <= #1 {{is}{1'b0}};              // clear edge enable register
          mask  <= #1 {{is}{1'b1}};              // mask all interrupts
      end
    else if(wb_wr)                               // wishbone write cycle??
      case (adr_i) // synopsys full_case parallel_case
        2'b00: edgen <= #1 dat_i[is-1:0];        // EDGE-ENABLE register
        2'b01: pol   <= #1 dat_i[is-1:0];        // POLARITY register
        2'b10: mask  <= #1 dat_i[is-1:0];        // MASK register
        2'b11: ;                                 // PENDING register is a special case (see below)
      endcase


    // pending register is a special case
    always @(posedge clk_i or negedge rst_i)
      if (~rst_i)
          pending <= #1 {{is}{1'b0}};            // clear all pending interrupts
      else if ( wb_wr & (&adr_i) )
          pending <= #1 (pending & ~dat_i[is-1:0]) | irq_event;
      else
          pending <= #1 pending | irq_event;

    //
    // generate dat_o
    reg [7:0] dat_o;
    always @(posedge clk_i)
      case (adr_i) // synopsys full_case parallel_case
        2'b00: dat_o <= #1 { {{8-is}{1'b0}}, edgen};
        2'b01: dat_o <= #1 { {{8-is}{1'b0}}, pol};
        2'b10: dat_o <= #1 { {{8-is}{1'b0}}, mask};
        2'b11: dat_o <= #1 { {{8-is}{1'b0}}, pending};
      endcase

   //
   // generate ack_o
   reg ack_o;
   always @(posedge clk_i)
     ack_o <= #1 wb_acc & !ack_o;

  //
  // generate CPU interrupt signal
  reg int_o;
  always @(posedge clk_i)
    int_o <= #1 |(pending & ~mask);

endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -