Przeglądaj źródła

Add I/O interface to the ABC bus, using SDRAM DMA

Add handling of ABC-bus I/O ports. All ABC-bus I/O is done
as DMA into the SDRAM; much of which is handled by the same mapping
RAM as used for the memory accesses.

Device select is handled in hardware.

IN and OUT ports 0 support queued DMA; other ports simply access a
single address per port × device select.
H. Peter Anvin 3 lat temu
rodzic
commit
69476ffdf6

+ 67 - 53
fpga/ip/abcmapram.v

@@ -41,6 +41,8 @@ module abcmapram (
 	aclr,
 	address_a,
 	address_b,
+	byteena_a,
+	byteena_b,
 	clock,
 	data_a,
 	data_b,
@@ -50,19 +52,23 @@ module abcmapram (
 	q_b);
 
 	input	  aclr;
-	input	[6:0]  address_a;
-	input	[6:0]  address_b;
+	input	[7:0]  address_a;
+	input	[7:0]  address_b;
+	input	[3:0]  byteena_a;
+	input	[3:0]  byteena_b;
 	input	  clock;
-	input	[17:0]  data_a;
-	input	[17:0]  data_b;
+	input	[35:0]  data_a;
+	input	[35:0]  data_b;
 	input	  wren_a;
 	input	  wren_b;
-	output	[17:0]  q_a;
-	output	[17:0]  q_b;
+	output	[35:0]  q_a;
+	output	[35:0]  q_b;
 `ifndef ALTERA_RESERVED_QIS
 // synopsys translate_off
 `endif
 	tri0	  aclr;
+	tri1	[3:0]  byteena_a;
+	tri1	[3:0]  byteena_b;
 	tri1	  clock;
 	tri0	  wren_a;
 	tri0	  wren_b;
@@ -70,15 +76,17 @@ module abcmapram (
 // synopsys translate_on
 `endif
 
-	wire [17:0] sub_wire0;
-	wire [17:0] sub_wire1;
-	wire [17:0] q_a = sub_wire0[17:0];
-	wire [17:0] q_b = sub_wire1[17:0];
+	wire [35:0] sub_wire0;
+	wire [35:0] sub_wire1;
+	wire [35:0] q_a = sub_wire0[35:0];
+	wire [35:0] q_b = sub_wire1[35:0];
 
 	altsyncram	altsyncram_component (
 				.aclr0 (aclr),
 				.address_a (address_a),
 				.address_b (address_b),
+				.byteena_a (byteena_a),
+				.byteena_b (byteena_b),
 				.clock0 (clock),
 				.data_a (data_a),
 				.data_b (data_b),
@@ -89,8 +97,6 @@ module abcmapram (
 				.aclr1 (1'b0),
 				.addressstall_a (1'b0),
 				.addressstall_b (1'b0),
-				.byteena_a (1'b1),
-				.byteena_b (1'b1),
 				.clock1 (1'b1),
 				.clocken0 (1'b1),
 				.clocken1 (1'b1),
@@ -101,6 +107,8 @@ module abcmapram (
 				.rden_b (1'b1));
 	defparam
 		altsyncram_component.address_reg_b = "CLOCK0",
+		altsyncram_component.byteena_reg_b = "CLOCK0",
+		altsyncram_component.byte_size = 9,
 		altsyncram_component.clock_enable_input_a = "BYPASS",
 		altsyncram_component.clock_enable_input_b = "BYPASS",
 		altsyncram_component.clock_enable_output_a = "BYPASS",
@@ -108,8 +116,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 = 256,
+		altsyncram_component.numwords_b = 256,
 		altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
 		altsyncram_component.outdata_aclr_a = "CLEAR0",
 		altsyncram_component.outdata_aclr_b = "CLEAR0",
@@ -117,14 +125,14 @@ module abcmapram (
 		altsyncram_component.outdata_reg_b = "CLOCK0",
 		altsyncram_component.power_up_uninitialized = "FALSE",
 		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.width_a = 18,
-		altsyncram_component.width_b = 18,
-		altsyncram_component.width_byteena_a = 1,
-		altsyncram_component.width_byteena_b = 1,
+		altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_WITH_NBE_READ",
+		altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ",
+		altsyncram_component.widthad_a = 8,
+		altsyncram_component.widthad_b = 8,
+		altsyncram_component.width_a = 36,
+		altsyncram_component.width_b = 36,
+		altsyncram_component.width_byteena_a = 4,
+		altsyncram_component.width_byteena_b = 4,
 		altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0";
 
 
@@ -137,8 +145,8 @@ endmodule
 // Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
 // Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
 // Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
-// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
-// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
+// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "1"
+// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "1"
 // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "9"
 // Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
 // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
@@ -163,7 +171,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"
@@ -171,8 +179,8 @@ endmodule
 // Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1"
 // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
 // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "1"
-// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "1"
-// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "1"
+// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "4"
+// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "4"
 // Retrieval info: PRIVATE: REGdata NUMERIC "1"
 // Retrieval info: PRIVATE: REGq NUMERIC "1"
 // Retrieval info: PRIVATE: REGrdaddress NUMERIC "0"
@@ -183,10 +191,10 @@ endmodule
 // Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
 // Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
 // Retrieval info: PRIVATE: VarWidth NUMERIC "0"
-// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "18"
-// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "18"
-// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "18"
-// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "18"
+// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "36"
+// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "36"
+// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "36"
+// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "36"
 // Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
 // Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1"
 // Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
@@ -194,6 +202,8 @@ endmodule
 // Retrieval info: PRIVATE: rden NUMERIC "0"
 // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
 // Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0"
+// Retrieval info: CONSTANT: BYTEENA_REG_B STRING "CLOCK0"
+// Retrieval info: CONSTANT: BYTE_SIZE NUMERIC "9"
 // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
 // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
 // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
@@ -201,8 +211,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 "256"
+// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256"
 // 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"
@@ -210,35 +220,39 @@ endmodule
 // Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK0"
 // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
 // 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: 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: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_WITH_NBE_READ"
+// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_WITH_NBE_READ"
+// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8"
+// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8"
+// Retrieval info: CONSTANT: WIDTH_A NUMERIC "36"
+// Retrieval info: CONSTANT: WIDTH_B NUMERIC "36"
+// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "4"
+// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "4"
 // 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 8 0 INPUT NODEFVAL "address_a[7..0]"
+// Retrieval info: USED_PORT: address_b 0 0 8 0 INPUT NODEFVAL "address_b[7..0]"
+// Retrieval info: USED_PORT: byteena_a 0 0 4 0 INPUT VCC "byteena_a[3..0]"
+// Retrieval info: USED_PORT: byteena_b 0 0 4 0 INPUT VCC "byteena_b[3..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]"
-// Retrieval info: USED_PORT: q_a 0 0 18 0 OUTPUT NODEFVAL "q_a[17..0]"
-// Retrieval info: USED_PORT: q_b 0 0 18 0 OUTPUT NODEFVAL "q_b[17..0]"
+// Retrieval info: USED_PORT: data_a 0 0 36 0 INPUT NODEFVAL "data_a[35..0]"
+// Retrieval info: USED_PORT: data_b 0 0 36 0 INPUT NODEFVAL "data_b[35..0]"
+// Retrieval info: USED_PORT: q_a 0 0 36 0 OUTPUT NODEFVAL "q_a[35..0]"
+// Retrieval info: USED_PORT: q_b 0 0 36 0 OUTPUT NODEFVAL "q_b[35..0]"
 // 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 8 0 address_a 0 0 8 0
+// Retrieval info: CONNECT: @address_b 0 0 8 0 address_b 0 0 8 0
+// Retrieval info: CONNECT: @byteena_a 0 0 4 0 byteena_a 0 0 4 0
+// Retrieval info: CONNECT: @byteena_b 0 0 4 0 byteena_b 0 0 4 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
+// Retrieval info: CONNECT: @data_a 0 0 36 0 data_a 0 0 36 0
+// Retrieval info: CONNECT: @data_b 0 0 36 0 data_b 0 0 36 0
 // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0
 // Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0
-// Retrieval info: CONNECT: q_a 0 0 18 0 @q_a 0 0 18 0
-// Retrieval info: CONNECT: q_b 0 0 18 0 @q_b 0 0 18 0
+// Retrieval info: CONNECT: q_a 0 0 36 0 @q_a 0 0 36 0
+// Retrieval info: CONNECT: q_b 0 0 36 0 @q_b 0 0 36 0
 // Retrieval info: GEN_FILE: TYPE_NORMAL abcmapram.v TRUE
 // Retrieval info: GEN_FILE: TYPE_NORMAL abcmapram.inc FALSE
 // Retrieval info: GEN_FILE: TYPE_NORMAL abcmapram.cmp FALSE

+ 210 - 78
fpga/max80.sv

@@ -247,33 +247,71 @@ module max80
    //
    // ABC bus basic interface
    //
+
+   // Synchronizer for ABC-bus input signals; also changes
+   // the sense to positive logic where applicable
+   wire	       abc_clk_s;
+   wire [15:0] abc_a_s;
+   wire [7:0]  abc_di;
+   wire        abc_rst_s;
+   wire        abc_cs_s;
+   wire [4:0]  abc_out_s;
+   wire [1:0]  abc_inp_s;
+   wire        abc_xmemfl_s;
+   wire        abc_xmemw800_s;
+   wire        abc_xmemw80_s;
+   wire        abc_xinpstb_s;
+   wire        abc_xoutpstb_s;
+
+   synchronizer #( .width(39) ) abc_synchro
+     (
+      .rst_n ( rst_n ),
+      .clk ( clk ),
+      .d ( { abc_clk, abc_a, abc_d, ~abc_rst_n, ~abc_cs_n,
+	     ~abc_out_n, ~abc_inp_n, ~abc_xmemfl_n, ~abc_xmemw800_n,
+	     ~abc_xmemw80_n, ~abc_xinpstb_n, ~abc_xoutpstb_n } ),
+      .q ( { abc_clk_s, abc_a_s, abc_di, abc_rst_s, abc_cs_s,
+	     abc_out_s, abc_inp_s, abc_xmemfl_s, abc_xmemw800_s,
+	     abc_xmemw80_s, abc_xinpstb_s, abc_xoutpstb_s } )
+      );
+
    assign abc_master = 1'b0;	// Only device mode supported
    assign abc_d_ce_n = 1'b0;	// Do not isolate busses
 
+   reg	     abc_clk_active;
+
    // On ABC800, only one of XINPSTB# or XOUTPSTB# will be active;
    // on ABC80 they will either be 00 or ZZ; in the latter case pulled
    // low by external resistors.
-   wire abc800 = abc_xinpstb_n | abc_xoutpstb_n;
-   wire abc80  = ~abc800;
+   wire      abc80  = abc_xinpstb_s & abc_xoutpstb_s;
+   wire      abc800 = ~abc80;
 
    // Memory read/write strobes
-   wire abc_xmemrd = ~abc_xmemfl_n; // For consistency
-   wire abc_xmemwr = abc800 ? ~abc_xmemw800_n : ~abc_xmemw80_n;
+   wire abc_xmemrd = abc_clk_active & abc_xmemfl_s;
+   wire abc_xmemwr = abc_clk_active &
+	(abc800 ? abc_xmemw800_s : abc_xmemw80_s);
 
    // I/O read/write strobes
-   wire abc_iord = (abc800 & ~abc_xinpstb_n)  | ~(|abc_inp_n);
-   wire abc_iowr = (abc800 & ~abc_xoutpstb_n) | ~(|abc_out_n);
+   wire abc_iord = abc_clk_active &
+	((abc800 & abc_xinpstb_s)  | (|abc_inp_s));
+   wire abc_iowr = abc_clk_active &
+	((abc800 & abc_xoutpstb_s) | (|abc_out_s));
 
    reg  [7:0] abc_do;
-   reg  [7:0] abc_di;
-   reg [15:0] abc_a_q;
    assign abc_d    = abc_d_oe ? abc_do : 8'hzz;
 
-   always @(posedge sdram_clk)
-     begin
-	abc_di  <= abc_d;
-	abc_a_q <= abc_a;
-     end
+   reg [8:0]  ioselx;
+   wire       iosel_en = ioselx[8];
+   wire       iosel = ioselx[5:0];
+
+   // ABC-bus I/O select
+   always @(negedge rst_n or posedge sdram_clk)
+     if (~rst_n)
+       ioselx <= 9'b0;
+     else if (abc_rst_s)
+       ioselx <= 9'b0;
+     else if (abc_cs_s)
+       ioselx <= { 1'b1, abc_di };
 
    // Open drain signals with optional MOSFETs
    wire abc_wait;
@@ -297,10 +335,10 @@ module max80
    assign abc_xm_x     = opt_mosfet(abc_xm, mosfet_installed[6]);
 
    // Detect ABC-bus clock: need a minimum frequency of 84/64 MHz
-   // to be considered live...
+   // to be considered live.
    reg [2:0] abc_clk_ctr;
    reg [1:0] abc_clk_q;
-   reg	     abc_clk_active;
+
    always @(negedge rst_n or posedge sys_clk)
      if (~rst_n)
        begin
@@ -310,7 +348,7 @@ module max80
        end
      else
        begin
-	  abc_clk_q <= { abc_clk_q[0], abc_clk };
+	  abc_clk_q <= { abc_clk_q[0], abc_clk_s };
 	  case ( {(abc_clk_q == 2'b10), sys_clk_stb[6]} )
 	    5'b10: begin
 	       if (abc_clk_ctr == 3'b111)
@@ -402,81 +440,186 @@ module max80
 `include "iodevs.vh"
 
    // ABC SDRAM interface
-   reg	       abc_rrq;
-   reg	       abc_wrq;
-   reg	       abc_xmemrd_q;
-   reg	       abc_xmemwr_q;
-   reg	       abc_racked;
-   reg	       abc_wacked;
-   wire [15:0] abc_mempg;
-   wire        abc_rden;
-   wire        abc_wren;
-   reg [7:0]   abc_r_q;
-
-
-   wire        abc_rack;
-   wire        abc_wack;
-   wire        abc_rready;
-   wire [7:0]  abc_sr_rd;
-
    //
    // Memory map for ABC-bus memory references.
-   // 512 byte granularity,
-   // bit [15:0] = SDRAM bits [24:9]
-   // bit [16]   = write enable
-   // bit [17]   = read enable
+   // 512 byte granularity for memory (registers 0-127),
+   // one input and one output queue per select code for I/O (128-255).
+   //
+   // bit [24:0]  = SDRAM address.
+   // bit [25]    = write enable ( bit 30 from CPU )
+   // bit [26]    = read enable  ( bit 31 from CPU )
+   // bit [35:27] = DMA count for I/O ( separate register 384-511 from CPU )
    //
    // Accesses from the internal CPU supports 32-bit accesses only!
    //
+   // If the DMA counter is exhausted, or I/O operations other than port 0,
+   // I/O is instead directed to a memory area pointed to by the iomem_base
+   // register as:
+   // bit [24:4]  = iomem_base
+   // bit [3]     = read
+   // bit [2:0]   = port
+   //
+   // However, the rd and wr enable bits in the I/O map still apply.
+   //
+   wire [24:0] abc_memaddr;
+
+   wire [7:0] abc_map_addr =
+	       abc_out_s[0] ? { 1'b1, iosel, 1'b0 } :
+	       abc_inp_s[0] ? { 1'b1, iosel, 1'b1 } :
+	      { 1'b0, abc_a_s[15:9] };
+   wire [8:0]  abc_dma_count;
+   wire [35:0] rdata_abcmemmap;
+   wire        abc_rden;
+   wire        abc_wren;
+
+   //
+   // For I/O, don't allow the read/write enables to conflict with
+   // the direction of the I/O.
+   //
+   wire [1:0] abcmap_masked_rdwr = cpu_mem_wdata[31:30] &
+	      { ~cpu_mem_addr[9] | ~cpu_mem_addr[2],
+		~cpu_mem_addr[9] |  cpu_mem_addr[2] };
+
    abcmapram abcmapram (
 			.aclr      ( ~rst_n ),
 
 			.clock     ( sdram_clk ),
 
-			.address_a ( abc_a_q[15:9] ),
-			.data_a    ( 18'bx ),
-			.wren_a    ( 1'b0 ),
-			.q_a       ( { abc_rden, abc_wren, abc_mempg } ),
-
-			.address_b ( cpu_mem_addr[8:2] ),
-			.data_b    ( cpu_mem_wdata[17:0] ),
+			.address_a ( abc_map_addr ),
+			.data_a    ( { abc_dma_count - 1'b1,
+				       abc_rden, abc_wren,
+				       abc_memaddr + 1'b1 } ),
+			.wren_a    ( abc_dma_update ),
+			.byteena_a ( 4'b1111 ),
+			.q_a       ( { abc_dma_count,
+				       abc_rden, abc_wren, abc_memaddr } ),
+
+			.address_b ( cpu_mem_addr[9:2] ),
+			.data_b    ( { cpu_mem_wdata[8:0],
+				       abcmap_masked_rdwr,
+				       cpu_mem_wdata[24:0] } ),
 			.wren_b    ( iodev_valid_abcmemmap & cpu_mem_wstrb[0] ),
-			.q_b       ( iodev_rdata_abcmemmap )
+			.byteena_b ( { cpu_mem_addr[10],
+				       {3{~cpu_mem_addr[10]}} } ),
+
+			.q_b       ( rdata_abcmemmap )
 			);
 
+   assign iodev_rdata_abcmemmap = cpu_mem_addr[10] ?
+				  { 23'b0, rdata_abcmemmap[35:27] } :
+				  { rdata_abcmemmap[26:25], 5'b0,
+				    rdata_abcmemmap[24:0] };
+   reg [24:4] abc_iobase;
+   reg	      abc_mem_en;
+   reg	      abc_dma_en;
+   reg	      abc_io_en;
+   reg	      abc_rrq;
+   reg	      abc_wrq;
+   reg	      abc_do_memrd;
+   reg	      abc_do_memwr;
+   reg	      abc_racked;
+   reg	      abc_wacked;
+
+   wire       abc_rack;
+   wire       abc_wack;
+   wire       abc_rready;
+   wire [7:0] abc_sr_rd;
 
    always @(posedge sdram_clk or negedge rst_n)
      if (~rst_n)
        begin
-	  abc_d_oe      <= 1'b0;
+	  abc_mem_en    <= 1'b0;
+	  abc_dma_en    <= 1'b0;
+	  abc_io_en     <= 1'b0;
+	  abc_do_memrd  <= 1'b0;
+	  abc_do_memwr  <= 1'b0;
 	  abc_rrq       <= 1'b0;
 	  abc_wrq       <= 1'b0;
-	  abc_xmemrd_q  <= 1'b0;
-	  abc_xmemwr_q  <= 1'b0;
 	  abc_racked    <= 1'b0;
 	  abc_wacked    <= 1'b0;
        end
      else
        begin
-	  abc_d_oe      <= 1'b0;
-
-	  abc_di        <= abc_d;
-	  abc_xmemrd_q  <= abc_xmemrd & abc_rden;
-	  abc_xmemwr_q  <= abc_xmemwr & abc_wren;
-	  abc_racked    <= abc_xmemrd_q & (abc_rack | abc_racked);
-	  abc_wacked    <= abc_xmemwr_q & (abc_wack | abc_wacked);
+	  // Careful with the registering here; need to make sure
+	  // abcmapram is caught up
+	  abc_mem_en    <= abc_xmemwr | abc_xmemrd;
+	  abc_dma_en    <= iosel_en & (abc_out_s[0] | abc_inp_s[0]);
+	  abc_io_en     <= iosel_en & |{abc_out_s, abc_inp_s};
+
+	  abc_do_memrd  <= abc_rden & (abc_mem_en | abc_io_en);
+	  abc_do_memwr  <= abc_wren & (abc_mem_en | abc_io_en);
+	  abc_racked    <= abc_do_memrd & (abc_rack | abc_racked);
+	  abc_wacked    <= abc_do_memwr & (abc_wack | abc_wacked);
+
+	  abc_rrq <= abc_do_memrd & ~abc_racked;
+	  abc_wrq <= abc_do_memwr & ~abc_wacked;
+
+	  abc_dma_update <= abc_dma_en &
+			    ((abc_do_memrd & abc_rack & ~abc_racked) |
+			     (abc_do_memwr & abc_wack & ~abc_wacked));
+       end // else: !if(~rst_n)
 
-	  abc_rrq <= abc_xmemrd_q & ~abc_racked;
-	  abc_wrq <= abc_xmemwr_q & ~abc_wacked;
+   wire [24:0] abc_sdram_addr =
+	       abc_dma_en ? abc_memaddr :
+	       abc_io_en  ? { abc_iobase, |abc_inp_s, abc_a_s[2:0] } :
+	       { abc_memaddr[24:9], abc_a_s[8:0] };
 
-	  if (abc_xmemrd_q & abc_racked & abc_rready)
-	    begin
-	       abc_do   <= abc_sr_rd;
-	       abc_d_oe <= 1'b1;
-	    end
-       end // else: !if(~rst_n)
+   //
+   // ABC-bus data bus handling
+   //
+   always @(posedge sdram_clk or negedge rst_n)
+     if (~rst_n)
+       begin
+	  abc_do   <= 8'hxx;
+	  abc_d_oe <= 1'b0;
+       end
+     else if (abc_do_memwr & abc_racked & abc_rready)
+       begin
+	  abc_do   <= abc_sr_rd;
+	  abc_d_oe <= 1'b1;
+       end
+     else
+       begin
+	  abc_do   <= 8'hxx;
+	  abc_d_oe <= 1'b0;
+       end
 
    //
+   // ABC-bus control/status registers
+   // All these registers are 32-bit access only...
+   //
+   always @(posedge sys_clk or negedge rst_n)
+     if (~rst_n)
+       begin
+	  abc_iobase <= 20'bx;
+       end
+     else if (iodev_valid_abc & cpu_mem_wstrb[0])
+       begin
+	  casez (cpu_mem_addr[5:2])
+	    5'b????1:
+	      abc_iobase <= cpu_mem_wdata[24:4];
+	    default:
+	      /* do nothing */ ;
+	  endcase
+       end
+
+   reg [31:0] abc_status[0:1];
+   always @(posedge sys_clk)
+     begin
+	abc_status[0] <= { 30'b0, abc800, abc_clk_active };
+	abc_status[1] <= abc_status[0];
+     end
+
+   always_comb
+     casez (cpu_mem_addr[5:2])
+       5'b00000: iodev_rdata_abc = abc_status[0];
+       5'b00001: iodev_rdata_abc = abc_iobase;
+       default:  iodev_rdata_abc = 32'bx;
+     endcase // casez (cpu_mem_addr[5:2])
+
+   assign iodev_irq_abc = (abc_status[1] != abc_status[0]);
+
+    //
    // SDRAM
    //
    wire [31:0] sdram_rd;
@@ -511,12 +654,12 @@ module max80
 		.sr_a     ( sr_a ),
 		.sr_dq    ( sr_dq ),
 
-		.a0       ( { abc_mempg, abc_a_q[8:0] } ),
+		.a0       ( abc_sdram_addr ),
 		.rd0      ( abc_sr_rd ),
 		.rrq0     ( abc_rrq ),
 		.rack0    ( abc_rack ),
 		.rready0  ( abc_rready ),
-		.wd0      ( abc_d_q ),
+		.wd0      ( abc_di ),
 		.wrq0     ( abc_wrq ),
 		.wack0    ( abc_wack ),
 
@@ -694,18 +837,7 @@ module max80
    // Hard system reset under program control
    assign reset_cmd = sysreg[3] & cpu_mem_wstrb[0] & cpu_mem_wdata[0];
 
-   // ABC80/800 status
-   assign iodev_rdata_abcbus = { 30'b0, abc800, abc_clk_active };
-   reg [1:0] abc_status[0:1];
-   always @(posedge sys_clk)
-     begin
-	abc_status[0] <= iodev_rdata_abcbus;
-	abc_status[1] <= abc_status[0];
-     end
-
-   wire iodev_irq_abcbus = (abc_status[1] != abc_status[0]);
-
-   // LED indication from the CPU
+  // LED indication from the CPU
    reg [2:0]   led_q;
    always @(negedge rst_n or posedge sys_clk)
      if (~rst_n)
@@ -930,7 +1062,7 @@ module max80
 	    .i2c_scl ( i2c_scl ),
 	    .i2c_sda ( i2c_sda )
 	    );
-   
+
    //
    // Registering of I/O data and handling of iodev_mem_ready
    //

BIN
fpga/output_files/max80.jbc


BIN
fpga/output_files/max80.jic


BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


Plik diff jest za duży
+ 3514 - 3514
fw/boot.mif


+ 13 - 5
fw/hello.c

@@ -147,17 +147,25 @@ IRQHANDLER(sysclock)
 static void init_abc_memmap(void)
 {
     volatile uint32_t *pg = &ABCMEMMAP_PAGE(0);
-    unsigned int addr;
 
-    for (addr = 0; addr < 0x10000; addr += 512) {
+    /* Memory */
+    for (unsigned int addr = 0; addr < 0x10000; addr += 512) {
 	if (addr >= 0x5800 && addr < 0x6000) {
-	    *pg++ = ABCMEMMAP_RD | (addr >> 9);
+	    *pg++ = ABCMEMMAP_RD | addr;
 	} else if (addr >= 0x8000 && addr < 0xc000) {
-	    *pg++ = ABCMEMMAP_RD | ABCMEMMAP_WR | (addr >> 9);
+	    *pg++ = ABCMEMMAP_RD | ABCMEMMAP_WR | addr;
 	} else {
-	    *pg++ = 0;
+	    *pg++ = addr;	/* Disabled */
 	}
     }
+
+    /* I/O */
+    for (unsigned int sel = 0; sel < 64; sel++) {
+	ABCMEMMAP_WRPORT(sel)  = 0;	/* Write DMA address/OUT enable */
+	ABCMEMMAP_WRCOUNT(sel) = 0;	/* DMA write byte count */
+	ABCMEMMAP_RDPORT(sel)  = 0;	/* Read DMA address/IN enable */
+	ABCMEMMAP_RDCOUNT(sel) = 0;	/* DMA read byte count */
+    }
 }
     
 static uint32_t timer_irq_start;

+ 7 - 2
fw/ioregs.h

@@ -95,9 +95,14 @@
 #define ABC_STATUS		IODEVL(ABC,0)
 #define ABC_STATUS_LIVE		1
 #define ABC_STATUS_800		2
+#define ABC_IOBASE		IODEVL(ABC,1)
 
 #define ABCMEMMAP_PAGE(n)	IODEVL(ABCMEMMAP,n)
-#define ABCMEMMAP_WR		0x10000
-#define ABCMEMMAP_RD		0x20000
+#define ABCMEMMAP_WRPORT(n)	IODEVL(ABCMEMMAP,128+((n) << 1))
+#define ABCMEMMAP_RDPORT(n)	IODEVL(ABCMEMMAP,129+((n) << 1))
+#define ABCMEMMAP_WRCOUNT(n)	IODEVL(ABCMEMMAP,384+((n) << 1))
+#define ABCMEMMAP_RDCOUNT(n)	IODEVL(ABCMEMMAP,385+((n) << 1))
+#define ABCMEMMAP_WR		(1 << 30)
+#define ABCMEMMAP_RD		(1 << 31)
 
 #endif /* IODEV_H */

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików