mirror of
https://github.com/garrettsworkshop/RAM2E.git
synced 2024-12-26 09:29:28 +00:00
Refactor to separate core and chip-specific stuff
This commit is contained in:
parent
1de3608efa
commit
04eb798443
@ -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
|
636
CPLD/RAM2E-old.v
636
CPLD/RAM2E-old.v
@ -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
|
@ -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
|
333
CPLD/UFM-LCMXO2.v
Normal file
333
CPLD/UFM-LCMXO2.v
Normal file
@ -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
|
189
CPLD/UFM-MAX.v
Normal file
189
CPLD/UFM-MAX.v
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user