/* Phased approach --------------- - Leave SDRAM hanging - Validate SDRAM clocking - Add SDRAM connection for XMS only? - I/O decode (reserved and address registers) - Connect EFB - Connect SPI - Validate we can talk to SPI - Connect page tables - Pre-init page tables - Find and reprogram page tables in UFM - Find and reprogram page tables in bit file - Add config block with XMS mask TP1 : Pin 63 TP2 : Pin 31 TP3 : Pin 89 TP4 : Pin 15 TP5 : Pin 87 TP6 : Pin 17 TP7 : Pin 103 Test connector: [GND] [103] [87 ] [89 ] [63 ] [GND] [N/C] [17 ] [15 ] [31 ] tp[6:0: [GND] [ 6 ] [ 4 ] [ 2 ] [ 0 ] [GND] [N/C] [ 5 ] [ 3 ] [ 1 ] ToDo ---- - Move from external XO input to internal RC. Make sure frequency chosen will work for all temperature ranges - I don't plan to ever support 16-bit I/O. So it seems that driver support for IO16n can be removed. - Eliminate external pullup on OP_ENABLE - It also seems that LA17 and LA18 can also be removed. LA is only used ATM for ZWS control and only for upper XMS Pages. - With XO, LA17, LA18 and IO17n recovered, add extra lines for QSPI and I2C - Add PnP configuration to ISA bridge - Enable EFB - SPI - SPI Flash - Timers - PLLs - UFM - Add steering logic - 16 bit access to an 8 bit device initiates to two 8 bit cycles and reassembly of the bits - 8 bit access to a 16 bit device initates one 16 bit cycle with the wb_sel signal specified by address bit 0 and if odd, steers the upper byte lane back to the lower path. RAM 64 MB - 26 bit Address space 16 MB - 24 bit 32 bit mask for direct translation of upper 15MB in 512KB segments to SDRAM map (by rule lower 2 bits always 0) EMS code reads masks and excludes target pages from free pool. Need two bits in EBR for ro/rw and mapping enabled. If I want to keep EBR map in a 16-bit wide only friendly format for updating by the host, that leaves only 14 bits or 12 bit page size (4K). That leaves 12 bit page frame and 8 bit page count in lower 1MB. 2 EBRs @ 25% utilization. Enable pulls on 16-bit signals to keep them at a sane constant state I/O block at configurable base address - EFB address - EFB data - SPI CS - SPI data - ?????????? - 8 bit read/write - Page address - Page data lo - Page data hi Features: - Configurable conventional/UMB/XMS RAM back-fill - Configurable EMS remappable window (supporting 4.0+) - Configurable 8 or 16-bit operation - ISA PnP config - None traditional. Only used by driver/utility to find card. - Allows config utility to edit stored configuration - DIP switch turns off all config driven actions except PnP block - Automatic load of 32MB flash to 32MB RAM for use as RAM disk - Bootable - Utility to snap-shot current contents to flash - Eventually change RAM to 8-bit and extend burst to free-up 10 pins - Add either SD card or EMMC to STM32 to extend functionality - RTC - BIOS - Int 13h - RAM disk - Int 19h - RAM disk warm boot handler - Int 67h - LIM-EMS - Int 2fh:43h - XMS - Memtest? */ module cpld_top ( // buffered ISA signals input isa_RESET, // ISA reset inout [15:0] isa_D, // ISA data bus (x8) input [19:0] isa_SA, // ISA system address bus (x20) input [23:17] isa_UA, // ISA address bus (x7) input isa_ALE, // ISA address latch enable input isa_SMEMWn, // ISA system memory write input isa_SMEMRn, // ISA system memory read input isa_MEMWn, // ISA memory write input isa_MEMRn, // ISA memory read input isa_IOWn, // ISA I/O write 5 input isa_IORn, // ISA I/O read input isa_SBHEn, // ISA system byte high enable output isa_READY, // ISA ready output isa_M16n, // ISA 16-bit memory supported output isa_IO16n, // ISA 16-bit I/O supported input isa_AEN, // ISA DMA address enable output isa_ZWSn, // ISA Zero wait state enable // Misc input sys_CLK_in, // SYS 20.00 MHz external XO input sys_CFGn, // Normal (1) vs config (0) DIP SW output sys_LED_R, // Status LED Red output sys_LED_B, // Status LED Blue // 64MB SDR SDRAM output [12:0] sdram_A, // 8 Kbit row/column address inout [15:0] sdram_D, // 16-bit data output sdram_CLK, // Clock output sdram_CKE, // Clock enable output [1:0] sdram_DQM, // Data qualification mask output [1:0] sdram_BA, // Bank address output sdram_CSn, // Chip select output sdram_RASn, // Row address strobe output sdram_CASn, // Column address strobe output sdram_WEn // Write enable strobe ); // Clock & reset setup wire sys_CLK; wire sdr_CLK; wire pll_LOCK; plla PLLA ( .CLKI (sys_CLK_in), // 20 MHz .CLKOP (sdr_CLK), // 80 MHz .CLKOS (sys_CLK), // 40 MHz .LOCK (pll_LOCK) ); wire sys_RST = isa_RESET; // Configuration wire [31:0] cfg_XMS = { 32'b0011_1111_1111_1110_0000_0000_0000_0000 }; // ISA strobe aggregation - positive logic wire isa_SMEMW = ~isa_SMEMWn; wire isa_SMEMR = ~isa_SMEMRn; wire isa_MEMW = ~isa_MEMWn; wire isa_MEMR = ~isa_MEMRn; wire isa_SBHE = ~isa_SBHEn; wire isa_MEM = isa_SMEMW | isa_MEMW | isa_SMEMR | isa_MEMR; wire isa_WE = isa_SMEMW | isa_MEMW; // ISA address propagation reg [23:17] isa_LA; always @(negedge isa_ALE) isa_LA <= isa_UA; wire [23:0] isa_A = { isa_LA[23:20], isa_SA[19:0] }; wire [4:0] zero_IDX = { isa_LA[23:19] }; wire cs_XMS = cfg_XMS[ zero_IDX ]; // I/O decode logic reg [8:0] io_BASE = 9'b0010_0100_0; // 240 hex wire cs_IO = (isa_A[11:3] == io_BASE) & ~isa_AEN; reg [7:0] efb_ADR; reg [7:0] efb_DAT; reg [7:0] spi_DAT; reg [7:0] res_DAT; reg [7:0] page_ADR; reg [15:0] page_DAT; wire dummy = isa_SBHEn | isa_SMEMRn | isa_SMEMWn | isa_UA[17] | isa_UA[18]; `define state_IDLE 5'b00_000 `define state_XMS_WRITE_SETUP 5'b01_000 `define state_XMS_WRITE 5'b01_001 `define state_XMS_WRITE_WAIT 5'b01_010 `define state_XMS_READ_SETUP 5'b01_100 `define state_XMS_READ 5'b01_101 `define state_XMS_READ_WAIT 5'b01_110 `define state_IO_WRITE 5'b10_000 `define state_IO_WRITE_WAIT 5'b10_001 `define state_IO_READ 5'b10_010 `define state_IO_READ_WAIT 5'b10_011 // CONV (ram), EMS (window), PNP (io) reg [4:0] state = `state_IDLE; reg ready; reg sdr_CE; reg sdr_WE; reg [24:0] sdr_A; reg [1:0] sdr_SEL; reg [15:0] sdr_DAT_i; wire [15:0] sdr_DAT_o; wire sdr_ACK; reg [7:0] isa_DAT_U; reg [7:0] isa_DAT_L; reg isa_DRV_U; reg isa_DRV_L; always @(posedge sys_CLK)// or posedge sys_RST) begin /* if (sys_RST) begin state <= `state_IDLE; ready <= 1'b1; sdr_CE <= 1'b0; sdr_WE <= 1'b0; sdr_A <= 25'b00_00000000_00000000_0000000; sdr_SEL <= 2'b00; sdr_DAT_i <= 16'h0000; isa_DAT_U <= 8'h00; isa_DRV_U <= 1'b0; isa_DAT_L <= 8'h00; isa_DRV_L <= 1'b0; efb_ADR <= 8'h00; efb_DAT <= 8'h00; spi_DAT <= 8'h00; res_DAT <= 8'h00; page_ADR <= 8'h00; page_DAT <= 16'h0000; end else begin */ ready <= 1'b1; case (state) `state_IDLE : begin if (cs_XMS & ~isa_MEMWn) begin state <= `state_XMS_WRITE_SETUP; ready <= 1'b0; end else if (cs_XMS & ~isa_MEMRn) begin state <= `state_XMS_READ_SETUP; ready <= 1'b0; end else if (cs_IO & ~isa_IORn) begin state <= `state_IO_READ; ready <= 1'b0; end else if (cs_IO & ~isa_IOWn) begin state <= `state_IO_WRITE; ready <= 1'b0; end else begin state <= `state_IDLE; isa_DRV_U <= 1'b0; isa_DRV_L <= 1'b0; end end `state_XMS_WRITE_SETUP : begin state <= `state_XMS_WRITE; ready <= 1'b0; sdr_CE <= 1'b1; sdr_WE <= 1'b1; sdr_A <= {2'b00, isa_A[23:1]}; sdr_SEL <= 2'b11; sdr_DAT_i <= isa_D; end `state_XMS_WRITE : begin if (sdr_ACK) begin state <= `state_XMS_WRITE_WAIT; sdr_CE <= 1'b0; end ready <= 1'b0; end `state_XMS_WRITE_WAIT : begin if (isa_MEMWn) state <= `state_IDLE; end `state_XMS_READ_SETUP : begin state <= `state_XMS_READ; ready <= 1'b0; sdr_CE <= 1'b1; sdr_WE <= 1'b0; sdr_A <= {2'b00, isa_A[23:1]}; sdr_SEL <= 2'b11; end `state_XMS_READ : begin if (sdr_ACK) begin state <= `state_XMS_READ_WAIT; sdr_CE <= 1'b0; isa_DAT_U <= sdr_DAT_o[15:8]; isa_DAT_L <= sdr_DAT_o[7:0]; isa_DRV_U <= 1'b1; isa_DRV_L <= 1'b1; end ready <= 1'b0; end `state_XMS_READ_WAIT : begin if (isa_MEMRn) begin state <= `state_IDLE; isa_DRV_U <= 1'b0; isa_DRV_L <= 1'b0; end end `state_IO_READ : begin state <= `state_IO_READ_WAIT; ready <= 1'b0; isa_DRV_L <= 1'b1; isa_DAT_L <= (isa_A[2:0] == 3'b000) ? efb_ADR : (isa_A[2:0] == 3'b001) ? efb_DAT : (isa_A[2:0] == 3'b010) ? spi_DAT : (isa_A[2:0] == 3'b011) ? spi_DAT : (isa_A[2:0] == 3'b100) ? res_DAT : (isa_A[2:0] == 3'b101) ? page_ADR : (isa_A[2:0] == 3'b110) ? page_DAT[7:0] : page_DAT[15:8]; end `state_IO_READ_WAIT : begin if (isa_IORn) begin state <= `state_IDLE; isa_DRV_L <= 1'b0; end end `state_IO_WRITE : begin case (isa_A[2:0]) 3'b000 : efb_ADR <= isa_D[7:0]; 3'b001 : efb_DAT <= isa_D[7:0]; 3'b010 : spi_DAT <= isa_D[7:0]; 3'b011 : spi_DAT <= isa_D[7:0]; 3'b100 : res_DAT <= isa_D[7:0]; 3'b101 : page_ADR <= isa_D[7:0]; 3'b110 : page_DAT[7:0] <= isa_D[7:0]; 3'b111 : page_DAT[15:8] <= {isa_D[7:1], dummy}; endcase state <= `state_IO_WRITE_WAIT; ready <= 1'b0; end `state_IO_WRITE_WAIT : begin if (isa_IOWn) state <= `state_IDLE; end endcase //end end wire cs_MEM = cs_XMS; // eventually or in lower fill sdram SDRAM ( .sdr_CLK (sdr_CLK), .sdr_RST (sys_RST), .sdr_A (sdr_A), .sdr_SEL (sdr_SEL), .sdr_DAT_i (sdr_DAT_i), .sdr_DAT_o (sdr_DAT_o), .sdr_WE (sdr_WE), .sdr_ACK (sdr_ACK), .sdr_CE (sdr_CE), .pad_DQ (sdram_D), .pad_A (sdram_A), .pad_BA (sdram_BA), .pad_CKE (sdram_CKE), .pad_CSn (sdram_CSn), .pad_RASn (sdram_RASn), .pad_CASn (sdram_CASn), .pad_WEn (sdram_WEn), .pad_DQM (sdram_DQM), .pad_CLK (sdram_CLK) ); /* * ISA output logic * * I'm not sure how the host interprets M16 when a single byte * odd address access is issued. However I think the logic below * is ok for all cases. We always drive D[15:8] on even memory * accesses with valid data and never support 16-bit I/O accesses. * * Only assert zero wait for XML based on backfil (pure combinatorial) */ assign isa_M16n = ~cs_MEM; assign isa_IO16n = 1'bz; assign isa_READY = ready ? 1'bz : 1'b0; assign isa_D[15:8] = isa_DRV_U ? isa_DAT_U : 8'hzz; assign isa_D[7:0] = isa_DRV_L ? isa_DAT_L : 8'hzz; assign isa_ZWSn = 1'bz;//~cs_XMS; // Temporary assign sys_LED_R = cs_MEM; assign sys_LED_B = isa_READY; endmodule