Browse Source

Enable up to 8 ABC memory maps; additional romhack control registers

Enabled up to eight ABC memory maps (Smartaid Magnum requires four);
implement some of the infrastructure for multiple maps in memory
initialization.
H. Peter Anvin 1 year ago
parent
commit
9005376e47

BIN
esp32/output/max80.ino.bin


+ 72 - 45
fpga/abcbus.sv

@@ -297,7 +297,7 @@ module abcbus (
    //
    // Accesses from RV32 supports 32-bit accesses only!
    //
-   logic       abc_a_map;
+   logic [2:0] abc_a_map;
    wire [17:0] rdata_abcmemmap;		// RV32 access port
    wire [17:0] abc_memmap_rd;		// ABC-bus access port
 
@@ -312,7 +312,7 @@ module abcbus (
     .wren_a    ( 1'b0 ),
     .q_a       ( abc_memmap_rd ),
 
-    .address_b ( cpu_addr[8:2] ),
+    .address_b ( cpu_addr[10:2] ),
     .data_b    ( { cpu_wdata[2:0], cpu_wdata[24:10] } ),
     .wren_b    ( map_valid & cpu_wstrb[0] ),
 
@@ -468,18 +468,35 @@ module abcbus (
    //
    // "ROM hack" map control logic
    //
-   reg	     romhack_en    = 1'b0;     // Enable
-   reg [5:0] romhack_addr  = 6'b0;     // Address mask (1K granular)
-   reg	     romhack_map   = 1'b0;     // Current map
-   wire	     cpu_romhackmap = rst_n && abc_valid && cpu_addr[6:2] == 5'b01011;
+   localparam romhack_regs  = 2;
+   localparam romhack_rmax  = romhack_regs - 1;
+   reg [2:0]  romhack_mask [0:romhack_rmax];
+   reg [5:0]  romhack_addr [0:romhack_rmax];
+   reg [2:0]  romhack_map   = 3'b0;     // Current map
+   wire	      cpu_romhackmap = rst_n && abc_valid && cpu_addr[6:2] == 5'd11;
+
+   // The control registers are handled elsewhere
+   always @(negedge rst_n or posedge sdram_clk)
+     if (~rst_n)
+       begin
+	  romhack_map <= 3'b000;
+       end
+     else
+       begin
+	  logic [2:0] new_map;
 
-   always @(posedge sdram_clk)
-     begin
-	if (abc_xmemwr & romhack_en & (abc_a_s[15:10] == romhack_addr))
-	  romhack_map <= abc_a_s[0];
-	else if (cpu_romhackmap & cpu_wstrb[0])
-	  romhack_map <= cpu_wdata[0];
-     end
+	  new_map = romhack_map;
+	  if (cpu_romhackmap & cpu_wstrb[0])
+	    new_map = cpu_wdata[2:0];
+
+	  for (int i = 0; i < romhack_regs; i++)
+	    begin
+	       if (abc_xmemwr && abc_a_s[15:0] == romhack_addr[i])
+		 new_map = (new_map & ~romhack_map[i]) | (abc_a_s[2:0] & romhack_map[i]);
+	    end
+
+	  romhack_map <= new_map;
+       end // else: !if(~rst_n)
 
    //
    // ABC data out (= ABC host read) logic
@@ -529,11 +546,8 @@ module abcbus (
    //
    always_comb
      begin
-	abc_a_map = 1'b0;
-	if (abc800mac_en)
-	  abc_a_map |= abc800mac_xmmask[abc_a_s[15:12]];
-	if (romhack_en)
-	  abc_a_map |= romhack_map;
+	abc_a_map = romhack_map;
+	abc_a_map[0] ^= abc800mac_en & abc800mac_xmmask[abc_a_s[15:12]];
      end
 
    // Memory read latency counter
@@ -588,10 +602,12 @@ module abcbus (
 	  bus_change_status <= 4'b0;
 	  bus_change_mask   <= 4'b0;
 	  abc800mac_en      <= 1'b0;
-	  romhack_en        <= 1'b0;
 	  abc80_force       <= 1'b0;
 	  abc800_force      <= 1'b0;
 
+	  for (int i = 0; i < romhack_regs; i++)
+	    romhack_mask[i] <= 3'b0;
+
 	  // abc_resin, nmi, int and force_wait are deliberately not affected
 	  // by an internal CPU reset. They are, however, inherently asserted
 	  // when the FPGA is configured, and initialized to fixed values
@@ -644,23 +660,28 @@ module abcbus (
 		       reg_inp_data[1] <= cpu_wdata[15:8];
 		     if (cpu_wstrb[2])
 		       inp_en <= cpu_wdata[17:16];
-		   end
+		 end
 		 5'b01000: begin
 		    if (cpu_wstrb[0])
 		      abc800mac_iobase <= cpu_wdata[7:1];
 		    if (cpu_wstrb[3])
 		      abc800mac_en <= cpu_wdata[31];
-		   end
+		 end
 		   // 5'b01001: abc800mac_xmdata - handled elsewhere
-		 5'b01010: begin
-		    if (cpu_wstrb[1])
-		      romhack_addr <= cpu_wdata[15:10];
-		    if (cpu_wstrb[3])
-		      romhack_en <= cpu_wdata[31];
-		   end
 		   // 5'b01011: romhack_map - handled elsewhere
-		 default:
-		   /* do nothing */ ;
+		 5'b10???: begin
+		    for (int i = 0; i < romhack_regs; i++)
+		      if (i == cpu_addr[4:2])
+			begin
+			   if (cpu_wstrb[0])
+			     romhack_mask[i] <= cpu_wdata[2:0];
+			   if (cpu_wstrb[1])
+			     romhack_addr[i] <= cpu_wdata[15:10];
+			end
+		 end
+		 default: begin
+		   /* do nothing */
+		 end
 	       endcase // casez (cpu_addr[6:2])
 	    end // if (abc_valid & cpu_wstrb[0])
        end
@@ -671,21 +692,27 @@ module abcbus (
 
    // Read MUX
    always_comb
-     casez (cpu_addr[6:2])
-       5'b00000: cpu_rdata = { 22'b0, abc800_force, abc80_force,
-			       4'b0, abc_status[0] };
-       5'b00001: cpu_rdata = { 23'b0, ~iosel_en, ioselx[7:0] };
-       5'b00010: cpu_rdata = { bus_change_mask, 2'b0, busy_mask,
-			       bus_change_status, 2'b0, busy_status };
-       5'b00011: cpu_rdata = { 28'b0, abc_resin, abc_nmi, abc_int, abc_wait };
-       5'b00100: cpu_rdata = { 21'b0, reg_out_addr, reg_out_data };
-       5'b00101: cpu_rdata = { 14'b0, inp_en, reg_inp_data[1], reg_inp_data[0] };
-       5'b00111: cpu_rdata = { 23'b0, memrd_latency_err, memrd_latency_max };
-       5'b01000: cpu_rdata = { abc800mac_en, 23'b0, abc800mac_iobase, 1'b0 };
-       5'b01001: cpu_rdata = { 16'b0, abc800mac_xmmask };
-       5'b01010: cpu_rdata = { romhack_en, 15'b0, romhack_addr, 10'b0 };
-       5'b01011: cpu_rdata = { 31'b0, romhack_map };
-       default:  cpu_rdata = 32'bx;
-     endcase // casez (cpu_addr[6:2])
+     begin
+	cpu_rdata = 32'b0;
+	casez (cpu_addr[6:2])
+	  5'b00000: cpu_rdata = { 22'b0, abc800_force, abc80_force,
+				  4'b0, abc_status[0] };
+	  5'b00001: cpu_rdata = { 23'b0, ~iosel_en, ioselx[7:0] };
+	  5'b00010: cpu_rdata = { bus_change_mask, 2'b0, busy_mask,
+				  bus_change_status, 2'b0, busy_status };
+	  5'b00011: cpu_rdata = { 28'b0, abc_resin, abc_nmi, abc_int, abc_wait };
+	  5'b00100: cpu_rdata = { 21'b0, reg_out_addr, reg_out_data };
+	  5'b00101: cpu_rdata = { 14'b0, inp_en, reg_inp_data[1], reg_inp_data[0] };
+	  5'b00111: cpu_rdata = { 23'b0, memrd_latency_err, memrd_latency_max };
+	  5'b01000: cpu_rdata = { abc800mac_en, 23'b0, abc800mac_iobase, 1'b0 };
+	  5'b01001: cpu_rdata = { 16'b0, abc800mac_xmmask };
+	  5'b01011: cpu_rdata = { 31'b0, romhack_map };
+	  5'b10???: begin
+	     for (int i = 0; i < romhack_regs; i++)
+	       if (i == cpu_addr[4:2])
+		 cpu_rdata = { 16'b0, romhack_addr[i], 7'b0, romhack_mask[i] };
+	  end
+	endcase // casez (cpu_addr[6:2])
+     end
 
 endmodule // abcbus

