Browse Source

abcbus: put the I/O status register (INP 1) in a separate SRAM

Put the I/O status register (INP 0) into a separate SRAM; this allows
reflecting the status of the DMA engine into the status register.

This eliminates timing dependencies for FIFO management, e.g. in the
disk controller or PUN80 devices.
H. Peter Anvin 3 years ago
parent
commit
4a0966e759

+ 55 - 12
fpga/abcbus.sv

@@ -284,13 +284,16 @@ module abcbus (
 	      { ~cpu_addr[9] | ~cpu_addr[2],
 		~cpu_addr[9] |  cpu_addr[2] };
 
+   wire [8:0] next_dma_count = abc_dma_count - 1'b1;
+   wire       next_dma_empty = ~&next_dma_count;
+
    abcmapram abcmapram (
 			.aclr      ( ~rst_n ),
 
 			.clock     ( sdram_clk ),
 
 			.address_a ( abc_map_addr ),
-			.data_a    ( { abc_dma_count - 1'b1,
+			.data_a    ( { next_dma_count,
 				       abc_rden, abc_wren,
 				       abc_memaddr + 1'b1 } ),
 			.wren_a    ( abc_dma_update ),
@@ -301,7 +304,7 @@ module abcbus (
 			.data_b    ( { cpu_wdata[8:0],
 				       abcmap_masked_rdwr,
 				       cpu_wdata[24:0] } ),
-			.wren_b    ( map_valid & cpu_wstrb[0] ),
+			.wren_b    ( map_valid & ~cpu_addr[11] & cpu_wstrb[0] ),
 			.byteena_b ( { cpu_addr[10],
 				       {3{~cpu_addr[10]}} } ),
 
@@ -330,7 +333,42 @@ module abcbus (
 	  abc_dma_nzero <= |abc_memmap_rd[35:27]; // -> |abc_dma_count
        end
 
-   assign cpu_rdata_map = cpu_addr[10] ?
+   //
+   // RAM for the status register (INP 1). This is in a separate SRAM
+   // so that it can be adjusted for certain DMA events.
+   // bit [7:0] - status register value
+   // bit [8]   - clear bit 0 on read DMA empty
+   // bit [9]   - clear bit 0 on write DMA empty
+   // bit [10]  - clear bit 1 on write DMA empty
+   // bit [11]  - clear bit 7 on any DMA event
+   //
+   wire [15:0] status_out;
+   wire [15:0] rdata_status;
+
+   statusram statusram (
+			.aclr ( ~rst_n ),
+			.clock ( sdram_clk ),
+
+			.address_a ( iosel ),
+			.data_a    ( status_out &
+				     ~{ 4'hf0, status_out[11], 5'b00000,
+					status_out[10] & abc_out_s[0]
+					& next_dma_empty,
+					((status_out[9] & abc_out_s[0]) |
+					 (status_out[8] & abc_inp_s[0]))
+					& next_dma_empty } ),
+			.wren_a    ( abc_dma_update ),
+			.q_a       ( status_out ),
+
+			.address_b ( cpu_addr[7:2] ),
+			.data_b    ( cpu_wdata[11:0] ),
+			.q_b       ( rdata_status ),
+			.wren_b    ( map_valid & cpu_addr[11] & cpu_wstrb[0] )
+			);
+
+   assign cpu_rdata_map = cpu_addr[11] ?
+			  { 16'b0, rdata_status } :
+			  cpu_addr[10] ?
 			  { 23'b0, rdata_abcmemmap[35:27] } :
 			  { rdata_abcmemmap[26:25], 5'b0,
 			    rdata_abcmemmap[24:0] };
@@ -378,7 +416,8 @@ module abcbus (
 	  abc_iowr_en   <= iosel_en & |abc_out & abc_stb[3];
 	  abc_iord_en   <= iosel_en & |abc_inp & abc_stb[3];
 
-	  abc_do_memrd  <= abc_rden & (abc_memrd_en | abc_iord_en);
+	  abc_do_memrd  <= abc_rden & (abc_memrd_en |
+				       (abc_iord_en & abc_inp[0]));
 	  abc_do_memwr  <= abc_wren & (abc_memwr_en | abc_iowr_en);
 	  abc_racked    <= abc_do_memrd & (sdram_rack | abc_racked);
 	  abc_wacked    <= abc_do_memwr & (sdram_wack | abc_wacked);
@@ -392,7 +431,6 @@ module abcbus (
 			     (sdram_wrq & abc_wacked));
        end // else: !if(~rst_n)
 
-
    assign sdram_addr =
 		      (abc_dma_en & |abc_dma_count) ? abc_memaddr :
 		      (abc_iord_en|abc_iowr_en) ? { abc_iobase, |abc_inp_s, abc_a_s[2:0] } :
@@ -406,17 +444,17 @@ module abcbus (
    // set the bit once the DMA counter reaches or already is zero.
 
    wire [7:0] abc_inpflag = { abc_rst, 5'b00000,
-			      abc_iord_en & abc_inp[1],
-			      abc_iord_en & ~abc_dma_nzero & abc_inp[0] };
+			      abc_iord_en & abc_rden & abc_inp[1],
+			      abc_iord_en & abc_rden & ~abc_dma_nzero & abc_inp[0] };
    wire [7:0] abc_outflag = { 2'b00,
-			  {4{abc_iowr_en}} & abc_out[4:1],
+			  {4{abc_iowr_en & abc_wren}} & abc_out[4:1],
 			  abc_cs,
-			  abc_iowr_en & ~abc_dma_nzero & abc_out[0] };
+			  abc_iowr_en & abc_wren & ~abc_dma_nzero & abc_out[0] };
 
    // DMA status register: set on *any* DMA access.
    // bit 0 = out DMA; bit 1 = in DMA.
-   wire [1:0]  abc_dmaflag = { abc_iord_en & abc_dma_en,
-			       abc_iowr_en & abc_dma_en };
+   wire [1:0]  abc_dmaflag = { abc_iord_en & abc_rden & abc_dma_en,
+			       abc_iowr_en & abc_wren & abc_dma_en };
    //
    // ABC-bus data bus handling
    //
@@ -426,6 +464,11 @@ module abcbus (
 	  abc_do   <= 8'hxx;
 	  abc_d_oe <= 1'b0;
        end
+     else if (abc_inp[1] & abc_iord_en & abc_rden)
+       begin
+	  abc_do   <= status_out;
+	  abc_d_oe <= 1'b1;
+       end
      else if (abc_racked & sdram_rready)
        begin
 	  abc_do   <= sdram_rd;
@@ -504,7 +547,7 @@ module abcbus (
    always_comb
      casez (cpu_addr[5:2])
        5'b00000: cpu_rdata = { 24'b0, abc_status[0] };
-       5'b00001: cpu_rdata = ioselx[7:0];
+       5'b00001: cpu_rdata = { 23'b0, ~iosel_en, ioselx[7:0] };
        5'b00010: cpu_rdata = abc_iobase;
        5'b00100: cpu_rdata = irq_mask & irq_status_mask;
        5'b00101: cpu_rdata = irq_status;

+ 10 - 9
fpga/max80.qsf

@@ -215,6 +215,15 @@ set_global_assignment -name OCP_HW_EVAL DISABLE
 set_global_assignment -name TIMING_ANALYZER_DO_REPORT_TIMING ON
 
 
+
+set_global_assignment -name READ_OR_WRITE_IN_BYTE_ADDRESS ON
+set_global_assignment -name POWER_REPORT_POWER_DISSIPATION ON
+set_global_assignment -name POWER_USE_DEVICE_CHARACTERISTICS MAXIMUM
+set_global_assignment -name POWER_USE_TA_VALUE 35
+
+
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+set_global_assignment -name VERILOG_FILE ip/statusram.v
 set_global_assignment -name VERILOG_INCLUDE_FILE iodevs.vh
 set_global_assignment -name SYSTEMVERILOG_FILE tty.sv
 set_global_assignment -name SYSTEMVERILOG_FILE sdcard.sv
@@ -244,12 +253,4 @@ set_global_assignment -name SYSTEMVERILOG_FILE max80.sv
 set_global_assignment -name SOURCE_FILE max80.pins
 set_global_assignment -name SOURCE_TCL_SCRIPT_FILE scripts/pins.tcl
 set_global_assignment -name VERILOG_FILE ip/fifo.v
-set_global_assignment -name VERILOG_FILE ip/ddufifo.v
-
-set_global_assignment -name READ_OR_WRITE_IN_BYTE_ADDRESS ON
-set_global_assignment -name POWER_REPORT_POWER_DISSIPATION ON
-set_global_assignment -name POWER_USE_DEVICE_CHARACTERISTICS MAXIMUM
-set_global_assignment -name POWER_USE_TA_VALUE 35
-
-
-set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+set_global_assignment -name VERILOG_FILE ip/ddufifo.v

BIN
fpga/output_files/max80.jbc


BIN
fpga/output_files/max80.jic


BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


+ 3 - 3
fw/boot.mif

@@ -5301,9 +5301,9 @@ CONTENT BEGIN
 14AE : 634F203A;
 14AF : 31322074;
 14B0 : 32303220;
-14B1 : 30312031;
-14B2 : 3A36333A;
-14B3 : 0A0A3535;
+14B1 : 31312031;
+14B2 : 3A35323A;
+14B3 : 0A0A3335;
 14B4 : 63647300;
 14B5 : 5F647261;
 14B6 : 64616572;

+ 6 - 0
fw/ioregs.h

@@ -127,4 +127,10 @@
 #define ABCMEMMAP_WR		(1 << 30)
 #define ABCMEMMAP_RD		(1 << 31)
 
+#define ABCMEMMAP_STATUS(n)	IODEVL(ABCMEMMAP,512+(n))
+#define ABCMEMMAP_CLR7DMA	0x800
+#define ABCMEMMAP_CLR1WEMP	0x400
+#define ABCMEMMAP_CLR0WEMP	0x200
+#define ABCMEMMAP_CLR0REMP	0x100
+
 #endif /* IODEV_H */