|  | @@ -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;
 |