From 04eb79844344a9663d5e1371de080cbefafe523d Mon Sep 17 00:00:00 2001 From: Zane Kaminski Date: Wed, 27 Dec 2023 01:09:54 -0500 Subject: [PATCH] Refactor to separate core and chip-specific stuff --- CPLD/RAM2E-LCMXO2.v | 785 ---------------------------------- CPLD/RAM2E-old.v | 636 --------------------------- CPLD/{RAM2E-MAX.v => RAM2E.v} | 233 ++-------- CPLD/UFM-LCMXO2.v | 333 ++++++++++++++ CPLD/UFM-MAX.v | 189 ++++++++ 5 files changed, 550 insertions(+), 1626 deletions(-) delete mode 100644 CPLD/RAM2E-LCMXO2.v delete mode 100644 CPLD/RAM2E-old.v rename CPLD/{RAM2E-MAX.v => RAM2E.v} (61%) create mode 100644 CPLD/UFM-LCMXO2.v create mode 100644 CPLD/UFM-MAX.v diff --git a/CPLD/RAM2E-LCMXO2.v b/CPLD/RAM2E-LCMXO2.v deleted file mode 100644 index 6a6f033..0000000 --- a/CPLD/RAM2E-LCMXO2.v +++ /dev/null @@ -1,785 +0,0 @@ -module RAM2E(C14M, PHI1, LED, - nWE, nWE80, nEN80, nC07X, - Ain, Din, Dout, nDOE, Vout, nVOE, - CKEout, nCSout, nRASout, nCASout, nRWEout, - BA, RAout, DQML, DQMH, RD); - - /* Clocks */ - input C14M, PHI1; - - /* Control inputs */ - input nWE, nWE80, nEN80, nC07X; - - /* Activity LED */ - reg LEDEN = 0; - output LED; assign LED = !(!nEN80 && LEDEN && Ready); - - /* Address Bus */ - input [7:0] Ain; // Multiplexed DRAM address input - - /* 6502 Data Bus */ - input [7:0] Din; // 6502 data bus inputs - reg DOEEN; - always @(posedge C14M) begin - DOEEN <= /*(S==4'h8) || (S==4'h9) || (S==4'hA) ||*/ (S==4'hB) || - (S==4'hC) || (S==4'hD) || (S==4'hE) || (S==4'hF); - end - output nDOE; assign nDOE = !(!nEN80 && nWE && DOEEN); - output [7:0] Dout; assign Dout[7:0] = RD[7:0]; - - /* Video Data Bus */ - reg VOEEN; - always @(posedge C14M) begin - VOEEN <= (S==4'h7) || - (S==4'h8) || (S==4'h9) || (S==4'hA) || (S==4'hB) || - (S==4'hC) || (S==4'hD) || (S==4'hE) || (S==4'hF); - end - output nVOE; assign nVOE = !(!PHI1 && VOEEN); - output reg [7:0] Vout; // Video data bus - always @(posedge C14M) if (S==4'h6) Vout[7:0] <= RD[7:0]; - - /* SDRAM */ - reg CKE = 1; - //reg nCS = 1; - reg nRAS = 1, nCAS = 1, nRWE = 1; - output reg [1:0] BA; - reg [11:0] RA; - output reg DQML = 1, DQMH = 1; - inout [7:0] RD; - assign RD[7:0] = Ready ? (!nWE80 ? Din[7:0] : 8'bZ) : 8'h00; - - /* SDRAM falling edge outputs */ - output reg CKEout; - output nCSout; assign nCSout = 0; - output reg nRASout = 1, nCASout = 1, nRWEout = 1; - output reg [11:0] RAout; - always @(negedge C14M) begin - CKEout <= CKE; - nRASout <= nRAS; - nCASout <= nCAS; - nRWEout <= nRWE; - RAout <= RA; - end - - /* RAMWorks Bank Register and Capacity Mask */ - reg [7:0] RWBank = 0; // RAMWorks bank register - reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask - reg RWSel = 0; // RAMWorks bank register select - always @(posedge C14M) begin - if (S==4'h9) RWSel <= RA[0] && !RA[3] && !nWE && !nC07X; - end - reg CmdRWMaskSet = 0; // RAMWorks Mask register set flag - // Causes RWBank to be zeroed next RWSel access - reg CmdSetRWBankFFChip = 0; - reg CmdSetRWBankFFLED = 0; - reg CmdLEDSet = 0; - reg CmdLEDGet = 0; - - /* Command Sequence Detector */ - reg [2:0] CS = 0; // Command sequence state - reg [2:0] CmdTout = 0; // Command sequence timeout - - /* UFM Interface */ - reg wb_rst; - reg wb_cyc_stb; - reg wb_req; - reg wb_we; - reg [7:0] wb_adr; - reg [7:0] wb_dati; - wire wb_ack; - wire [7:0] wb_dato; - wire ufm_irq; - REFB ufmefb( - .wb_clk_i(C14M), - .wb_rst_i(wb_rst), - .wb_cyc_i(wb_cyc_stb), - .wb_stb_i(wb_cyc_stb), - .wb_we_i(wb_we), - .wb_adr_i(wb_adr), - .wb_dat_i(wb_dati), - .wb_dat_o(wb_dato), - .wb_ack_o(wb_ack), - .wbc_ufm_irq(ufm_irq)); - - /* User Command Triggers */ - //reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel - //reg CmdBitbangSPI = 0; - reg CmdBitbangMXO2 = 0; - reg CmdExecMXO2 = 0; - //reg CmdPrgmMAX = 0; // Set by user command. Programs UFM - //reg CmdEraseMAX = 0; // Set by user command. Erases UFM - - /* State Counters */ - reg PHI1reg = 0; // Saved PHI1 at last rising clock edge - reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15 - reg [15:0] FS = 0; // Fast state counter - wire RefReq = FS[5:4]==0; // Refresh request based on fast state counter - reg [3:0] S = 0; // IIe State counter - - /* State Counters */ - always @(posedge C14M) begin - // Increment fast state counter - FS <= FS+16'h0001; - // Synchronize Apple state counter to S1 when just entering PHI1 - PHI1reg <= PHI1; // Save old PHI1 - S <= (PHI1 && !PHI1reg && Ready) ? 4'h1 : - (S==4'h0) ? 4'h0 : - (S==4'hF) ? 4'hF : S+4'h1; - // Begin normal operation after 64k init cycles (~4.59ms) - if (FS[15:0]==16'hFFFF) Ready <= 1'b1; - end - - /* Command sequence control */ - always @(posedge C14M) begin - if (S==4'hC) begin - if (RWSel) begin - CmdTout <= 0; // Reset command timeout if RWSel accessed - // Recognize command sequence and advance CS state - if ((CS==3'h0 && Din[7:0]==8'hFF) || - (CS==3'h1 && Din[7:0]==8'h00) || - (CS==3'h2 && Din[7:0]==8'h55) || - (CS==3'h3 && Din[7:0]==8'hAA) || - (CS==3'h4 && Din[7:0]==8'hC1) || - (CS==3'h5 && Din[7:0]==8'hAD) || - CS==3'h6 || CS==3'h7) CS <= CS+3'h1; - else CS <= 0; // Back to beginning if it's not right - end else begin - CmdTout <= CmdTout+3'h1; // Increment command timeout - // If command sequence times out, reset sequence state - if (CmdTout==3'h7) CS <= 0; - end - end - end - - /* UFM Control */ - always @(posedge C14M) begin - if (S==4'h0) begin - if (FS[15:14]==2'b00) wb_rst <= 1'b1; - else if (FS[15:14]==2'b01) wb_rst <= 1'b0; - else if (FS[15:14]==2'b10) begin - wb_rst <= 1'b0; - if (wb_ack || (FS[7:0]==0)) wb_cyc_stb <= 0; - else if ((FS[7:0]==1) && wb_req) wb_cyc_stb <= 1; - case (FS[13:8]) - 0: begin // Open frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h80; - wb_req <= 1; - end 1: begin // Enable configuration interface - command - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h74; - wb_req <= 1; - end 2: begin // Enable configuration interface - operand 1/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h08; - wb_req <= 1; - end 3: begin // Enable configuration interface - operand 2/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 4: begin // Enable configuration interface - operand 3/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 5: begin // Close frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - - end 6: begin // Open frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h80; - wb_req <= 1; - end 7: begin // Poll status register - command - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h3C; - wb_req <= 1; - end 8: begin // Poll status register - operand 1/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 9: begin // Poll status register - operand 2/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 10: begin // Poll status register - operand 3/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 11, 12, 13, 14: begin // Read status register 1-4 - wb_we <= 1'b0; - wb_adr[7:0] <= 8'h73; - wb_dati[7:0] <= 8'h3C; - wb_req <= 1; - end 15: begin // Close frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - - end 16: begin // Open frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h80; - wb_req <= 1; - end 17: begin // Set UFM address - command - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'hB4; - wb_req <= 1; - end 18: begin // Set UFM address - operand 1/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 19: begin // Set UFM address - operand 2/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 20: begin // Set UFM address - operand 3/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 21: begin // Set UFM address - data 1/4 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h40; - wb_req <= 1; - end 22: begin // Set UFM address - data 2/4 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 23: begin // Set UFM address - data 3/4 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 24: begin // Set UFM address - data 4/4 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 190; - wb_req <= 1; - end 25: begin // Close frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - - end 26: begin // Open frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h80; - wb_req <= 1; - end 27: begin // Read UFM page - command - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'hCA; - wb_req <= 1; - end 28: begin // Read UFM page - operand 1/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h10; - wb_req <= 1; - end 29: begin // Read UFM page - operand 2/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 30: begin // Read UFM page - operand 3/3 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h01; - wb_req <= 1; - end 31: begin // Read UFM page - data 0 - wb_we <= 1'b0; - wb_adr[7:0] <= 8'h73; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - if (wb_ack) RWMask[7:0] <= wb_dato[7:0]; - end 32: begin // Read UFM page - data 1 - wb_we <= 1'b0; - wb_adr[7:0] <= 8'h73; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - if (wb_ack) LEDEN <= wb_dato[0]; - end 33, 34, - 35, 36, 37, 38, - 39, 40, 41, 42, - 43, 44, 45, 46: begin // Read UFM page - data 2-15 - wb_we <= 1'b0; - wb_adr[7:0] <= 8'h73; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 47: begin // Close frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - - end 48: begin // Open frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h80; - wb_req <= 1; - end 49: begin // Disable configuration interface - command - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h26; - wb_req <= 1; - end 50: begin // Disable configuration interface - operand 1/2 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 51: begin // Disable configuration interface - operand 2/2 - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end 52: begin // Close frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - - end 53: begin // Open frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h80; - wb_req <= 1; - end 54: begin // Bypass - command - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h71; - wb_dati[7:0] <= 8'hFF; - wb_req <= 1; - end 55: begin // Close frame - wb_we <= 1'b1; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 1; - end default: begin - wb_we <= 1'b0; - wb_adr[7:0] <= 8'h70; - wb_dati[7:0] <= 8'h00; - wb_req <= 0; - end - endcase - end else begin - wb_rst <= 1'b0; - wb_cyc_stb <= 1'b0; - wb_req <= 1'b0; - wb_we <= 1'b0; - wb_adr[7:0] <= 8'h00; - wb_dati[7:0] <= 8'h00; - end - end else begin - // UFM bitbang control - wb_rst <= 1'b0; - wb_req <= 1'b0; - - if (RWSel && S==4'hC) begin - // LED control - if (CmdLEDSet) LEDEN <= Din[0]; - - // Set capacity mask - if (CmdRWMaskSet) RWMask[7:0] <= {Din[7], ~Din[6:0]}; - - // Set EFB address - if (CmdBitbangMXO2) begin - wb_adr[7:0] <= Din[7:0]; - wb_dati[7:0] <= wb_adr[7:0]; - end - - // Excecute EFB R/W cycle - if (CmdExecMXO2) begin - wb_we <= Din[0]; - wb_cyc_stb <= 1; - end else if (wb_ack) wb_cyc_stb <= 0; - end - end - end - - /* RAMWorks register control - bank, LED, etc. */ - always @(posedge C14M) begin - if (S==4'hC && RWSel) begin - // Latch RAMWorks bank if accessed - if ((CmdSetRWBankFFLED) || - (CmdSetRWBankFFChip) || - (CmdLEDGet && LEDEN)) RWBank <= 8'hFF; - else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]}; - - if (CS==3'h6) begin // Recognize and submit command in CS6 - // Board has LED detect command - CmdSetRWBankFFLED <= Din[7:0]==8'hF0; - - // Volatile commands - CmdRWMaskSet <= Din[7:0]==8'hE0; - CmdLEDSet <= Din[7:0]==8'hE2; - CmdLEDGet <= Din[7:0]==8'hE3; - end else begin // Reset command triggers - CmdSetRWBankFFLED <= 0; - CmdRWMaskSet <= 0; - CmdLEDSet <= 0; - CmdLEDGet <= 0; - end - end - end - - /* RAMWorks register control - Lattice MachXO2 */ - always @(posedge C14M) begin - if (S==4'hC && RWSel) begin - if (CS==3'h6) begin // Recognize and submit command in CS6 - // Chip detection commands - //CmdSetRWBankFFChip <= Din[7:0]==8'hFF; // MAX - //CmdSetRWBankFFChip <= Din[7:0]==8'hFE; // SPI - CmdSetRWBankFFChip <= Din[7:0]==8'hFD; // MachXO2 - - // Altera MAX II/V commands - //CmdBitbangMAX <= Din[7:0]==8'hEA; - //if (!CmdEraseMAX && !CmdPrgmMAX) begin - // if (Din[7:0]==8'hEE) CmdEraseMAX <= 1; - // if (Din[7:0]==8'hEF) CmdPrgmMAX <= 1; - //end - - // SPI commands - //CmdBitbangSPI <= Din[7:0]==8'hEB; - - // MachXO2 commands - CmdBitbangMXO2 <= Din[7:0]==8'hEC; - CmdExecMXO2 <= Din[7:0]==8'hED; - end else begin // Reset command triggers - CmdSetRWBankFFChip <= 0; - //CmdBitbangMAX <= 0; - //CmdBitbangSPI <= 0; - CmdBitbangMXO2 <= 0; - CmdExecMXO2 <= 0; - end - end - end - - - /* SDRAM Control */ - always @(posedge C14M) case (S) - 4'h0: begin - CKE <= 1'b1; - if (!FS[15] || FS[0]) begin - // NOP - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else case (FS[4:1]) - 4'h0: begin - // PC all - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b0; - end 4'h1: begin - // LDM - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b0; - end 4'h2: begin - // NOP - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end 4'h3, 4'h4, 4'h5, 4'h6, - 4'h7, 4'h8, 4'h9, 4'hA: begin - // AREF - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b1; - end 4'hB: begin - // ACT - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b1; - end 4'hC, 4'hD: begin - // WR - nRAS <= 1'b1; - nCAS <= 1'b0; - nRWE <= 1'b0; - end 4'hE: begin - // NOP - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end 4'hF: begin - // PC all - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b0; - end - endcase - case (FS[4:3]) - 2'b00, 2'b01: begin - // Mode register contents - BA[1:0] <= 2'b00; // Reserved - RA[11] <= 1'b0; // Reserved - RA[10] <= !FS[1]; // reserved / "all" - RA[9] <= 1'b1; // "1" for single write mode - RA[8] <= 1'b0; // Reserved - RA[7] <= 1'b0; // "0" for not test mode - RA[6:4] <= 3'b010; // "2" for CAS latency 2 - RA[3] <= 1'b0; // "0" for sequential burst (not used) - RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst) - end 2'b10: begin - BA[1:0] <= 2'b00; - RA[11:8] <= 4'h0; - RA[7:0] <= FS[14:7]; - end 2'b11: begin - BA[1:0] <= 2'b00; - RA[11:3] <= 9'h000; - RA[2:1] <= FS[6:5]; - RA[0] <= FS[1]; - end - endcase - DQML <= !FS[15]; - DQMH <= !FS[15]; - end 4'h1: begin - // NOP CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - BA[1:0] <= 2'b00; - RA[11:8] <= 4'b0000; - // Hold RA[7:0] - DQML <= 1'b0; - DQMH <= 1'b1; - end 4'h2: begin - // ACT CKE - CKE <= 1'b1; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold BA - // Hold RA - // Hold DQMs - end 4'h3: begin - // RD CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b0; - nRWE <= 1'b1; - // Hold BA - // Hold RA[11:8] - RA[7:0] <= Ain[7:0]; - // Hold DQMs - end 4'h4: begin - // PC all CKE - CKE <= 1'b1; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b0; - // Hold BA - // Hold RA[11] - RA[10] <= 1'b1; // "all" - // Hold RA[9:0] - // Hold DQMs - end 4'h5: begin - if (RefReq) begin - // AREF CKE - CKE <= 1'b1; - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b1; - end else begin - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end - // Hold BA - // Hold RA - // Hold DQMs - end 4'h6: begin - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold BA - // Hold RA - // Hold DQMs - end 4'h7: begin - // Can't check EN80 at this time - if (nWE) begin // Read / idle - // NOP CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else begin // Write / idle - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end - BA[1:0] <= RWBank[6:5]; - RA[11:8] <= RWBank[4:1]; - RA[7:0] <= Ain[7:0]; - // Hold DQMs - end 4'h8: begin - if (nEN80) begin // Idle - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else if (nWE) begin // Read - // ACT CKE - CKE <= 1'b1; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else begin // Write - // NOP CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end - // Hold BA - // Hold RA - // Hold DQMs - end 4'h9: begin - if (nEN80) begin // Idle - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else if (nWE) begin // Read - // RD CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b0; - nRWE <= 1'b1; - end else begin // Write - // ACT CKE - CKE <= 1'b1; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b1; - end - // Hold BA - RA[11:9] <= 3'b000; // no auto-precharge - RA[8] <= RWBank[7]; - RA[7:0] <= Ain[7:0]; - DQMH <= !RWBank[0]; - DQMH <= RWBank[0]; - end 4'hA: begin - if (nEN80) begin // Idle - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold RA[10] - end else if (nWE) begin // Read - // PC all CKD - CKE <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b0; - RA[10] <= 1'b1; - end else begin // Write - // WR CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b0; - nRWE <= 1'b0; - RA[10] <= 1'b0; - end - // Hold BA - // Hold RA[11,9:0] - // Hold DQMs - end 4'hB: begin - if (nEN80) begin // Idle - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else if (nWE) begin // Read - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end else begin // Write - // NOP CKE - CKE <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end - // Hold BA - // Hold RA[11:0] - // Hold DQMs - end 4'hC: begin - if (nEN80) begin // Idle - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold RA[10] - end else if (nWE) begin // Read - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold RA[10] - end else begin // Write - // PC all CKD - CKE <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b0; - RA[10] <= 1'b1; // "all" - end - // Hold BA - // Hold RA[11,9:0] - // Hold RA[7:0] - // Hold DQMs - end 4'hD: begin - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold BA - // Hold RA[11:0] - // Hold DQMs - end 4'hE, 4'hF: begin - // NOP CKD - CKE <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - // Hold BA - // Hold RA[11:8] - RA[7:0] <= Ain[7:0]; // Latch row address for next video read - // Hold DQMs - end - endcase -endmodule diff --git a/CPLD/RAM2E-old.v b/CPLD/RAM2E-old.v deleted file mode 100644 index bcb3b6c..0000000 --- a/CPLD/RAM2E-old.v +++ /dev/null @@ -1,636 +0,0 @@ -module RAM2E(C14M, PHI1, - nWE, nWE80, nEN80, nC07X, - Ain, Din, Dout, nDOE, Vout, nVOE, - CKE, nCS, nRAS, nCAS, nRWE, - BA, RA, RD, DQML, DQMH); - - /* Clocks */ - input C14M, PHI1; - - /* Control inputs */ - input nWE, nWE80, nEN80, nC07X; - - /* Delay for EN80 signal */ - //output DelayOut = 1'b0; - //input DelayIn; - wire EN80 = ~nEN80; - - /* Address Bus */ - input [7:0] Ain; // Multiplexed DRAM address input - - /* 6502 Data Bus */ - input [7:0] Din; // 6502 data bus inputs - reg DOEEN = 0; // 6502 data bus output enable from state machine - output nDOE = ~(EN80 & nWE & DOEEN); // 6502 data bus output enable - output reg [7:0] Dout; // 6502 data Bus output - - /* Video Data Bus */ - output nVOE = ~(~PHI1); /// Video data bus output enable - output reg [7:0] Vout; // Video data bus - - /* SDRAM */ - output reg CKE = 0; - output reg nCS = 1, nRAS = 1, nCAS = 1, nRWE = 1; - output reg [1:0] BA; - output reg [11:0] RA; - output reg DQML = 1, DQMH = 1; - wire RDOE = EN80 & ~nWE80; - inout [7:0] RD = RDOE ? Din[7:0] : 8'bZ; - - /* RAMWorks Bank Register and Capacity Mask */ - reg [7:0] RWBank = 0; // RAMWorks bank register - reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask - reg RWSel = 0; // RAMWorks bank register select - reg RWMaskSet = 0; // RAMWorks Mask register set flag - reg SetRWBankFF = 0; // Causes RWBank to be zeroed next RWSel access - - /* Command Sequence Detector */ - reg [2:0] CS = 0; // Command sequence state - reg [2:0] CmdTout = 0; // Command sequence timeout - - /* UFM Interface */ - reg [15:8] UFMD = 0; // *Parallel* UFM data register - reg ARCLK = 0; // UFM address register clock - // UFM address register data input tied to 0 - reg ARShift = 0; // 1 to Shift UFM address in, 0 to increment - reg DRCLK = 0; // UFM data register clock - reg DRDIn = 0; // UFM data register input - reg DRShift = 0; // 1 to shift UFM out, 0 to load from current address - reg UFMErase = 0; // Rising edge starts erase. UFM+RTP must not be busy - reg UFMProgram = 0; // Rising edge starts program. UFM+RTP must not be busy - wire UFMBusy; // 1 if UFM is doing user operation. Asynchronous - wire RTPBusy; // 1 if real-time programming in progress. Asynchronous - wire DRDOut; // UFM data output - // UFM oscillator always enabled - wire UFMOsc; // UFM oscillator output (3.3-5.5 MHz) - UFM UFM_inst ( // UFM IP block (for Altera MAX II and MAX V) - .arclk (ARCLK), - .ardin (1'b0), - .arshft (ARShift), - .drclk (DRCLK), - .drdin (DRDIn), - .drshft (DRShift), - .erase (UFMErase), - .oscena (1'b1), - .program (UFMProgram), - .busy (UFMBusy), - .drdout (DRDOut), - .osc (UFMOsc), - .rtpbusy (RTPBusy)); - reg UFMBusyReg = 0; // UFMBusy registered to sync with C14M - reg RTPBusyReg = 0; // RTPBusy registered to sync with C14M - - /* UFM State & User Command Triggers */ - reg UFMInitDone = 0; // 1 if UFM initialization finished - reg UFMReqErase = 0; // 1 if UFM requires erase - reg UFMBitbang = 0; // Set by user command. Loads UFM outputs next RWSel - reg UFMPrgmEN = 0; // Set by user command. Programs UFM - reg UFMEraseEN = 0; // Set by user command. Erases UFM - reg DRCLKPulse = 0; // Set by user command. Causes DRCLK pulse next C14M - - /* State Counters */ - reg PHI1reg = 0; // Saved PHI1 at last rising clock edge - reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15 - reg [15:0] FS = 0; // Fast state counter - reg [3:0] S = 0; // IIe State counter - - /* State Counters */ - always @(posedge C14M) begin - // Increment fast state counter - FS <= FS+1; - // Synchronize Apple state counter to S1 when just entering PHI1 - PHI1reg <= PHI1; // Save old PHI1 - S <= (PHI1 & ~PHI1reg & Ready) ? 4'h1 : - S==4'h0 ? 4'h0 : - S==4'hF ? 4'hF : S+1; - end - - /* UFM Control */ - always @(posedge C14M) begin - // Synchronize asynchronous UFM signals - UFMBusyReg <= UFMBusy; - RTPBusyReg <= RTPBusy; - - if (S==4'h0) begin - if ((FS[15:13]==3'b101) | (FS[15:13]==3'b111 & UFMReqErase)) begin - // In states AXXX-BXXX and also EXXX-FXXX if erase/wrap req'd - // shift in 0's to address register - ARCLK <= FS[0]; // Clock address register - DRCLK <= 1'b0; // Don't clock data register - ARShift <= 1'b1; // Shift address registers - DRDIn <= 1'b0; // Don't care DRDIn - DRShift <= 1'b0; // Don't care DRDShift - end else if (~UFMInitDone & FS[15:13]==3'b110 & FS[4:1]==4'h4) begin - // In states CXXX-DXXX (substep 4) - // Xfer to data reg (repeat 256x 1x) - ARCLK <= 1'b0; // Don't clock address register - DRCLK <= FS[0]; // Clock data register - ARShift <= 1'b0; // Don't care ARShift - DRDIn <= 1'b0; // Don't care DRDIn - DRShift <= 1'b0; // Don't care DRShift - end else if (~UFMInitDone & FS[15:13]==3'b110 & FS[4]==1'b1) begin - // In states CXXX-DXXX (substeps 8-F) - // Save UFM D15-8, shift out D14-7 (repeat 256x 8x) - DRCLK <= FS[0]; // Clock data register - ARShift <= 1'b0; // ARShift is 0 because we want to increment - DRDIn <= 1'b0; // Don't care what to shift into data register - DRShift <= 1'b1; // Shift data register - // Shift into UFMD - if (FS[0]) UFMD[15:8] <= {UFMD[14:8], DRDOut}; - - // Compare and store mask - if (FS[4:1]==4'hF) begin - ARCLK <= FS[0]; // Clock address register to increment - // If byte is erased (0xFF, i.e. all 1's, is erased)... - if (UFMD[14:8]==7'b1111111 & DRDOut==1'b1) begin - // Current UFM address is where we want to store - UFMInitDone <= 1'b1; // Quit iterating - // Otherwise byte is valid setting (i.e. some bit is 0)... - end else begin - // Set RWMask, but if saved mask is 0x80, store ~0xFF - if (UFMD[14:8]==7'b1000000 & DRDOut==1'b0) begin - RWMask[7:0] <= {1'b1, ~7'h7F}; - end else RWMask[7:0] <= {UFMD[14], ~UFMD[13:8], ~DRDOut}; - // If last byte in sector... - if (FS[12:5]==8'hFF) begin - UFMReqErase <= 1'b1; // Mark need to erase - end - end - end else ARCLK <= 1'b0; // Don't clock address register - end else begin - ARCLK <= 1'b0; - DRCLK <= 1'b0; - ARShift <= 1'b0; - DRDIn <= 1'b0; - DRShift <= 1'b0; - end - - // Don't erase or program UFM during initialization - UFMErase <= 1'b0; - UFMProgram <= 1'b0; - // Keep DRCLK pulse control disabled during init - DRCLKPulse <= 1'b0; - end else begin - // Can only shift UFM data register now - ARCLK <= 1'b0; - ARShift <= 1'b0; - DRShift <= 1'b1; - - // UFM bitbang control - if (UFMBitbang & CS==3'h7 & RWSel & S==4'hC) begin - DRDIn <= Din[6]; - DRCLKPulse <= Din[7]; - DRCLK <= 1'b0; - end else begin - DRCLKPulse <= 1'b0; - DRCLK <= DRCLKPulse; - end - - // Set capacity mask - if (RWMaskSet & RWSel & S==4'hC) RWMask[7:0] <= {Din[7], ~Din[6:0]}; - - // UFM programming sequence - if (UFMPrgmEN | UFMEraseEN) begin - if (~UFMBusyReg & ~RTPBusyReg) begin - if (UFMReqErase | UFMEraseEN) UFMErase <= 1'b1; - else if (UFMPrgmEN) UFMProgram <= 1'b1; - end else if (UFMBusyReg) UFMReqErase <= 1'b0; - end - end - end - - /* SDRAM Control */ - always @(posedge C14M) begin - if (S==4'h0) begin - // SDRAM initialization - if (FS[15:0]==16'hFFC0) begin - // Precharge All - nCS <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b0; - RA[10] <= 1'b1; // "all" - end else if (FS[15:4]==16'hFFD & FS[0]==1'b0) begin // Repeat 8x - // Auto-refresh - nCS <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b1; - RA[10] <= 1'b0; - end else if (FS[15:0]==16'hFFE8) begin - // Set Mode Register - nCS <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b0; - RA[10] <= 1'b0; // Reserved in mode register - end else if (FS[15:4]==12'hFFF & FS[0]==1'b0) begin // Repeat 8x - // Auto-refresh - nCS <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b1; - RA[10] <= 1'b0; - end else begin // Otherwise send no-op - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - RA[10] <= 1'b0; - end - // Enable SDRAM clock after 65,280 cycles (~4.56ms) - CKE <= FS[15:8] == 8'hFF; - - // Mode register contents - BA[1:0] <= 2'b00; // Reserved - RA[11] <= 1'b0; // Reserved - // RA[10] set above ^ - RA[9] <= 1'b1; // "1" for single write mode - RA[8] <= 1'b0; // Reserved - RA[7] <= 1'b0; // "0" for not test mode - RA[6:4] <= 3'b010; // "2" for CAS latency 2 - RA[3] <= 1'b0; // "0" for sequential burst (not used) - RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst) - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - - // Begin normal operation after 128k init cycles (~9.15ms) - if (FS == 16'hFFFF) Ready <= 1'b1; - end else if (S==4'h1) begin - // Enable clock - CKE <= 1'b1; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h2) begin - // Enable clock - CKE <= 1'b1; - - // Activate - nCS <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // SDRAM bank 0, high-order row address is 0 - BA <= 2'b00; - RA[11:8] <= 4'b0000; - // Row address is as previously latched - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h3) begin - // Enable clock - CKE <= 1'b1; - - // Read - nCS <= 1'b0; - nRAS <= 1'b1; - nCAS <= 1'b0; - nRWE <= 1'b1; - - // SDRAM bank 0, RA[11,9:8] don't care - BA <= 2'b00; - RA[11] <= 1'b0; - RA[10] <= 1'b1; // (A10 set to auto-precharge) - RA[9] <= 1'b0; - RA[8] <= 1'b0; - // Latch column address for read command - RA[7:0] <= Ain[7:0]; - - // Read low byte (high byte is +4MB in ramworks) - DQML <= 1'b0; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h4) begin - // Enable clock - CKE <= 1'b1; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h5) begin - // Enable clock - CKE <= 1'b1; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h6) begin - // Enable clock - CKE <= 1'b1; - - if (FS[5:4]==0) begin - // Auto-refresh - nCS <= 1'b0; - nRAS <= 1'b0; - nCAS <= 1'b0; - nRWE <= 1'b1; - end else begin - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - end - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h7) begin - // Enable clock - CKE <= 1'b1; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - // Latch row address for activate command - RA[7:0] <= Ain[7:0]; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h8) begin - // Enable clock if '245 output enabled - CKE <= EN80; - - // Activate if '245 output enabled - nCS <= nEN80; - nRAS <= 1'b0; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // SDRAM bank, RA[11:8] determine by RamWorks bank - BA <= RWBank[5:4]; - RA[11:8] <= RWBank[3:0]; - // Row address is as previously latched - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'h9) begin - // Enable clock if '245 output enabled - CKE <= EN80; - - // Read/Write if '245 output enabled - nCS <= nEN80; - nRAS <= 1'b1; - nCAS <= 1'b0; - nRWE <= nWE80; - - // SDRAM bank still determined by RamWorks, RA[11,9:8] don't care - BA <= RWBank[5:4]; - RA[11] <= 1'b0; - RA[10] <= 1'b1; // (A10 set to auto-precharge) - RA[9] <= 1'b0; - RA[8] <= RWBank[7]; - // Latch column address for R/W command - RA[7:0] <= Ain[7:0]; - - // Latch RAMWorks low nybble write select using old row address - RWSel <= RA[0] & ~RA[3] & ~nWE & ~nC07X; - - // Mask according to RAMWorks bank (high byte is +4MB) - DQML <= RWBank[6]; - DQMH <= ~RWBank[6]; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'hA) begin - // Enable clock if '245 output enabled - CKE <= EN80; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Inhibit data bus output - DOEEN <= 1'b0; - end else if (S==4'hB) begin - // Disable clock - CKE <= 1'b0; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Enable data bus output - DOEEN <= 1'b1; - end else if (S==4'hC) begin - // Disable clock - CKE <= 1'b0; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Enable data bus output - DOEEN <= 1'b1; - - // RAMWorks Bank Register Select - if (RWSel) begin - // Latch RAMWorks bank if accessed - if (SetRWBankFF) RWBank <= 8'hFF; - else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]}; - - // Recognize command sequence and advance CS state - if ((CS==3'h0 & Din[7:0]==8'hFF) | - (CS==3'h1 & Din[7:0]==8'h00) | - (CS==3'h2 & Din[7:0]==8'h55) | - (CS==3'h3 & Din[7:0]==8'hAA) | - (CS==3'h4 & Din[7:0]==8'hC1) | - (CS==3'h5 & Din[7:0]==8'hAD) | - CS==3'h6 | CS==3'h7) CS <= CS+1; - else CS <= 0; // Back to beginning if it's not right - - if (CS==3'h6) begin // Recognize and submit command in CS6 - SetRWBankFF <= Din[7:0]==8'hFF; - if (Din[7:0]==8'hEF) UFMPrgmEN <= 1'b1; - if (Din[7:0]==8'hEE) UFMEraseEN <= 1'b1; - UFMBitbang <= Din[7:0]==8'hEA; - RWMaskSet <= Din[7:0]==8'hE0; - end else begin // Reset command triggers - SetRWBankFF <= 1'b0; - UFMBitbang <= 1'b0; - RWMaskSet <= 1'b0; - end - - CmdTout <= 0; // Reset command timeout if RWSel accessed - end else begin - CmdTout <= CmdTout+1; // Increment command timeout - // If command sequence times out, reset sequence state - if (CmdTout==3'h7) CS <= 0; - end - end else if (S==4'hD) begin - // Disable clock - CKE <= 1'b0; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Enable data bus output - DOEEN <= 1'b1; - end else if (S==4'hE) begin - // Disable clock - CKE <= 1'b0; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - // Latch row address for next video read - RA[7:0] <= Ain[7:0]; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Enable data bus output - DOEEN <= 1'b1; - end else if (S==4'hF) begin - // Disable clock - CKE <= 1'b0; - - // NOP - nCS <= 1'b1; - nRAS <= 1'b1; - nCAS <= 1'b1; - nRWE <= 1'b1; - - // Don't care bank, RA[11:8] - BA <= 2'b00; - RA[11:8] <= 4'b0000; - // Latch row address for next video read - RA[7:0] <= Ain[7:0]; - - // Mask everything - DQML <= 1'b1; - DQMH <= 1'b1; - - // Enable data bus output - DOEEN <= 1'b1; - end - end - always @(negedge C14M) begin - // Latch video and read data outputs - if (S==4'h6) Vout[7:0] <= RD[7:0]; - if (S==4'hC) Dout[7:0] <= RD[7:0]; - end -endmodule diff --git a/CPLD/RAM2E-MAX.v b/CPLD/RAM2E.v similarity index 61% rename from CPLD/RAM2E-MAX.v rename to CPLD/RAM2E.v index a56b94b..1849e7c 100644 --- a/CPLD/RAM2E-MAX.v +++ b/CPLD/RAM2E.v @@ -10,8 +10,23 @@ module RAM2E(C14M, PHI1, LED, /* Control inputs */ input nWE, nWE80, nEN80, nC07X; + /* "Fast" (init) state counter */ + reg [15:0] FS = 0; always @(posedge C14M) FS <= FS+16'h0001; + reg Ready = 0; + always @(posedge C14M) if (FS[15:0]==16'hFFFF) Ready <= 1'b1; + wire RefReq = FS[5:4]==0; // Refresh request based on fast state counter + + /* IIe state counter */ + reg [3:0] S = 0; + reg PHI1r = 0; always @(posedge C14M) PHI1r <= PHI1; + always @(posedge C14M) begin + S <= (PHI1 && !PHI1r && Ready) ? 4'h1 : + (S==4'h0) ? 4'h0 : + (S==4'hF) ? 4'hF : S+4'h1; + end + /* Activity LED */ - reg LEDEN = 0; + wire LEDEN; output LED; assign LED = !(!nEN80 && LEDEN && Ready); /* Address Bus */ @@ -63,14 +78,14 @@ module RAM2E(C14M, PHI1, LED, /* RAMWorks Bank Register and Capacity Mask */ reg [7:0] RWBank = 0; // RAMWorks bank register - reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask + wire [7:0] RWMask; reg RWSel = 0; // RAMWorks bank register select always @(posedge C14M) begin if (S==4'h9) RWSel <= RA[0] && !RA[3] && !nWE && !nC07X; end reg CmdRWMaskSet = 0; // RAMWorks Mask register set flag // Causes RWBank to be zeroed next RWSel access - reg CmdSetRWBankFFChip = 0; + wire CmdSetRWBankFFChip; reg CmdSetRWBankFFLED = 0; reg CmdLEDSet = 0; reg CmdLEDGet = 0; @@ -79,68 +94,13 @@ module RAM2E(C14M, PHI1, LED, reg [2:0] CS = 0; // Command sequence state reg [2:0] CmdTout = 0; // Command sequence timeout - /* UFM Interface */ - reg [15:8] UFMD = 0; // *Parallel* UFM data register - reg ARCLK = 0; // UFM address register clock - // UFM address register data input tied to 0 - reg ARShift = 0; // 1 to Shift UFM address in, 0 to increment - reg DRCLK = 0; // UFM data register clock - reg DRDIn = 0; // UFM data register input - reg DRShift = 0; // 1 to shift UFM out, 0 to load from current address - reg UFMErase = 0; // Rising edge starts erase. UFM+RTP must not be busy - reg UFMProgram = 0; // Rising edge starts program. UFM+RTP must not be busy - wire UFMBusy; // 1 if UFM is doing user operation. Asynchronous - wire RTPBusy; // 1 if real-time programming in progress. Asynchronous - wire DRDOut; // UFM data output - // UFM oscillator always enabled - wire UFMOsc; // UFM oscillator output (3.3-5.5 MHz) - UFM UFM_inst ( // UFM IP block (for Altera MAX II and MAX V) - .arclk (ARCLK), - .ardin (1'b0), - .arshft (ARShift), - .drclk (DRCLK), - .drdin (DRDIn), - .drshft (DRShift), - .erase (UFMErase), - .oscena (1'b1), - .program (UFMProgram), - .busy (UFMBusy), - .drdout (DRDOut), - .osc (UFMOsc), - .rtpbusy (RTPBusy)); - reg UFMRTPBusy = 0; - always @(posedge C14M) UFMRTPBusy <= UFMBusy || RTPBusy; - reg UFMInitDone = 0; // 1 if UFM initialization finished - reg UFMReqErase = 0; // 1 if UFM requires erase - reg DRCLKPulse = 0; // Set by user command. Causes DRCLK pulse next C14M - - /* User Command Triggers */ - reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel - //reg CmdBitbangSPI = 0; - //reg CmdBitbangMXO2 = 0; - //reg CmdExecMXO2 = 0; - reg CmdPrgmMAX = 0; // Set by user command. Programs UFM - reg CmdEraseMAX = 0; // Set by user command. Erases UFM - - /* State Counters */ - reg PHI1reg = 0; // Saved PHI1 at last rising clock edge - reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15 - reg [15:0] FS = 0; // Fast state counter - wire RefReq = FS[5:4]==0; // Refresh request based on fast state counter - reg [3:0] S = 0; // IIe State counter - - /* State Counters */ - always @(posedge C14M) begin - // Increment fast state counter - FS <= FS+16'h0001; - // Synchronize Apple state counter to S1 when just entering PHI1 - PHI1reg <= PHI1; // Save old PHI1 - S <= (PHI1 && !PHI1reg && Ready) ? 4'h1 : - (S==4'h0) ? 4'h0 : - (S==4'hF) ? 4'hF : S+4'h1; - // Begin normal operation after 64k init cycles (~4.59ms) - if (FS[15:0]==16'hFFFF) Ready <= 1'b1; - end + /* Chip-specific UFM interface */ + RAM2E_UFM ram2e_ufm ( + .C14M(C14M), .S(S), .FS(FS), .CS(CS), + .RWSel(RWSel), .D(Din), + .RWMask(RWMask), .LEDEN(LEDEN), + .CmdRWMaskSet(CmdRWMaskSet), .CmdLEDSet(CmdLEDSet), + .CmdSetRWBankFFChip(CmdSetRWBankFFChip)); /* Command sequence control */ always @(posedge C14M) begin @@ -164,125 +124,20 @@ module RAM2E(C14M, PHI1, LED, end end - /* UFM Control */ - reg UFMProgStart; - always @(posedge C14M) begin - if (S==4'h0) begin - if ((FS[15:13]==3'b101) || (FS[15:13]==3'b111 && UFMReqErase)) begin - // In states AXXX-BXXX and also EXXX-FXXX if erase/wrap req'd - // shift in 0's to address register - ARCLK <= FS[0]; // Clock address register - DRCLK <= 1'b0; // Don't clock data register - ARShift <= 1'b1; // Shift address registers - DRDIn <= 1'b0; // Don't care DRDIn - DRShift <= 1'b0; // Don't care DRDShift - end else if (!UFMInitDone && FS[15:13]==3'b110 && FS[4:1]==4'h4) begin - // In states CXXX-DXXX (substep 4) - // Xfer to data reg (repeat 256x 1x) - ARCLK <= 1'b0; // Don't clock address register - DRCLK <= FS[0]; // Clock data register - ARShift <= 1'b0; // Don't care ARShift - DRDIn <= 1'b0; // Don't care DRDIn - DRShift <= 1'b0; // Don't care DRShift - end else if (!UFMInitDone && FS[15:13]==3'b110 && (FS[4:1]==4'h7 || FS[4]==1'b1)) begin - // In states CXXX-DXXX (substeps 8-F) - // Save UFM D15-8, shift out D14-7 (repeat 256x 8x) - DRCLK <= FS[0]; // Clock data register - ARShift <= 1'b0; // ARShift is 0 because we want to increment - DRDIn <= 1'b0; // Don't care what to shift into data register - DRShift <= 1'b1; // Shift data register - // Shift into UFMD - if (FS[0]) UFMD[15:8] <= {UFMD[14:8], DRDOut}; - - // Compare and store mask - if (FS[4:1]==4'hF) begin - ARCLK <= FS[0]; // Clock address register to increment - // If byte is erased (0xFF, i.e. all 1's, is erased)... - if (UFMD[15:8]==8'hFF && DRDOut==1'b1) begin - // Current UFM address is where we want to store - UFMInitDone <= 1'b1; // Quit iterating - // Otherwise byte is valid setting (i.e. some bit is 0)... - end else begin - // Set RWMask, but if saved mask is 0x80, store ~0xFF - if (UFMD[15:8]==8'b10000000) begin - RWMask[7:0] <= {1'b1, ~7'h7F}; - end else RWMask[7:0] <= {UFMD[15], ~UFMD[14:8]}; - // Set LED setting - LEDEN <= DRDOut ^ UFMD[15]; - // If last byte in sector... - if (FS[12:5]==8'hFF) begin - UFMReqErase <= 1'b1; // Mark need to erase - end - end - end else ARCLK <= 1'b0; // Don't clock address register - end else begin - ARCLK <= 1'b0; - DRCLK <= 1'b0; - ARShift <= 1'b0; - DRDIn <= 1'b0; - DRShift <= 1'b0; - end - - // Don't erase or program UFM during initialization - UFMErase <= 1'b0; - UFMProgram <= 1'b0; - // Keep DRCLK pulse control disabled during init - DRCLKPulse <= 1'b0; - // Reset UFMProgStart - UFMProgStart <= 1'b0; - end else begin - // Can only shift UFM data register now - ARCLK <= 1'b0; - ARShift <= 1'b0; - DRShift <= 1'b1; - - // UFM bitbang control - if (CmdBitbangMAX && RWSel && S==4'hC) begin - DRDIn <= Din[6]; - DRCLKPulse <= Din[7]; - DRCLK <= 1'b0; - end else begin - DRCLKPulse <= 1'b0; - DRCLK <= DRCLKPulse; - end - - // Volatile settings command execution - if (RWSel && S==4'hC) begin - // LED control - if (CmdLEDSet) LEDEN <= Din[0]; - // Set capacity mask - if (CmdRWMaskSet) RWMask[7:0] <= {Din[7], ~Din[6:0]}; - end - - // UFM programming sequence - if (S==4'h1) begin - if (!UFMProgStart && !UFMRTPBusy) begin - if (CmdPrgmMAX) begin - UFMErase <= UFMReqErase; - UFMProgStart <= 1; - end else if (CmdEraseMAX) UFMErase <= 1; - end else if (UFMProgStart && !UFMRTPBusy) begin - UFMErase <= 0; - if (!UFMErase) UFMProgram <= 1; - end - end - end - end - /* RAMWorks register control - bank, LED, etc. */ always @(posedge C14M) begin if (S==4'hC && RWSel) begin // Latch RAMWorks bank if accessed - if ((CmdSetRWBankFFLED) || - (CmdSetRWBankFFChip) || + if ((CmdSetRWBankFFLED) || (CmdSetRWBankFFChip) || (CmdLEDGet && LEDEN)) RWBank <= 8'hFF; else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]}; if (CS==3'h6) begin // Recognize and submit command in CS6 - // Board has LED detect command + // LED detect command CmdSetRWBankFFLED <= Din[7:0]==8'hF0; // Volatile commands + CmdSetRWBankFFLED <= Din[7:0]==8'hF0; CmdRWMaskSet <= Din[7:0]==8'hE0; CmdLEDSet <= Din[7:0]==8'hE2; CmdLEDGet <= Din[7:0]==8'hE3; @@ -295,38 +150,6 @@ module RAM2E(C14M, PHI1, LED, end end - /* RAMWorks register control - Altera MAX */ - always @(posedge C14M) begin - if (S==4'hC && RWSel) begin - if (CS==3'h6) begin // Recognize and submit command in CS6 - // Chip detection commands - CmdSetRWBankFFChip <= Din[7:0]==8'hFF; // MAX - //CmdSetRWBankFFChip <= Din[7:0]==8'hFE; // SPI - //CmdSetRWBankFFChip <= Din[7:0]==8'hFD; // MachXO2 - - // Altera MAX II/V commands - CmdBitbangMAX <= Din[7:0]==8'hEA; - if (!CmdEraseMAX && !CmdPrgmMAX) begin - if (Din[7:0]==8'hEE) CmdEraseMAX <= 1; - if (Din[7:0]==8'hEF) CmdPrgmMAX <= 1; - end - - // SPI commands - //CmdBitbangSPI <= Din[7:0]==8'hEB; - - // MachXO2 commands - //CmdBitbangMXO2 <= Din[7:0]==8'hEC; - //CmdExecMXO2 <= Din[7:0]==8'hED; - end else begin // Reset command triggers - CmdSetRWBankFFChip <= 0; - CmdBitbangMAX <= 0; - //CmdBitbangSPI <= 0; - //CmdBitbangMXO2 <= 0; - //CmdExecMXO2 <= 0; - end - end - end - /* SDRAM Control */ always @(posedge C14M) case (S) 4'h0: begin diff --git a/CPLD/UFM-LCMXO2.v b/CPLD/UFM-LCMXO2.v new file mode 100644 index 0000000..faf1ae0 --- /dev/null +++ b/CPLD/UFM-LCMXO2.v @@ -0,0 +1,333 @@ +module RAM2E_UFM(C14M, S, FS, CS, + RWSel, D, + RWMask, LEDEN, + CmdRWMaskSet, CmdLEDSet, + CmdSetRWBankFFChip); + input C14M; + input [3:0] S; + input [15:0] FS; + input [2:0] CS; + input RWSel; + input [7:0] D; + output reg [7:0] RWMask; + output reg LEDEN; + input CmdRWMaskSet; + input CmdLEDSet; + output reg CmdSetRWBankFFChip; + + /* RAMWorks register control - Lattice MachXO2 */ + reg CmdBitbangMXO2 = 0; + reg CmdExecMXO2 = 0; + always @(posedge C14M) begin + if (S==4'hC && RWSel) begin + if (CS==3'h6) begin // Recognize and submit command in CS6 + // Chip detection commands + //CmdSetRWBankFFChip <= D[7:0]==8'hFF; // MAX + //CmdSetRWBankFFChip <= D[7:0]==8'hFE; // SPI + CmdSetRWBankFFChip <= D[7:0]==8'hFD; // MachXO2 + + // Altera MAX II/V commands + //CmdBitbangMAX <= D[7:0]==8'hEA; + //if (!CmdEraseMAX && !CmdPrgmMAX) begin + // if (D[7:0]==8'hEE) CmdEraseMAX <= 1; + // if (D[7:0]==8'hEF) CmdPrgmMAX <= 1; + //end + + // SPI commands + //CmdBitbangSPI <= D[7:0]==8'hEB; + + // MachXO2 commands + CmdBitbangMXO2 <= D[7:0]==8'hEC; + CmdExecMXO2 <= D[7:0]==8'hED; + end else begin // Reset command triggers + CmdSetRWBankFFChip <= 0; + CmdBitbangMXO2 <= 0; + CmdExecMXO2 <= 0; + end + end + end + + /* UFM Interface */ + reg wb_rst; + reg wb_cyc_stb; + reg wb_req; + reg wb_we; + reg [7:0] wb_adr; + reg [7:0] wb_dati; + wire wb_ack; + wire [7:0] wb_dato; + wire ufm_irq; + REFB ufmefb( + .wb_clk_i(C14M), + .wb_rst_i(wb_rst), + .wb_cyc_i(wb_cyc_stb), + .wb_stb_i(wb_cyc_stb), + .wb_we_i(wb_we), + .wb_adr_i(wb_adr), + .wb_dat_i(wb_dati), + .wb_dat_o(wb_dato), + .wb_ack_o(wb_ack), + .wbc_ufm_irq(ufm_irq)); + + /* UFM Control */ + always @(posedge C14M) begin + if (S==4'h0) begin + if (FS[15:14]==2'b00) wb_rst <= 1'b1; + else if (FS[15:14]==2'b01) wb_rst <= 1'b0; + else if (FS[15:14]==2'b10) begin + wb_rst <= 1'b0; + if (wb_ack || (FS[7:0]==0)) wb_cyc_stb <= 0; + else if ((FS[7:0]==1) && wb_req) wb_cyc_stb <= 1; + case (FS[13:8]) + 0: begin // Open frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h80; + wb_req <= 1; + end 1: begin // Enable configuration interface - command + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h74; + wb_req <= 1; + end 2: begin // Enable configuration interface - operand 1/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h08; + wb_req <= 1; + end 3: begin // Enable configuration interface - operand 2/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 4: begin // Enable configuration interface - operand 3/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 5: begin // Close frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + + end 6: begin // Open frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h80; + wb_req <= 1; + end 7: begin // Poll status register - command + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h3C; + wb_req <= 1; + end 8: begin // Poll status register - operand 1/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 9: begin // Poll status register - operand 2/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 10: begin // Poll status register - operand 3/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 11, 12, 13, 14: begin // Read status register 1-4 + wb_we <= 1'b0; + wb_adr[7:0] <= 8'h73; + wb_dati[7:0] <= 8'h3C; + wb_req <= 1; + end 15: begin // Close frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + + end 16: begin // Open frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h80; + wb_req <= 1; + end 17: begin // Set UFM address - command + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'hB4; + wb_req <= 1; + end 18: begin // Set UFM address - operand 1/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 19: begin // Set UFM address - operand 2/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 20: begin // Set UFM address - operand 3/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 21: begin // Set UFM address - data 1/4 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h40; + wb_req <= 1; + end 22: begin // Set UFM address - data 2/4 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 23: begin // Set UFM address - data 3/4 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 24: begin // Set UFM address - data 4/4 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 190; + wb_req <= 1; + end 25: begin // Close frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + + end 26: begin // Open frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h80; + wb_req <= 1; + end 27: begin // Read UFM page - command + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'hCA; + wb_req <= 1; + end 28: begin // Read UFM page - operand 1/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h10; + wb_req <= 1; + end 29: begin // Read UFM page - operand 2/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 30: begin // Read UFM page - operand 3/3 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h01; + wb_req <= 1; + end 31: begin // Read UFM page - data 0 + wb_we <= 1'b0; + wb_adr[7:0] <= 8'h73; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + if (wb_ack) RWMask[7:0] <= wb_dato[7:0]; + end 32: begin // Read UFM page - data 1 + wb_we <= 1'b0; + wb_adr[7:0] <= 8'h73; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + if (wb_ack) LEDEN <= wb_dato[0]; + end 33, 34, + 35, 36, 37, 38, + 39, 40, 41, 42, + 43, 44, 45, 46: begin // Read UFM page - data 2-15 + wb_we <= 1'b0; + wb_adr[7:0] <= 8'h73; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 47: begin // Close frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + + end 48: begin // Open frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h80; + wb_req <= 1; + end 49: begin // Disable configuration interface - command + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h26; + wb_req <= 1; + end 50: begin // Disable configuration interface - operand 1/2 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 51: begin // Disable configuration interface - operand 2/2 + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end 52: begin // Close frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + + end 53: begin // Open frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h80; + wb_req <= 1; + end 54: begin // Bypass - command + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h71; + wb_dati[7:0] <= 8'hFF; + wb_req <= 1; + end 55: begin // Close frame + wb_we <= 1'b1; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 1; + end default: begin + wb_we <= 1'b0; + wb_adr[7:0] <= 8'h70; + wb_dati[7:0] <= 8'h00; + wb_req <= 0; + end + endcase + end else begin + wb_rst <= 1'b0; + wb_cyc_stb <= 1'b0; + wb_req <= 1'b0; + wb_we <= 1'b0; + wb_adr[7:0] <= 8'h00; + wb_dati[7:0] <= 8'h00; + end + end else begin + // UFM bitbang control + wb_rst <= 1'b0; + wb_req <= 1'b0; + + if (RWSel && S==4'hC) begin + // LED control + if (CmdLEDSet) LEDEN <= D[0]; + + // Set capacity mask + if (CmdRWMaskSet) RWMask[7:0] <= {D[7], ~D[6:0]}; + + // Set EFB address + if (CmdBitbangMXO2) begin + wb_adr[7:0] <= D[7:0]; + wb_dati[7:0] <= wb_adr[7:0]; + end + + // Excecute EFB R/W cycle + if (CmdExecMXO2) begin + wb_we <= D[0]; + wb_cyc_stb <= 1; + end else if (wb_ack) wb_cyc_stb <= 0; + end + end + end +endmodule diff --git a/CPLD/UFM-MAX.v b/CPLD/UFM-MAX.v new file mode 100644 index 0000000..d144db7 --- /dev/null +++ b/CPLD/UFM-MAX.v @@ -0,0 +1,189 @@ +module RAM2E_UFM(C14M, S, FS, CS, + RWSel, D, + RWMask, LEDEN, + CmdRWMaskSet, CmdLEDSet, + CmdSetRWBankFFChip); + input C14M; + input [3:0] S; + input [15:0] FS; + input [2:0] CS; + input RWSel; + input [7:0] D; + output reg [7:0] RWMask; + output reg LEDEN; + input CmdRWMaskSet; + input CmdLEDSet; + output reg CmdSetRWBankFFChip; + + /* RAMWorks register control - Altera MAX */ + reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel + reg CmdPrgmMAX = 0; // Set by user command. Programs UFM + reg CmdEraseMAX = 0; // Set by user command. Erases UFM + always @(posedge C14M) begin + if (S==4'hC && RWSel) begin + if (CS==3'h6) begin // Recognize and submit command in CS6 + // Chip detection commands + CmdSetRWBankFFChip <= D[7:0]==8'hFF; // MAX + //CmdSetRWBankFFChip <= D[7:0]==8'hFE; // SPI + //CmdSetRWBankFFChip <= D[7:0]==8'hFD; // MachXO2 + + // Altera MAX II/V commands + CmdBitbangMAX <= D[7:0]==8'hEA; + if (!CmdEraseMAX && !CmdPrgmMAX) begin + if (D[7:0]==8'hEE) CmdEraseMAX <= 1; + if (D[7:0]==8'hEF) CmdPrgmMAX <= 1; + end + + // SPI commands + //CmdBitbangSPI <= D[7:0]==8'hEB; + + // MachXO2 commands + //CmdBitbangMXO2 <= D[7:0]==8'hEC; + //CmdExecMXO2 <= D[7:0]==8'hED; + end else begin // Reset command triggers + CmdSetRWBankFFChip <= 0; + CmdBitbangMAX <= 0; + end + end + end + + /* UFM Interface */ + reg [15:8] UFMD = 0; // *Parallel* UFM data register + reg ARCLK = 0; // UFM address register clock + // UFM address register data input tied to 0 + reg ARShift = 0; // 1 to Shift UFM address in, 0 to increment + reg DRCLK = 0; // UFM data register clock + reg DRDIn = 0; // UFM data register input + reg DRShift = 0; // 1 to shift UFM out, 0 to load from current address + reg UFMErase = 0; // Rising edge starts erase. UFM+RTP must not be busy + reg UFMProgram = 0; // Rising edge starts program. UFM+RTP must not be busy + wire UFMBusy; // 1 if UFM is doing user operation. Asynchronous + wire RTPBusy; // 1 if real-time programming in progress. Asynchronous + wire DRDOut; // UFM data output + // UFM oscillator always enabled + wire UFMOsc; // UFM oscillator output (3.3-5.5 MHz) + UFM UFM_inst ( // UFM IP block (for Altera MAX II and MAX V) + .arclk (ARCLK), + .ardin (1'b0), + .arshft (ARShift), + .drclk (DRCLK), + .drdin (DRDIn), + .drshft (DRShift), + .erase (UFMErase), + .oscena (1'b1), + .program (UFMProgram), + .busy (UFMBusy), + .drdout (DRDOut), + .osc (UFMOsc), + .rtpbusy (RTPBusy)); + reg UFMRTPBusy = 0; + always @(posedge C14M) UFMRTPBusy <= UFMBusy || RTPBusy; + reg UFMInitDone = 0; // 1 if UFM initialization finished + reg UFMReqErase = 0; // 1 if UFM requires erase + reg DRCLKPulse = 0; // Set by user command. Causes DRCLK pulse next C14M + + /* UFM control */ + reg UFMProgStart; + always @(posedge C14M) begin + if (S==4'h0) begin + if ((FS[15:13]==3'b101) || (FS[15:13]==3'b111 && UFMReqErase)) begin + // In states AXXX-BXXX and also EXXX-FXXX if erase/wrap req'd + // shift in 0's to address register + ARCLK <= FS[0]; // Clock address register + DRCLK <= 1'b0; // Don't clock data register + ARShift <= 1'b1; // Shift address registers + DRDIn <= 1'b0; // Don't care DRDIn + DRShift <= 1'b0; // Don't care DRDShift + end else if (!UFMInitDone && FS[15:13]==3'b110 && FS[4:1]==4'h4) begin + // In states CXXX-DXXX (substep 4) + // Xfer to data reg (repeat 256x 1x) + ARCLK <= 1'b0; // Don't clock address register + DRCLK <= FS[0]; // Clock data register + ARShift <= 1'b0; // Don't care ARShift + DRDIn <= 1'b0; // Don't care DRDIn + DRShift <= 1'b0; // Don't care DRShift + end else if (!UFMInitDone && FS[15:13]==3'b110 && (FS[4:1]==4'h7 || FS[4]==1'b1)) begin + // In states CXXX-DXXX (substeps 8-F) + // Save UFM D15-8, shift out D14-7 (repeat 256x 8x) + DRCLK <= FS[0]; // Clock data register + ARShift <= 1'b0; // ARShift is 0 because we want to increment + DRDIn <= 1'b0; // Don't care what to shift into data register + DRShift <= 1'b1; // Shift data register + // Shift into UFMD + if (FS[0]) UFMD[15:8] <= {UFMD[14:8], DRDOut}; + + // Compare and store mask + if (FS[4:1]==4'hF) begin + ARCLK <= FS[0]; // Clock address register to increment + // If byte is erased (0xFF, i.e. all 1's, is erased)... + if (UFMD[15:8]==8'hFF && DRDOut==1'b1) begin + // Current UFM address is where we want to store + UFMInitDone <= 1'b1; // Quit iterating + // Otherwise byte is valid setting (i.e. some bit is 0)... + end else begin + // Set RWMask, but if saved mask is 0x80, store ~0xFF + if (UFMD[15:8]==8'b10000000) begin + RWMask[7:0] <= {1'b1, ~7'h7F}; + end else RWMask[7:0] <= {UFMD[15], ~UFMD[14:8]}; + // Set LED setting + LEDEN <= DRDOut ^ UFMD[15]; + // If last byte in sector... + if (FS[12:5]==8'hFF) begin + UFMReqErase <= 1'b1; // Mark need to erase + end + end + end else ARCLK <= 1'b0; // Don't clock address register + end else begin + ARCLK <= 1'b0; + DRCLK <= 1'b0; + ARShift <= 1'b0; + DRDIn <= 1'b0; + DRShift <= 1'b0; + end + + // Don't erase or program UFM during initialization + UFMErase <= 1'b0; + UFMProgram <= 1'b0; + // Keep DRCLK pulse control disabled during init + DRCLKPulse <= 1'b0; + // Reset UFMProgStart + UFMProgStart <= 1'b0; + end else begin + // Can only shift UFM data register now + ARCLK <= 1'b0; + ARShift <= 1'b0; + DRShift <= 1'b1; + + // UFM bitbang control + if (CmdBitbangMAX && RWSel && S==4'hC) begin + DRDIn <= D[6]; + DRCLKPulse <= D[7]; + DRCLK <= 1'b0; + end else begin + DRCLKPulse <= 1'b0; + DRCLK <= DRCLKPulse; + end + + // Volatile settings command execution + if (RWSel && S==4'hC) begin + // LED control + if (CmdLEDSet) LEDEN <= D[0]; + // Set capacity mask + if (CmdRWMaskSet) RWMask[7:0] <= {D[7], ~D[6:0]}; + end + + // UFM programming sequence + if (S==4'h1) begin + if (!UFMProgStart && !UFMRTPBusy) begin + if (CmdPrgmMAX) begin + UFMErase <= UFMReqErase; + UFMProgStart <= 1; + end else if (CmdEraseMAX) UFMErase <= 1; + end else if (UFMProgStart && !UFMRTPBusy) begin + UFMErase <= 0; + if (!UFMErase) UFMProgram <= 1; + end + end + end + end +endmodule