aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--control_lib/pic.v183
-rw-r--r--control_lib/priority_enc.v44
-rwxr-xr-xtop/u2_core/u2_core.v44
-rw-r--r--top/u2_rev3/Makefile3
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 \