+ 1 - 1
fpga/ip/abcmapram.qip

@@ -1,5 +1,5 @@
 set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
-set_global_assignment -name IP_TOOL_VERSION "20.1"
+set_global_assignment -name IP_TOOL_VERSION "22.1"
 set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}"
 set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "abcmapram.v"]
 set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "abcmapram_inst.v"]

+ 17 - 17
fpga/ip/abcmapram.v

@@ -14,11 +14,11 @@
 // ************************************************************
 // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
 //
-// 20.1.1 Build 720 11/11/2020 SJ Lite Edition
+// 22.1std.2 Build 922 07/20/2023 SC Lite Edition
 // ************************************************************
 
 
-//Copyright (C) 2020  Intel Corporation. All rights reserved.
+//Copyright (C) 2023  Intel Corporation. All rights reserved.
 //Your use of Intel Corporation's design tools, logic functions 
 //and other software and tools, and any partner logic 
 //functions, and any output files from any of the foregoing 
@@ -50,8 +50,8 @@ module abcmapram (
 	q_b);
 
 	input	  aclr;
-	input	[6:0]  address_a;
-	input	[6:0]  address_b;
+	input	[8:0]  address_a;
+	input	[8:0]  address_b;
 	input	  clock;
 	input	[17:0]  data_a;
 	input	[17:0]  data_b;
