瀏覽代碼

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 年之前
父節點
當前提交
4a0966e759
共有 8 個文件被更改,包括 74 次插入24 次删除
  1. 55 12
      fpga/abcbus.sv
  2. 10 9
      fpga/max80.qsf
  3. 二進制
      fpga/output_files/max80.jbc
  4. 二進制
      fpga/output_files/max80.jic
  5. 二進制
      fpga/output_files/max80.pof
  6. 二進制
      fpga/output_files/max80.sof
  7. 3 3
      fw/boot.mif
  8. 6 0
      fw/ioregs.h

+ 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

二進制
fpga/output_files/max80.jbc


二進制
fpga/output_files/max80.jic


二進制
fpga/output_files/max80.pof


二進制
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 */