|
@@ -479,6 +479,35 @@ module max80 (
|
|
|
|
|
|
// Embedded RISC-V CPU
|
|
|
parameter cpu_fast_mem_bits = 13; /* 2^[this] * 4 bytes */
|
|
|
+
|
|
|
+ // Edge-triggered system IRQs not necessarily associated
|
|
|
+ // with a specific I/O device. picorv32 latches interrupts
|
|
|
+ // but doesn't edge detect for a slow signal, so do it
|
|
|
+ // here instead and use level triggered signalling to the
|
|
|
+ // CPU.
|
|
|
+ wire [31:0] cpu_eoi;
|
|
|
+ reg [31:0] cpu_eoi_q;
|
|
|
+
|
|
|
+ tri0 [15:3] sys_irq;
|
|
|
+ reg [15:3] sys_irq_q;
|
|
|
+ reg [15:3] sys_irq_pending;
|
|
|
+
|
|
|
+ always @(negedge rst_n or posedge sys_clk)
|
|
|
+ if (~rst_n)
|
|
|
+ begin
|
|
|
+ sys_irq_q <= 1'b0;
|
|
|
+ cpu_eoi_q <= 1'b0;
|
|
|
+ sys_irq_pending <= 13'b0;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ sys_irq_q <= sys_irq;
|
|
|
+ cpu_eoi_q <= cpu_eoi;
|
|
|
+
|
|
|
+ sys_irq_pending <= (sys_irq & ~sys_irq_q)
|
|
|
+ | (sys_irq_pending & ~(cpu_eoi[15:3] & ~cpu_eoi_q[15:3]));
|
|
|
+ end
|
|
|
+
|
|
|
picorv32 #(
|
|
|
.ENABLE_COUNTERS ( 1 ),
|
|
|
.ENABLE_COUNTERS64 ( 1 ),
|
|
@@ -496,8 +525,7 @@ module max80 (
|
|
|
.ENABLE_IRQ ( 1 ),
|
|
|
.ENABLE_IRQ_QREGS ( 1 ),
|
|
|
.ENABLE_IRQ_TIMER ( 1 ),
|
|
|
- .LATCHED_IRQ ( 32'h0000_0007 ), // Device IRQs are level
|
|
|
- .MASKED_IRQ ( 32'h0000_fff8 ), // Unused IRQs for now
|
|
|
+ .LATCHED_IRQ ( 32'h0000_0007 ),
|
|
|
.PROGADDR_RESET ( 32'h0000_0000 ),
|
|
|
.PROGADDR_IRQ ( 32'h0000_0020 ),
|
|
|
.REGS_INIT_ZERO ( 1 ),
|
|
@@ -523,8 +551,8 @@ module max80 (
|
|
|
.mem_la_addr ( cpu_la_addr ),
|
|
|
.mem_la_wstrb ( cpu_la_wstrb ),
|
|
|
|
|
|
- .irq ( { iodev_irq, 16'b0 } ),
|
|
|
- .eoi ( )
|
|
|
+ .irq ( { iodev_irq, sys_irq_pending, 3'b000 } ),
|
|
|
+ .eoi ( cpu_eoi )
|
|
|
);
|
|
|
|
|
|
// cpu_mem_ready is always true for fast memory; for SDRAM we have to
|
|
@@ -708,18 +736,40 @@ module max80 (
|
|
|
assign sd_dat[2:1] = 2'bzz;
|
|
|
|
|
|
// System local clock (not an RTC, but settable from one)
|
|
|
+ // Also provides a periodic interrupt (set to 32 Hz)
|
|
|
wire [31:0] sysclock_rdata;
|
|
|
|
|
|
- sysclock sysclock (
|
|
|
+ // XXX: the RTC 32 kHz signal is missing a pull-up,
|
|
|
+ // so it will require board rework. For now, use an
|
|
|
+ // divider down from the 84 MHz system clock. The
|
|
|
+ // error is about 200 ppm; a proper NCO could do better.
|
|
|
+
|
|
|
+ reg [10:0] ctr_64khz;
|
|
|
+ reg ctr_32khz;
|
|
|
+ always @(posedge sys_clk)
|
|
|
+ begin
|
|
|
+ if (~|ctr_64khz)
|
|
|
+ begin
|
|
|
+ ctr_32khz <= ~ctr_32khz;
|
|
|
+ ctr_64khz <= 11'd1280;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ ctr_64khz <= ctr_64khz - 1'b1;
|
|
|
+ end
|
|
|
+
|
|
|
+ sysclock #(.PERIODIC_HZ_LG2 ( 5 ))
|
|
|
+ sysclock (
|
|
|
.rst_n ( rst_n ),
|
|
|
.sys_clk ( sys_clk ),
|
|
|
- .rtc_clk ( rtc_32khz ),
|
|
|
+ .rtc_clk ( ctr_32khz ),
|
|
|
|
|
|
.wdata ( cpu_mem_wdata ),
|
|
|
.rdata ( sysclock_rdata ),
|
|
|
.valid ( iodev[5] ),
|
|
|
.wstrb ( cpu_mem_wstrb ),
|
|
|
- .addr ( cpu_mem_addr[2] )
|
|
|
+ .addr ( cpu_mem_addr[2] ),
|
|
|
+
|
|
|
+ .periodic ( sys_irq[3] )
|
|
|
);
|
|
|
//
|
|
|
// I/O device input data MUX
|