@@ -108,8 +108,8 @@ module abcmapram (
 		altsyncram_component.indata_reg_b = "CLOCK0",
 		altsyncram_component.intended_device_family = "Cyclone IV E",
 		altsyncram_component.lpm_type = "altsyncram",
-		altsyncram_component.numwords_a = 128,
-		altsyncram_component.numwords_b = 128,
+		altsyncram_component.numwords_a = 512,
+		altsyncram_component.numwords_b = 512,
 		altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
 		altsyncram_component.outdata_aclr_a = "CLEAR0",
 		altsyncram_component.outdata_aclr_b = "CLEAR0",
@@ -119,8 +119,8 @@ module abcmapram (
 		altsyncram_component.read_during_write_mode_mixed_ports = "OLD_DATA",
 		altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
 		altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
-		altsyncram_component.widthad_a = 7,
-		altsyncram_component.widthad_b = 7,
+		altsyncram_component.widthad_a = 9,
+		altsyncram_component.widthad_b = 9,
 		altsyncram_component.width_a = 18,
 		altsyncram_component.width_b = 18,
 		altsyncram_component.width_byteena_a = 1,
@@ -163,7 +163,7 @@ endmodule
 // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
 // Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
 // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-// Retrieval info: PRIVATE: MEMSIZE NUMERIC "2304"
+// Retrieval info: PRIVATE: MEMSIZE NUMERIC "9216"
 // Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
 // Retrieval info: PRIVATE: MIFfilename STRING ""
 // Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3"
@@ -201,8 +201,8 @@ endmodule
 // Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK0"
 // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
 // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "128"
-// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "128"
+// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "512"
+// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "512"
 // Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT"
 // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "CLEAR0"
 // Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "CLEAR0"
@@ -212,16 +212,16 @@ endmodule
 // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "OLD_DATA"
 // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "OLD_DATA"
 // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "OLD_DATA"
-// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "7"
-// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "7"
+// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9"
+// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "9"
 // Retrieval info: CONSTANT: WIDTH_A NUMERIC "18"
 // Retrieval info: CONSTANT: WIDTH_B NUMERIC "18"
 // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
 // Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1"
 // Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK0"
 // Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND "aclr"
-// Retrieval info: USED_PORT: address_a 0 0 7 0 INPUT NODEFVAL "address_a[6..0]"
-// Retrieval info: USED_PORT: address_b 0 0 7 0 INPUT NODEFVAL "address_b[6..0]"
+// Retrieval info: USED_PORT: address_a 0 0 9 0 INPUT NODEFVAL "address_a[8..0]"
+// Retrieval info: USED_PORT: address_b 0 0 9 0 INPUT NODEFVAL "address_b[8..0]"
 // Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
 // Retrieval info: USED_PORT: data_a 0 0 18 0 INPUT NODEFVAL "data_a[17..0]"
 // Retrieval info: USED_PORT: data_b 0 0 18 0 INPUT NODEFVAL "data_b[17..0]"
@@ -230,8 +230,8 @@ endmodule
 // Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a"
 // Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b"
 // Retrieval info: CONNECT: @aclr0 0 0 0 0 aclr 0 0 0 0
-// Retrieval info: CONNECT: @address_a 0 0 7 0 address_a 0 0 7 0
-// Retrieval info: CONNECT: @address_b 0 0 7 0 address_b 0 0 7 0
+// Retrieval info: CONNECT: @address_a 0 0 9 0 address_a 0 0 9 0
+// Retrieval info: CONNECT: @address_b 0 0 9 0 address_b 0 0 9 0
 // Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
 // Retrieval info: CONNECT: @data_a 0 0 18 0 data_a 0 0 18 0
 // Retrieval info: CONNECT: @data_b 0 0 18 0 data_b 0 0 18 0

+ 3 - 3
fpga/max80.qpf

@@ -19,15 +19,15 @@
 #
 # Quartus Prime
 # Version 22.1std.2 Build 922 07/20/2023 SC Lite Edition
-# Date created = 21:58:24  November 08, 2023
+# Date created = 06:53:40  November 13, 2023
 #
 # -------------------------------------------------------------------------- #
 
 QUARTUS_VERSION = "22.1"
-DATE = "21:58:24  November 08, 2023"
+DATE = "06:53:40  November 13, 2023"
 
 # Revisions
 
-PROJECT_REVISION = "v1"
 PROJECT_REVISION = "v2"
+PROJECT_REVISION = "v1"
 PROJECT_REVISION = "bypass"

BIN
fpga/output/bypass.jic


BIN
fpga/output/max80.fw


BIN
fpga/output/v1.fw


BIN
fpga/output/v1.jic


BIN
fpga/output/v1.sof


BIN
fpga/output/v2.fw


BIN
fpga/output/v2.jic


BIN
fpga/output/v2.sof


+ 34 - 14
rv32/abcmem.c

@@ -39,6 +39,9 @@ struct abc_mem_init {
 /* Not really NV, but matches NVRAM in some expansions */
 static char __dram_bss __aligned(PAGE_SIZE) abc80_nvram[2][2*K];
 
+/* ABC800MAC RAM */
+static char __dram_bss __aligned(PAGE_SIZE) abc800mac_ram[64*K];
+
 /* 16K external memory to expand to 512K */
 static char __dram_bss __aligned(PAGE_SIZE) abc80_extmem[16*K];
 
@@ -82,6 +85,10 @@ static const struct abc_mem_init mem_init_abc800[] = {
     { 24*K, RD,    config_abc_mem_abc800_ufddos,    R(rom_abc800_ufddos) },
     END
 };
+static const struct abc_mem_init mem_init_abc800mac[] = {
+    { 0,    RD|WR, 0,                               R(abc800mac_ram) },
+    END
+};
 
 static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
 {
@@ -123,10 +130,32 @@ static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
     }
 }
 
+static void abc_init_memmap800(uint32_t memmap[MAPS][PERMAP])
+{
+    abc_map_list(memmap[0], mem_init_abc800);
+    abc_map_list(memmap[1], mem_init_abc800mac);
+
+    /* XXX: enable abc800mac if desired */
+}
+
+static void abc_init_memmap80(uint32_t memmap[MAPS][PERMAP])
+{
+    /* Put 22K first so UFD-DOS/PUN80 memory always is put at the end */
+    if (getvar_bool(config_abc_mem_abc80_nvram_22k))
+	abc_map_list(memmap[0], mem_init_abc80_nvram_22k);
+    else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
+	abc_map_list(memmap[0], mem_init_abc80_nvram_20k);
+    else
+	abc_map_list(memmap[0], mem_init_abc80_no_nvram);
+
+    abc_map_list(memmap[0], mem_init_abc80);
+
+    /* XXX: enable romhack if needed */
+}
+
 void __cold abc_init_memmap(void)
 {
     static uint32_t memmap[MAPS][PERMAP]; /* Too big to fit on stack */
-    const struct abc_mem_init *mem;
 
     memset(memmap, 0, sizeof memmap);
 
@@ -135,19 +164,10 @@ void __cold abc_init_memmap(void)
      * remaining map(s) get cleared by the memset() above.
      */
 
-    if (is_abc800()) {
-	abc_map_list(memmap[0], mem_init_abc800);
-    } else {
-	/* Put 22K first so UFD-DOS/PUN80 memory always is put at the end */
-	if (getvar_bool(config_abc_mem_abc80_nvram_22k))
-	    abc_map_list(memmap[0], mem_init_abc80_nvram_22k);
-	else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
-	    abc_map_list(memmap[0], mem_init_abc80_nvram_20k);
-	else
-	    abc_map_list(memmap[0], mem_init_abc80_no_nvram);
-
-	abc_map_list(memmap[0], mem_init_abc80);
-    }
+    if (is_abc800())
+	abc_init_memmap800(memmap);
+    else
+	abc_init_memmap80(memmap);
 
     /* Install memory map into hardware registers */
     memcpy((void *)&ABCMEMMAP_PAGE(0), memmap, sizeof memmap);

+ 1 - 1
rv32/checksum.h

@@ -1,4 +1,4 @@
 #ifndef CHECKSUM_H
 #define CHECKSUM_H
-#define SDRAM_SUM 0x3fd7e92f
+#define SDRAM_SUM 0x94ce79b9
 #endif

+ 3 - 3
rv32/ioregs.h

@@ -134,13 +134,13 @@
 #define ABC_LATENCY_ERR		IODEVRB1(ABC,7)
 #define ABC_MAP_MAC800_CFG	IODEVL(ABC,8)
 #define ABC_MAP_MAC800_MAPS	IODEVL(ABC,9)
-#define ABC_MAP_ROMHACK_CFG	IODEVL(ABC,10)
 #define ABC_MAP_ROMHACK_MAP	IODEVL(ABC,11)
+#define ABC_MAP_ROMHACK_CFG	IODEVL(ABC,16) /* Multiple registers */
 
-/* n = 0 ... 127 for one of two 64x1K maps */
+/* n = 0 ... 511 for one of 8 64x1K maps */
 #define ABCMEMMAP_PAGE(n)	IODEVL(ABCMEMMAP,n)
 
-#define ABCMEMMAP_MAPS		2
+#define ABCMEMMAP_MAPS		8
 #define ABCMEMMAP_PAGE_SHIFT	10
 #define ABCMEMMAP_PAGE_SIZE	(1 << ABCMEMMAP_PAGE_SHIFT)
 #define ABCMEMMAP_PAGE_MASK	(0xffff & ~(ABCMEMMAP_PAGE_SIZE-1))