|
@@ -354,8 +354,45 @@ module max80 (
|
|
|
abc_mempg <= { abc_a[1:0], abc_di };
|
|
|
end // else: !if(~rst_n)
|
|
|
|
|
|
+ //
|
|
|
+ // Internal CPU bus
|
|
|
+ //
|
|
|
+ wire cpu_mem_valid;
|
|
|
+ wire cpu_mem_instr;
|
|
|
+ wire [ 3:0] cpu_mem_wstrb;
|
|
|
+ wire [31:0] cpu_mem_addr;
|
|
|
+ wire [31:0] cpu_mem_wdata;
|
|
|
+ reg [31:0] cpu_mem_rdata;
|
|
|
+ wire cpu_mem_ready;
|
|
|
+
|
|
|
+ wire cpu_mem_read = cpu_mem_valid & ~|cpu_mem_wstrb;
|
|
|
+
|
|
|
+ wire cpu_la_read;
|
|
|
+ wire cpu_la_write;
|
|
|
+ wire [31:0] cpu_la_addr;
|
|
|
+ wire [31:0] cpu_la_wdata;
|
|
|
+ wire [ 3:0] cpu_la_wstrb;
|
|
|
+
|
|
|
+ // 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)
|
|
|
+ wire [15:0] iodev = cpu_mem_quad[3] << cpu_mem_addr[9:6];
|
|
|
+
|
|
|
+ wire [31:0] sdram_rd;
|
|
|
+ wire sdram_rack;
|
|
|
+ wire sdram_rready;
|
|
|
+ wire sdram_wack;
|
|
|
+ reg sdram_acked;
|
|
|
+
|
|
|
+ always @(posedge sdram_clk)
|
|
|
+ sdram_acked <= cpu_mem_quad[1] & (sdram_acked | sdram_rack | sdram_wack);
|
|
|
+
|
|
|
+ wire sdram_req = cpu_mem_quad[1] & ~sdram_acked;
|
|
|
+
|
|
|
sdram sdram (
|
|
|
- .rst_n ( rst_n ),
|
|
|
+ .rst_n ( rst_n & ~iodev[12] ),
|
|
|
.clk ( sdram_clk ), // Input clock
|
|
|
|
|
|
.sr_clk ( sr_clk ), // Output clock buffer
|
|
@@ -378,14 +415,14 @@ module max80 (
|
|
|
.wrq0 ( abc_wrq ),
|
|
|
.wack0 ( abc_wack ),
|
|
|
|
|
|
- .a1 ( 24'hxxxxxx ),
|
|
|
- .rd1 ( ),
|
|
|
- .rrq1 ( 1'b0 ),
|
|
|
- .rack1 ( ),
|
|
|
- .rready1 ( ),
|
|
|
- .wd1 ( 32'hxxxx_xxxx ),
|
|
|
- .wstrb1 ( 4'b0000 ),
|
|
|
- .wack1 ( )
|
|
|
+ .a1 ( cpu_mem_addr[24:2] ),
|
|
|
+ .rd1 ( sdram_rd ),
|
|
|
+ .rrq1 ( sdram_req & ~|cpu_mem_wstrb ),
|
|
|
+ .rack1 ( sdram_rack ),
|
|
|
+ .rready1 ( sdram_rready ),
|
|
|
+ .wd1 ( cpu_mem_wdata ),
|
|
|
+ .wstrb1 ( {4{sdram_req}} & cpu_mem_wstrb ),
|
|
|
+ .wack1 ( sdram_wack )
|
|
|
);
|
|
|
|
|
|
// SD card
|
|
@@ -413,23 +450,6 @@ module max80 (
|
|
|
|
|
|
// Embedded RISC-V CPU
|
|
|
parameter cpu_fast_mem_bits = 11; /* 2^[this] * 4 bytes */
|
|
|
-
|
|
|
- wire cpu_mem_valid;
|
|
|
- wire cpu_mem_instr;
|
|
|
- wire [ 3:0] cpu_mem_wstrb;
|
|
|
- wire [31:0] cpu_mem_addr;
|
|
|
- wire [31:0] cpu_mem_wdata;
|
|
|
- reg [31:0] cpu_mem_rdata;
|
|
|
- wire cpu_mem_ready;
|
|
|
-
|
|
|
- wire cpu_mem_read = cpu_mem_valid & ~|cpu_mem_wstrb;
|
|
|
-
|
|
|
- wire cpu_la_read;
|
|
|
- wire cpu_la_write;
|
|
|
- wire [31:0] cpu_la_addr;
|
|
|
- wire [31:0] cpu_la_wdata;
|
|
|
- wire [ 3:0] cpu_la_wstrb;
|
|
|
-
|
|
|
picorv32 #(
|
|
|
.ENABLE_COUNTERS ( 1 ),
|
|
|
.ENABLE_COUNTERS64 ( 1 ),
|
|
@@ -473,11 +493,33 @@ module max80 (
|
|
|
.eoi ( )
|
|
|
);
|
|
|
|
|
|
- // cpu_mem_ready is always true for fast memory
|
|
|
- assign cpu_mem_ready = cpu_mem_valid;
|
|
|
+ // cpu_mem_ready is always true for fast memory; for SDRAM we have to
|
|
|
+ // wait either for a write ack or a low-high transition on the
|
|
|
+ // read ready signal.
|
|
|
+ reg sdram_rready_q;
|
|
|
+ reg sdram_mem_ready;
|
|
|
+ reg [31:0] sdram_rdata;
|
|
|
+ always @(posedge sys_clk)
|
|
|
+ begin
|
|
|
+ sdram_rready_q <= sdram_rready;
|
|
|
+ if (cpu_mem_quad[1])
|
|
|
+ sdram_mem_ready <= sdram_mem_ready | sdram_wack |
|
|
|
+ (sdram_rready & ~sdram_rready_q);
|
|
|
+ else
|
|
|
+ sdram_mem_ready <= 1'b0;
|
|
|
+
|
|
|
+ sdram_rdata <= sdram_rd;
|
|
|
+ end
|
|
|
|
|
|
- // Memory valid flag by quadrant
|
|
|
- wire [3:0] mem_quad = cpu_mem_valid << cpu_mem_addr[31:30];
|
|
|
+ always @(*)
|
|
|
+ case ( cpu_mem_quad )
|
|
|
+ 4'b0000: cpu_mem_ready = 1'b0;
|
|
|
+ 4'b0001: cpu_mem_ready = 1'b1;
|
|
|
+ 4'b0010: cpu_mem_ready = sdram_mem_ready;
|
|
|
+ 4'b0100: cpu_mem_ready = 1'b1;
|
|
|
+ 4'b1000: cpu_mem_ready = 1'b1;
|
|
|
+ default: cpu_mem_ready = 1'bx;
|
|
|
+ endcase // case ( mem_quad )
|
|
|
|
|
|
//
|
|
|
// Fast memory. This runs on the SDRAM clock, i.e. 2x the speed
|
|
@@ -498,15 +540,14 @@ module max80 (
|
|
|
.rdata ( fast_mem_rdata )
|
|
|
);
|
|
|
|
|
|
+ // Input data MUX
|
|
|
always @(*)
|
|
|
- case (cpu_mem_addr[31:30])
|
|
|
- 2'b00: cpu_mem_rdata = fast_mem_rdata;
|
|
|
+ case ( cpu_mem_quad )
|
|
|
+ 4'b0001: cpu_mem_rdata = fast_mem_rdata;
|
|
|
+ 4'b0010: cpu_mem_rdata = sdram_rdata;
|
|
|
+ 4'b1000: cpu_mem_rdata = 32'hffff_ffff;
|
|
|
default: cpu_mem_rdata = 32'hxxxx_xxxx;
|
|
|
- endcase // case (cpu_mem_addr[31:30])
|
|
|
-
|
|
|
- // Decode for small devices; use address space within range of
|
|
|
- // negative offsets from the zero register [-1K,0)
|
|
|
- wire [15:0] iodev = mem_quad[3] << cpu_mem_addr[9:6];
|
|
|
+ endcase
|
|
|
|
|
|
// LED indication from the CPU
|
|
|
reg [2:0] led_q;
|