diff options
| -rw-r--r-- | control_lib/pic.v | 183 | ||||
| -rw-r--r-- | control_lib/priority_enc.v | 44 | ||||
| -rwxr-xr-x | top/u2_core/u2_core.v | 44 | ||||
| -rw-r--r-- | top/u2_rev3/Makefile | 3 | 
4 files changed, 259 insertions, 15 deletions
| diff --git a/control_lib/pic.v b/control_lib/pic.v new file mode 100644 index 000000000..9b9944d4a --- /dev/null +++ b/control_lib/pic.v @@ -0,0 +1,183 @@ + +// Heavily modified by M. Ettus, 2009, little original code remains +// Modified by M. Ettus, 2008 for 32 bit width + +///////////////////////////////////////////////////////////////////// +////                                                             //// +////  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.                                 //// +////                                                             //// +///////////////////////////////////////////////////////////////////// +// +// 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. +// + + +module pic +  (input clk_i, input rst_i, input cyc_i, input stb_i, +   input [2:0] adr_i,  +   input we_i,  +   input [31:0] dat_i,  +   output reg [31:0] dat_o,  +   output reg ack_o,  +   output reg int_o, +   input [31:0] irq +   ); + +   reg [31:0] 	pol, edgen, pending, mask;   // register bank +   reg [31:0] 	lirq, dirq;                  // latched irqs, delayed latched irqs +    +   // latch interrupt inputs +   always @(posedge clk_i) +     lirq <=  irq; +    +   // generate delayed latched irqs +   always @(posedge clk_i) +     dirq <=  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  [31:0] irq_event; +   integer     n; +   always @(posedge clk_i) +     for(n = 0; n < 32; n = n+1) +       irq_event[n] <=  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) +     if (rst_i) +       begin +          pol   <=  0;              // clear polarity register +          edgen <=  0;              // clear edge enable register +          mask  <=  0;              // mask all interrupts +       end +     else if(wb_wr)                               // wishbone write cycle?? +       case (adr_i) // synopsys full_case parallel_case +         3'd0 : edgen <=  dat_i;        // EDGE-ENABLE register +         3'd1 : pol   <=  dat_i;        // POLARITY register +         3'd2 : mask  <=  dat_i;        // MASK register +         3'd3 : ;                       // PENDING register is a special case (see below) +	 3'd4 : ;                       // Priority encoded live (pending & ~mask) +       endcase + +   // pending register is a special case +   always @(posedge clk_i) +     if (rst_i) +       pending <=  0;            // clear all pending interrupts +     else if ( wb_wr & (adr_i == 3'd3) ) +       pending <=  (pending & ~dat_i) | irq_event; +     else +       pending <=  pending | irq_event; + +   wire [31:0] live_enc; +   priority_enc priority_enc ( .in(pending & ~mask), .out(live_enc) ); +    +   always @(posedge clk_i) +      case (adr_i) // synopsys full_case parallel_case +        3'd0 : dat_o <= edgen; +        3'd1 : dat_o <= pol; +        3'd2 : dat_o <= mask; +        3'd3 : dat_o <= pending; +	3'd4 : dat_o <= live_enc; +      endcase + +   always @(posedge clk_i) +     ack_o <=  wb_acc & !ack_o; + +   always @(posedge clk_i) +     if(rst_i) +       int_o <=  0; +     else +       int_o <=  |(pending & ~mask); +    +endmodule diff --git a/control_lib/priority_enc.v b/control_lib/priority_enc.v new file mode 100644 index 000000000..916192445 --- /dev/null +++ b/control_lib/priority_enc.v @@ -0,0 +1,44 @@ + +module priority_enc +  (input [31:0] in, +   output reg [31:0] out); + +   always @* +     casex(in) +       32'b1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 31; +       32'b01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 30; +       32'b001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 29; +       32'b0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 28; +       32'b0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 27; +       32'b0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 26; +       32'b0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 25; +       32'b0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 24; +       32'b0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 23; +       32'b0000_0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 22; +       32'b0000_0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 21; +       32'b0000_0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 20; +       32'b0000_0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx : out <= 19; +       32'b0000_0000_0000_01xx_xxxx_xxxx_xxxx_xxxx : out <= 18; +       32'b0000_0000_0000_001x_xxxx_xxxx_xxxx_xxxx : out <= 17; +       32'b0000_0000_0000_0001_xxxx_xxxx_xxxx_xxxx : out <= 16; +       32'b0000_0000_0000_0000_1xxx_xxxx_xxxx_xxxx : out <= 15; +       32'b0000_0000_0000_0000_01xx_xxxx_xxxx_xxxx : out <= 14; +       32'b0000_0000_0000_0000_001x_xxxx_xxxx_xxxx : out <= 13; +       32'b0000_0000_0000_0000_0001_xxxx_xxxx_xxxx : out <= 12; +       32'b0000_0000_0000_0000_0000_1xxx_xxxx_xxxx : out <= 11; +       32'b0000_0000_0000_0000_0000_01xx_xxxx_xxxx : out <= 10; +       32'b0000_0000_0000_0000_0000_001x_xxxx_xxxx : out <=  9; +       32'b0000_0000_0000_0000_0000_0001_xxxx_xxxx : out <=  8; +       32'b0000_0000_0000_0000_0000_0000_1xxx_xxxx : out <=  7; +       32'b0000_0000_0000_0000_0000_0000_01xx_xxxx : out <=  6; +       32'b0000_0000_0000_0000_0000_0000_001x_xxxx : out <=  5; +       32'b0000_0000_0000_0000_0000_0000_0001_xxxx : out <=  4; +       32'b0000_0000_0000_0000_0000_0000_0000_1xxx : out <=  3; +       32'b0000_0000_0000_0000_0000_0000_0000_01xx : out <=  2; +       32'b0000_0000_0000_0000_0000_0000_0000_001x : out <=  1; +       32'b0000_0000_0000_0000_0000_0000_0000_0001 : out <=  0; +       32'b0000_0000_0000_0000_0000_0000_0000_0000 : out <= 32'hFFFF_FFFF; +       default : out <= 32'hFFFF_FFFF; +     endcase // casex (in) +    +endmodule // priority_enc diff --git a/top/u2_core/u2_core.v b/top/u2_core/u2_core.v index 03016e9b3..fd17a10a7 100755 --- a/top/u2_core/u2_core.v +++ b/top/u2_core/u2_core.v @@ -158,6 +158,7 @@ module u2_core     wire 	serdes_link_up;     wire 	epoch; +   wire [31:0] 	irq;     // ///////////////////////////////////////////////////////////////////////////////////////////////     // Wishbone Single Master INTERCON @@ -278,6 +279,7 @@ module u2_core  		 .wb_we_o(ram_loader_we),.wb_ack_i(ram_loader_ack),  		 .ram_loader_done_o(ram_loader_done)); +   // /////////////////////////////////////////////////////////////////////////     // Processor     aeMB_core_BE #(.ISIZ(16),.DSIZ(16),.MUL(0),.BSF(1))       aeMB (.sys_clk_i(wb_clk), .sys_rst_i(wb_rst), @@ -292,6 +294,7 @@ module u2_core     assign 	 bus_error = m0_err | m0_rty; +   // /////////////////////////////////////////////////////////////////////////     // Dual Ported RAM -- D-Port is Slave #0 on main Wishbone     // I-port connects directly to processor and ram loader @@ -314,6 +317,7 @@ module u2_core     setting_reg #(.my_addr(7)) sr_icache (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr),  					 .in(set_data),.out(),.changed(flush_icache)); +   // /////////////////////////////////////////////////////////////////////////     // Buffer Pool, slave #1     wire 	 rd0_ready_i, rd0_ready_o;     wire 	 rd1_ready_i, rd1_ready_o; @@ -353,6 +357,10 @@ module u2_core        .rd3_data_o(rd3_dat), .rd3_flags_o(rd3_flags), .rd3_ready_i(rd3_ready_i), .rd3_ready_o(rd3_ready_o)        ); +   wire [31:0] 	 status_enc; +   priority_enc priority_enc (.in({16'b0,status[15:0]}), .out(status_enc)); +    +   // /////////////////////////////////////////////////////////////////////////     // SPI -- Slave #2     spi_top shared_spi       (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.wb_adr_i(s2_adr[4:0]),.wb_dat_i(s2_dat_o), @@ -361,6 +369,7 @@ module u2_core        .ss_pad_o({sen_tx_db,sen_tx_adc,sen_tx_dac,sen_rx_db,sen_rx_adc,sen_rx_dac,sen_dac,sen_clk}),        .sclk_pad_o(sclk),.mosi_pad_o(mosi),.miso_pad_i(miso) ); +   // /////////////////////////////////////////////////////////////////////////     // I2C -- Slave #3     i2c_master_top #(.ARST_LVL(1))        i2c (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.arst_i(1'b0),  @@ -372,6 +381,7 @@ module u2_core     assign 	 s3_dat_i[31:8] = 24'd0; +   // /////////////////////////////////////////////////////////////////////////     // GPIOs -- Slave #4     nsgpio nsgpio(.clk_i(wb_clk),.rst_i(wb_rst),  		 .cyc_i(s4_cyc),.stb_i(s4_stb),.adr_i(s4_adr[3:0]),.we_i(s4_we), @@ -379,19 +389,24 @@ module u2_core  		 .atr(atr_lines),.debug_0(debug_gpio_0),.debug_1(debug_gpio_1),  		 .gpio( {io_tx,io_rx} ) ); -   // Buffer Pool Status -- Slave #5 +   // ///////////////////////////////////////////////////////////////////////// +   // Buffer Pool Status -- Slave #5    +    +   reg [31:0] 	 cycle_count; +   always @(posedge wb_clk) +     if(wb_rst) +       cycle_count <= 0; +     else +       cycle_count <= cycle_count + 1; +        wb_readback_mux buff_pool_status -     (.wb_clk_i(wb_clk), -      .wb_rst_i(wb_rst), -      .wb_stb_i(s5_stb), -      .wb_adr_i(s5_adr), -      .wb_dat_o(s5_dat_i), -      .wb_ack_o(s5_ack), +     (.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb), +      .wb_adr_i(s5_adr), .wb_dat_o(s5_dat_i), .wb_ack_o(s5_ack),        .word00(status_b0),.word01(status_b1),.word02(status_b2),.word03(status_b3),        .word04(status_b4),.word05(status_b5),.word06(status_b6),.word07(status_b7),        .word08(status),.word09({sim_mode,27'b0,clock_divider[3:0]}),.word10(32'b0), -      .word11(32'b0),.word12(32'b0),.word13(32'b0),.word14(32'b0),.word15(32'b0) +      .word11(32'b0),.word12(32'b0),.word13(irq),.word14(status_enc),.word15(cycle_count)        );     // ///////////////////////////////////////////////////////////////////////// @@ -457,13 +472,14 @@ module u2_core     // /////////////////////////////////////////////////////////////////////////     // Interrupt Controller, Slave #8 -   wire [15:0] 	 irq={{4'b0, clk_status, serdes_link_up, uart_tx_int, uart_rx_int}, -		      {pps_int,overrun,underrun,PHY_INTn,i2c_int,spi_int,timer_int,buffer_int}}; +   assign irq= {{8'b0}, +		{8'b0}, +		{4'b0, clk_status, serdes_link_up, uart_tx_int, uart_rx_int}, +		{pps_int,overrun,underrun,PHY_INTn,i2c_int,spi_int,timer_int,buffer_int}}; -   simple_pic #(.is(16),.dwidth(32)) simple_pic -     (.clk_i(wb_clk),.rst_i(wb_rst),.cyc_i(s8_cyc),.stb_i(s8_stb),.adr_i(s8_adr[3:2]), -      .we_i(s8_we),.dat_i(s8_dat_o),.dat_o(s8_dat_i),.ack_o(s8_ack),.int_o(proc_int), -      .irq(irq) ); +   pic pic(.clk_i(wb_clk),.rst_i(wb_rst),.cyc_i(s8_cyc),.stb_i(s8_stb),.adr_i(s8_adr[3:2]), +	   .we_i(s8_we),.dat_i(s8_dat_o),.dat_o(s8_dat_i),.ack_o(s8_ack),.int_o(proc_int), +	   .irq(irq) );     // /////////////////////////////////////////////////////////////////////////     // Master Timer, Slave #9 diff --git a/top/u2_rev3/Makefile b/top/u2_rev3/Makefile index 94681f6cd..4358d7c56 100644 --- a/top/u2_rev3/Makefile +++ b/top/u2_rev3/Makefile @@ -82,6 +82,8 @@ control_lib/sd_spi.v \  control_lib/sd_spi_wb.v \  control_lib/wb_bridge_16_32.v \  control_lib/reset_sync.v \ +control_lib/priority_enc.v \ +control_lib/pic.v \  simple_gemac/simple_gemac_wrapper.v \  simple_gemac/simple_gemac.v \  simple_gemac/simple_gemac_wb.v \ @@ -132,7 +134,6 @@ opencores/i2c/rtl/verilog/i2c_master_byte_ctrl.v \  opencores/i2c/rtl/verilog/i2c_master_defines.v \  opencores/i2c/rtl/verilog/i2c_master_top.v \  opencores/i2c/rtl/verilog/timescale.v \ -opencores/simple_pic/rtl/simple_pic.v \  opencores/spi/rtl/verilog/spi_clgen.v \  opencores/spi/rtl/verilog/spi_defines.v \  opencores/spi/rtl/verilog/spi_shift.v \ | 
