|
@@ -383,23 +383,10 @@ module max80 (
|
|
|
// cpu_mem_valid by address quadrant
|
|
|
wire [ 3:0] cpu_mem_quad = cpu_mem_valid << cpu_mem_addr[31:30];
|
|
|
|
|
|
- // Decode for small devices; use address space within range of
|
|
|
- // negative offsets from the zero register [-1K,0)
|
|
|
- //
|
|
|
- // Device map:
|
|
|
- // 0 - LED
|
|
|
- // 1 - Reset
|
|
|
- // 2 - SPI->SDRAM downloader
|
|
|
- // 3 - Serial port
|
|
|
- // 4 - SD card
|
|
|
- // 5 - system local clock (not RTC)
|
|
|
- //
|
|
|
- // A device has IRQ (devno)+16 if it needs an interrupt.
|
|
|
- //
|
|
|
-
|
|
|
- wire [15:0] iodev = cpu_mem_quad[3] << cpu_mem_addr[10:7];
|
|
|
- tri0 [15:0] iodev_irq; // tri0: if nothing is driving, value is 0
|
|
|
-
|
|
|
+ // I/O device map from iodevs.conf
|
|
|
+ wire iodev_mem_valid = cpu_mem_quad[3];
|
|
|
+`include "iodevs.vh"
|
|
|
+
|
|
|
//
|
|
|
// SDRAM
|
|
|
//
|
|
@@ -480,32 +467,31 @@ 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
|
|
|
+ // Edge-triggered IRQs. 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;
|
|
|
+ // sys_irq defined in iodevs.vh
|
|
|
+ reg [31:0] sys_irq_q;
|
|
|
+ reg [31:0] cpu_irq;
|
|
|
|
|
|
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;
|
|
|
+ sys_irq_q <= 32'b0;
|
|
|
+ cpu_eoi_q <= 32'b0;
|
|
|
+ cpu_irq <= 32'b0;
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
- sys_irq_q <= sys_irq;
|
|
|
- cpu_eoi_q <= cpu_eoi;
|
|
|
+ sys_irq_q <= sys_irq & irq_edge_mask;
|
|
|
+ cpu_eoi_q <= cpu_eoi & irq_edge_mask;
|
|
|
|
|
|
- sys_irq_pending <= (sys_irq & ~sys_irq_q)
|
|
|
- | (sys_irq_pending & ~(cpu_eoi[15:3] & ~cpu_eoi_q[15:3]));
|
|
|
+ cpu_irq <= (sys_irq & ~sys_irq_q)
|
|
|
+ | (cpu_irq & irq_edge_mask & ~(cpu_eoi & ~cpu_eoi_q));
|
|
|
end
|
|
|
|
|
|
picorv32 #(
|
|
@@ -525,6 +511,7 @@ module max80 (
|
|
|
.ENABLE_IRQ ( 1 ),
|
|
|
.ENABLE_IRQ_QREGS ( 1 ),
|
|
|
.ENABLE_IRQ_TIMER ( 1 ),
|
|
|
+ .MASKED_IRQ ( irq_masked ),
|
|
|
.LATCHED_IRQ ( 32'h0000_0007 ),
|
|
|
.REGS_INIT_ZERO ( 1 ),
|
|
|
.STACKADDR ( 32'h4 << cpu_fast_mem_bits )
|
|
@@ -552,7 +539,7 @@ module max80 (
|
|
|
.mem_la_addr ( cpu_la_addr ),
|
|
|
.mem_la_wstrb ( cpu_la_wstrb ),
|
|
|
|
|
|
- .irq ( { iodev_irq, sys_irq_pending, 3'b000 } ),
|
|
|
+ .irq ( cpu_irq ),
|
|
|
.eoi ( cpu_eoi )
|
|
|
);
|
|
|
|
|
@@ -577,7 +564,6 @@ module max80 (
|
|
|
// Add a mandatory wait state to iodevs to reduce the size
|
|
|
// of the CPU memory input MUX (it hurts timing on memory
|
|
|
// accesses...)
|
|
|
- tri1 [15:0] iodev_wait_n;
|
|
|
reg iodev_mem_ready;
|
|
|
|
|
|
always @(*)
|
|
@@ -609,20 +595,20 @@ module max80 (
|
|
|
.rdata ( fast_mem_rdata )
|
|
|
);
|
|
|
|
|
|
-
|
|
|
- // Input data MUX
|
|
|
- wire [31:0] iodev_rdata;
|
|
|
-
|
|
|
+ // Register I/O data to reduce the size of the read data MUX
|
|
|
+ reg [31:0] iodev_rdata_q;
|
|
|
+
|
|
|
+ // Read data MUX
|
|
|
always @(*)
|
|
|
case ( cpu_mem_quad )
|
|
|
4'b0001: cpu_mem_rdata = fast_mem_rdata;
|
|
|
4'b0010: cpu_mem_rdata = sdram_rdata;
|
|
|
- 4'b1000: cpu_mem_rdata = iodev_rdata;
|
|
|
+ 4'b1000: cpu_mem_rdata = iodev_rdata_q;
|
|
|
default: cpu_mem_rdata = 32'hxxxx_xxxx;
|
|
|
endcase
|
|
|
|
|
|
// Hard system reset under program control
|
|
|
- assign reset_cmd = rst_n & iodev[1] & cpu_mem_wstrb[0] & cpu_mem_wdata[0];
|
|
|
+ assign reset_cmd = iodev_valid_reset & cpu_mem_wstrb[0] & cpu_mem_wdata[0];
|
|
|
|
|
|
// LED indication from the CPU
|
|
|
reg [2:0] led_q;
|
|
@@ -630,10 +616,11 @@ module max80 (
|
|
|
if (~rst_n)
|
|
|
led_q <= 3'b000;
|
|
|
else
|
|
|
- if ( iodev[0] & cpu_mem_wstrb[0] )
|
|
|
+ if ( iodev_valid_led & cpu_mem_wstrb[0] )
|
|
|
led_q <= cpu_mem_wdata[2:0];
|
|
|
|
|
|
assign led = led_q;
|
|
|
+ assign iodev_rdata_led = { 29'b0, led_q };
|
|
|
|
|
|
//
|
|
|
// Serial ROM (also configuration ROM.) Fast hardwired data download
|
|
@@ -661,6 +648,8 @@ module max80 (
|
|
|
always @(posedge sys_clk)
|
|
|
rom_done_q <= rom_done;
|
|
|
|
|
|
+ assign iodev_rdata_romcopy = { 31'b0, rom_done_q };
|
|
|
+
|
|
|
//
|
|
|
// Serial port. Direct to the CP2102N for reworked
|
|
|
// boards or to GPIO for non-reworked boards, depending on
|
|
@@ -677,19 +666,18 @@ module max80 (
|
|
|
wire tty_data_in; // Input data
|
|
|
wire tty_cts_out; // Assert CTS# externally
|
|
|
wire tty_rts_in; // RTS# received from outside
|
|
|
- wire [31:0] tty_rdata;
|
|
|
|
|
|
assign tty_cts_out = 1'b0; // Assert CTS#
|
|
|
- tty tty (
|
|
|
+ tty console (
|
|
|
.rst_n ( rst_n ),
|
|
|
- .clk ( sys_clk ),
|
|
|
+ .clk ( sys_clk ),
|
|
|
|
|
|
- .valid ( iodev[3] ),
|
|
|
+ .valid ( iodev_valid_console ),
|
|
|
.wstrb ( cpu_mem_wstrb ),
|
|
|
.wdata ( cpu_mem_wdata ),
|
|
|
- .rdata ( tty_rdata ),
|
|
|
- .addr ( cpu_mem_addr[3:2] ),
|
|
|
- .irq ( iodev_irq[3] ),
|
|
|
+ .rdata ( iodev_rdata_console ),
|
|
|
+ .addr ( cpu_mem_addr[3:2] ),
|
|
|
+ .irq ( iodev_irq_console ),
|
|
|
|
|
|
.tty_txd ( tty_data_out ) // DTE -> DCE
|
|
|
);
|
|
@@ -720,8 +708,6 @@ module max80 (
|
|
|
|
|
|
|
|
|
// SD card
|
|
|
- wire [31:0] sdcard_rdata;
|
|
|
-
|
|
|
sdcard sdcard (
|
|
|
.rst_n ( rst_n ),
|
|
|
.clk ( sys_clk ),
|
|
@@ -732,18 +718,16 @@ module max80 (
|
|
|
.sd_cd_n ( 1'b0 ),
|
|
|
|
|
|
.wdata ( cpu_mem_wdata ),
|
|
|
- .rdata ( sdcard_rdata ),
|
|
|
- .valid ( iodev[4] ),
|
|
|
+ .rdata ( iodev_rdata_sdcard ),
|
|
|
+ .valid ( iodev_valid_sdcard ),
|
|
|
.wstrb ( cpu_mem_wstrb ),
|
|
|
.addr ( cpu_mem_addr[6:2] ),
|
|
|
- .wait_n ( iodev_wait_n[4] )
|
|
|
+ .wait_n ( iodev_wait_n_sdcard )
|
|
|
);
|
|
|
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;
|
|
|
-
|
|
|
// 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
|
|
@@ -769,32 +753,24 @@ module max80 (
|
|
|
.rtc_clk ( ctr_32khz ),
|
|
|
|
|
|
.wdata ( cpu_mem_wdata ),
|
|
|
- .rdata ( sysclock_rdata ),
|
|
|
- .valid ( iodev[5] ),
|
|
|
+ .rdata ( iodev_rdata_sysclock ),
|
|
|
+ .valid ( iodev_valid_sysclock ),
|
|
|
.wstrb ( cpu_mem_wstrb ),
|
|
|
.addr ( cpu_mem_addr[2] ),
|
|
|
|
|
|
- .periodic ( sys_irq[3] )
|
|
|
+ .periodic ( iodev_irq_sysclock )
|
|
|
);
|
|
|
+
|
|
|
//
|
|
|
- // I/O device input data (registered to reduce MUX overhead for
|
|
|
- // the critical memory data paths.)
|
|
|
- // abo
|
|
|
+ // Registering of I/O data and handling of iodev_mem_ready
|
|
|
//
|
|
|
always @(posedge sys_clk)
|
|
|
- case ( cpu_mem_addr[10:7] )
|
|
|
- 4'd0: iodev_rdata <= { 29'b0, led_q };
|
|
|
- 4'd2: iodev_rdata <= { 31'b0, rom_done_q };
|
|
|
- 4'd3: iodev_rdata <= tty_rdata;
|
|
|
- 4'd4: iodev_rdata <= sdcard_rdata;
|
|
|
- 4'd5: iodev_rdata <= sysclock_rdata;
|
|
|
- default: iodev_rdata <= 32'h0;
|
|
|
- endcase
|
|
|
+ iodev_rdata_q <= iodev_rdata;
|
|
|
|
|
|
always @(negedge rst_n or posedge sys_clk)
|
|
|
if (~rst_n)
|
|
|
iodev_mem_ready <= 1'b0;
|
|
|
else
|
|
|
- iodev_mem_ready <= &iodev_wait_n & cpu_mem_valid;
|
|
|
+ iodev_mem_ready <= iodev_wait_n & cpu_mem_valid;
|
|
|
|
|
|
endmodule
|