URL
https://opencores.org/ocsvn/simple_pic/simple_pic/trunk
Subversion Repositories simple_pic
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/tags/initial/rtl/simple_pic.v
File deleted
/trunk/rtl/simple_pic.v
File deleted
/simple_pic/trunk/rtl/simple_pic.v
0,0 → 1,247
///////////////////////////////////////////////////////////////////// |
//// //// |
//// OpenCores Simple Programmable Interrupt Controller //// |
//// //// |
//// Author: Richard Herveille //// |
//// richard@asics.ws //// |
//// www.asics.ws //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2002 Richard Herveille //// |
//// richard@asics.ws //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// CVS Log |
// |
// $Id: simple_pic.v,v 1.3 2002-12-24 10:26:51 rherveille Exp $ |
// |
// $Date: 2002-12-24 10:26:51 $ |
// $Revision: 1.3 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.2 2002/12/22 16:11:03 rherveille |
// *** empty log message *** |
// |
// |
|
|
|
// |
// 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 |
|
simple_pic/trunk
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: simple_pic/web_uploads
===================================================================
--- simple_pic/web_uploads (nonexistent)
+++ simple_pic/web_uploads (revision 6)
simple_pic/web_uploads
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: simple_pic/branches
===================================================================
--- simple_pic/branches (nonexistent)
+++ simple_pic/branches (revision 6)
simple_pic/branches
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: simple_pic/tags/initial/rtl/simple_pic.v
===================================================================
--- simple_pic/tags/initial/rtl/simple_pic.v (nonexistent)
+++ simple_pic/tags/initial/rtl/simple_pic.v (revision 6)
@@ -0,0 +1,241 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// OpenCores Simple Programmable Interrupt Controller ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2002 Richard Herveille ////
+//// richard@asics.ws ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+// CVS Log
+//
+// $Id: simple_pic.v,v 1.1.1.1 2002-12-02 17:19:58 rherveille Exp $
+//
+// $Date: 2002-12-02 17:19:58 $
+// $Revision: 1.1.1.1 $
+// $Author: rherveille $
+// $Locker: $
+// $State: Exp $
+//
+
+
+
+//
+// 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
+// 0x02: PolarityRegister
+// bits 7:0 R/W Polarity '1' = high level / rising edge
+// '0' = low level / falling edge
+// 0x03: MaskRegister
+// bits 7:0 R/W Mask '1' = interrupt masked (disabled)
+// '0' = interrupt not masked (enabled)
+// 0x04: 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
+
Index: simple_pic/tags
===================================================================
--- simple_pic/tags (nonexistent)
+++ simple_pic/tags (revision 6)
simple_pic/tags
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##