41
41
-- BANK1 (USER BIOS 512kB) XXXX 0111 0 |0 |X 0x000000
42
42
-- BANK2 (USER BIOS 512kB) XXXX 1000 0 |1 |X 0x080000
43
43
-- BANK1 (USER BIOS 1MB) XXXX 1001 0 |X |X 0x000000
44
- -- RECOVERY (NOTE 1) XXXX 1010 1 |1 |1 0x1C0000
45
- --
44
+ -- RECOVERY (NOTE 1) XXXX 1010 1 |1 |1 0x1C0000
45
+ --
46
46
--
47
47
-- NOTE 1: The RECOVERY bank can also be actived by the physical switch on the Xenium. This forces bank ten (0b1010) on power up.
48
48
-- This bank also contains non-volatile storage of settings an EEPROM backup in the smaller sectors at the end of the flash memory.
58
58
-- X,SCK,CS,MOSI,BANK[3:0]
59
59
--
60
60
-- **0xEF READ:**
61
- -- RECOV SWITCH POSITION (0=ACTIVE),X,MISO(Pin 1),MISO (Pin 4),BANK[3:0]
61
+ -- RECOV SWITCH POSITION (0=ACTIVE),X,MISO(Pin 1),MISO (Pin 4),BANK[3:0]
62
62
--
63
63
-- **0xEE (WRITE)**
64
64
-- X,X,X,X X,B,G,R (DEFAULT LED ON POWER UP IS RED)
65
65
--
66
66
-- **0xEE (READ)**
67
67
-- Just returns 0x55 on a real xenium?
68
- --
69
-
68
+ --
69
+
70
70
LIBRARY IEEE;
71
71
USE IEEE.STD_LOGIC_1164.ALL ;
72
72
USE IEEE.STD_LOGIC_UNSIGNED.ALL ;
@@ -99,23 +99,23 @@ END openxenium;
99
99
ARCHITECTURE Behavioral OF openxenium IS
100
100
101
101
TYPE LPC_STATE_MACHINE IS (
102
- WAIT_START,
103
- CYCTYPE_DIR,
104
- ADDRESS,
105
- WRITE_DATA,
106
- READ_DATA0,
107
- READ_DATA1,
108
- TAR1,
109
- TAR2,
110
- SYNCING,
111
- SYNC_COMPLETE,
102
+ WAIT_START,
103
+ CYCTYPE_DIR,
104
+ ADDRESS,
105
+ WRITE_DATA,
106
+ READ_DATA0,
107
+ READ_DATA1,
108
+ TAR1,
109
+ TAR2,
110
+ SYNCING,
111
+ SYNC_COMPLETE,
112
112
TAR_EXIT
113
113
);
114
-
114
+
115
115
TYPE CYC_TYPE IS (
116
116
IO_READ, -- Default state
117
- IO_WRITE,
118
- MEM_READ,
117
+ IO_WRITE,
118
+ MEM_READ,
119
119
MEM_WRITE
120
120
);
121
121
@@ -126,22 +126,22 @@ ARCHITECTURE Behavioral OF openxenium IS
126
126
127
127
-- XENIUM IO REGISTERS. BITS MARKED 'X' HAVE AN UNKNOWN FUNCTION OR ARE UNUSED. NEEDS MORE RE.
128
128
-- Bit masks are all shown upper nibble first.
129
-
129
+
130
130
-- IO WRITE/READ REGISTERS SIGNALS
131
131
CONSTANT REG_00EE_READ : STD_LOGIC_VECTOR (7 DOWNTO 0 ) := "01010101" ; -- Genuine Xenium
132
132
SIGNAL REG_00EE_WRITE : STD_LOGIC_VECTOR (7 DOWNTO 0 ) := "00000001" ; -- X,X,X,X X,B,G,R. Red is default LED colour
133
133
SIGNAL REG_00EF_WRITE : STD_LOGIC_VECTOR (7 DOWNTO 0 ) := "00000001" ; -- X,SCK,CS,MOSI, BANKCONTROL[3:0]. Bank 1 is default.
134
134
SIGNAL REG_00EF_READ : STD_LOGIC_VECTOR (7 DOWNTO 0 ) := "01010101" ; -- Input signal
135
135
SIGNAL READBUFFER : STD_LOGIC_VECTOR (7 DOWNTO 0 ); -- I buffer Memory and IO reads to reduce pin to pin delay in CPLD which caused issues
136
-
136
+
137
137
-- R/W SIGNAL FOR FLASH MEMORY
138
138
SIGNAL sFLASH_DQ : STD_LOGIC_VECTOR (7 DOWNTO 0 ) := "ZZZZZZZZ" ;
139
-
139
+
140
140
-- TSOPBOOT IS SET TO '1' WHEN YOU REQUEST TO BOOT FROM TSOP. THIS PREVENTS THE CPLD FROM DRIVING D0.
141
141
-- D0LEVEL is inverted and connected to the D0 output pad. This allows the CPLD to latch/release the D0/LFRAME signal.
142
142
SIGNAL TSOPBOOT : STD_LOGIC := '0' ;
143
143
SIGNAL D0LEVEL : STD_LOGIC := '0' ;
144
-
144
+
145
145
-- GENERIC COUNTER USED TO TRACK ADDRESS AND SYNC COUNTERS.
146
146
SIGNAL COUNT : INTEGER RANGE 0 TO 7 ;
147
147
@@ -165,12 +165,12 @@ BEGIN
165
165
"1111" WHEN LPC_CURRENT_STATE = TAR2 ELSE
166
166
"1111" WHEN LPC_CURRENT_STATE = TAR_EXIT ELSE
167
167
READBUFFER(3 DOWNTO 0 ) WHEN LPC_CURRENT_STATE = READ_DATA0 ELSE -- This has to be lower nibble first!
168
- READBUFFER(7 DOWNTO 4 ) WHEN LPC_CURRENT_STATE = READ_DATA1 ELSE
168
+ READBUFFER(7 DOWNTO 4 ) WHEN LPC_CURRENT_STATE = READ_DATA1 ELSE
169
169
"ZZZZ" ;
170
170
171
171
-- FLASH_DQ is mapped to the data byte sent by the Xbox in MEM_WRITE mode, else its just an input
172
172
FLASH_DQ <= sFLASH_DQ WHEN CYCLE_TYPE = MEM_WRITE ELSE "ZZZZZZZZ" ;
173
-
173
+
174
174
-- Write Enable for Flash Memory Write (Active low)
175
175
-- Minimum pulse width 90ns.
176
176
-- Address is latched on the falling edge of WE.
@@ -200,8 +200,8 @@ BEGIN
200
200
XENIUM_D0 <= '0' WHEN TSOPBOOT = '1' ELSE
201
201
'1' WHEN CYCLE_TYPE = MEM_READ ELSE
202
202
'1' WHEN CYCLE_TYPE = MEM_WRITE ELSE
203
- NOT D0LEVEL;
204
-
203
+ NOT D0LEVEL;
204
+
205
205
REG_00EF_READ <= XENIUM_RECOVERY & '0' & HEADER_4 & HEADER_1 & REG_00EF_WRITE(3 DOWNTO 0 );
206
206
207
207
PROCESS (LPC_CLK, LPC_RST, TSOPBOOT) BEGIN
@@ -212,16 +212,16 @@ PROCESS (LPC_CLK, LPC_RST, TSOPBOOT) BEGIN
212
212
D0LEVEL <= TSOPBOOT;
213
213
LPC_CURRENT_STATE <= WAIT_START;
214
214
215
- ELSIF (rising_edge (LPC_CLK)) THEN
215
+ ELSIF (rising_edge (LPC_CLK)) THEN
216
216
CASE LPC_CURRENT_STATE IS
217
- WHEN WAIT_START =>
217
+ WHEN WAIT_START =>
218
218
IF LPC_LAD = "0000" AND TSOPBOOT = '0' THEN
219
219
LPC_CURRENT_STATE <= CYCTYPE_DIR;
220
220
END IF ;
221
- WHEN CYCTYPE_DIR =>
222
-
221
+ WHEN CYCTYPE_DIR =>
222
+
223
223
LPC_CURRENT_STATE <= ADDRESS;
224
-
224
+
225
225
IF LPC_LAD(3 DOWNTO 1 ) = "000" THEN
226
226
CYCLE_TYPE <= IO_READ;
227
227
COUNT <= 3 ;
@@ -237,9 +237,9 @@ PROCESS (LPC_CLK, LPC_RST, TSOPBOOT) BEGIN
237
237
ELSE
238
238
LPC_CURRENT_STATE <= WAIT_START; -- Unsupported, reset state machine.
239
239
END IF ;
240
-
240
+
241
241
-- ADDRESS GATHERING
242
- WHEN ADDRESS =>
242
+ WHEN ADDRESS =>
243
243
244
244
IF COUNT = 5 THEN
245
245
LPC_ADDRESS(20 ) <= LPC_LAD(0 );
@@ -251,77 +251,77 @@ PROCESS (LPC_CLK, LPC_RST, TSOPBOOT) BEGIN
251
251
REG_00EF_WRITE(3 DOWNTO 0 ) <= "1010" ;
252
252
END IF ;
253
253
CASE REG_00EF_WRITE(3 DOWNTO 0 ) IS
254
- WHEN "0001" =>
254
+ WHEN "0001" =>
255
255
LPC_ADDRESS(20 DOWNTO 18 ) <= "110" ; -- 256kb bank
256
- WHEN "0010" =>
256
+ WHEN "0010" =>
257
257
LPC_ADDRESS(20 DOWNTO 19 ) <= "10" ; -- 512kb bank
258
- WHEN "0011" =>
258
+ WHEN "0011" =>
259
259
LPC_ADDRESS(20 DOWNTO 18 ) <= "000" ; -- 256kb bank
260
- WHEN "0100" =>
260
+ WHEN "0100" =>
261
261
LPC_ADDRESS(20 DOWNTO 18 ) <= "001" ; -- 256kb bank
262
- WHEN "0101" =>
262
+ WHEN "0101" =>
263
263
LPC_ADDRESS(20 DOWNTO 18 ) <= "010" ; -- 256kb bank
264
- WHEN "0110" =>
264
+ WHEN "0110" =>
265
265
LPC_ADDRESS(20 DOWNTO 18 ) <= "011" ; -- 256kb bank
266
- WHEN "0111" =>
266
+ WHEN "0111" =>
267
267
LPC_ADDRESS(20 DOWNTO 19 ) <= "00" ; -- 512kb bank
268
- WHEN "1000" =>
268
+ WHEN "1000" =>
269
269
LPC_ADDRESS(20 DOWNTO 19 ) <= "01" ; -- 512kb bank
270
- WHEN "1001" =>
270
+ WHEN "1001" =>
271
271
LPC_ADDRESS(20 ) <= '0' ; -- 1mb bank
272
- WHEN "1010" =>
272
+ WHEN "1010" =>
273
273
LPC_ADDRESS(20 DOWNTO 18 ) <= "111" ; -- 256kb bank
274
- WHEN "0000" =>
274
+ WHEN "0000" =>
275
275
-- Bank zero will disable modchip and release D0 and reset state machine.
276
276
LPC_CURRENT_STATE <= WAIT_START;
277
277
TSOPBOOT <= '1' ;
278
- WHEN OTHERS =>
278
+ WHEN OTHERS =>
279
279
END CASE ;
280
280
ELSIF COUNT = 3 THEN
281
- LPC_ADDRESS(15 DOWNTO 12 ) <= LPC_LAD;
281
+ LPC_ADDRESS(15 DOWNTO 12 ) <= LPC_LAD;
282
282
ELSIF COUNT = 2 THEN
283
283
LPC_ADDRESS(11 DOWNTO 8 ) <= LPC_LAD;
284
284
ELSIF COUNT = 1 THEN
285
285
LPC_ADDRESS(7 DOWNTO 4 ) <= LPC_LAD;
286
286
ELSIF COUNT = 0 THEN
287
287
LPC_ADDRESS(3 DOWNTO 0 ) <= LPC_LAD;
288
-
288
+
289
289
LPC_CURRENT_STATE <= WAIT_START;
290
-
290
+
291
291
-- catch unsupported IO read/writes here before they modify LAD
292
292
IF CYCLE_TYPE = MEM_READ THEN
293
293
LPC_CURRENT_STATE <= TAR1;
294
294
ELSIF CYCLE_TYPE = MEM_WRITE THEN
295
295
LPC_CURRENT_STATE <= WRITE_DATA;
296
296
ELSIF LPC_ADDRESS(7 DOWNTO 1 ) = x"77" THEN -- check if supported Xenium register (EE or EF), the last bit is irrelevant
297
-
297
+
298
298
IF CYCLE_TYPE = IO_READ THEN
299
299
LPC_CURRENT_STATE <= TAR1;
300
300
ELSIF CYCLE_TYPE = IO_WRITE THEN
301
301
LPC_CURRENT_STATE <= WRITE_DATA;
302
302
END IF ;
303
303
304
304
END IF ;
305
-
305
+
306
306
END IF ;
307
307
COUNT <= COUNT - 1 ;
308
-
308
+
309
309
-- MEMORY OR IO WRITES. These all happen lower nibble first. (Refer to Intel LPC spec)
310
310
-- HACK: abuses counter rollover from previous state
311
- WHEN WRITE_DATA =>
312
-
311
+ WHEN WRITE_DATA =>
312
+
313
313
IF CYCLE_TYPE = MEM_WRITE THEN
314
-
314
+
315
315
IF COUNT = 7 THEN
316
316
sFLASH_DQ(3 DOWNTO 0 ) <= LPC_LAD;
317
317
ELSE
318
318
sFLASH_DQ(7 DOWNTO 4 ) <= LPC_LAD;
319
319
END IF ;
320
-
320
+
321
321
ELSE
322
322
323
323
-- it's already been confirmed this is a supported Xenium register in a previous state
324
- -- so only a single bit needs to be checked to differentiate between the two
324
+ -- so only a single bit needs to be checked to differentiate between the two
325
325
IF LPC_ADDRESS(0 ) = '0' THEN
326
326
327
327
IF COUNT = 7 THEN
@@ -339,37 +339,37 @@ PROCESS (LPC_CLK, LPC_RST, TSOPBOOT) BEGIN
339
339
END IF ;
340
340
341
341
END IF ;
342
-
342
+
343
343
IF COUNT = 6 THEN
344
344
LPC_CURRENT_STATE <= TAR1;
345
345
END IF ;
346
- COUNT <= COUNT - 1 ;
346
+ COUNT <= COUNT - 1 ;
347
347
348
348
-- MEMORY OR IO READS
349
- WHEN READ_DATA0 =>
349
+ WHEN READ_DATA0 =>
350
350
LPC_CURRENT_STATE <= READ_DATA1;
351
- WHEN READ_DATA1 =>
352
- LPC_CURRENT_STATE <= TAR_EXIT;
351
+ WHEN READ_DATA1 =>
352
+ LPC_CURRENT_STATE <= TAR_EXIT;
353
353
354
354
-- TURN BUS AROUND (HOST TO PERIPHERAL)
355
- WHEN TAR1 =>
355
+ WHEN TAR1 =>
356
356
LPC_CURRENT_STATE <= TAR2;
357
- WHEN TAR2 =>
357
+ WHEN TAR2 =>
358
358
LPC_CURRENT_STATE <= SYNCING;
359
359
COUNT <= 6 ;
360
-
360
+
361
361
-- SYNCING STAGE
362
362
WHEN SYNCING =>
363
- COUNT <= COUNT - 1 ;
363
+ COUNT <= COUNT - 1 ;
364
364
-- Buffer IO reads during syncing. Helps output timings
365
365
IF COUNT = 1 THEN
366
366
IF CYCLE_TYPE = MEM_READ THEN
367
367
READBUFFER <= FLASH_DQ;
368
-
368
+
369
369
ELSIF CYCLE_TYPE = IO_READ THEN
370
-
370
+
371
371
-- it's already been confirmed this is a supported Xenium register in a previous state
372
- -- so only a single bit needs to be checked to differentiate between the two
372
+ -- so only a single bit needs to be checked to differentiate between the two
373
373
IF LPC_ADDRESS(0 ) = '0' THEN
374
374
READBUFFER <= REG_00EE_READ;
375
375
ELSE
@@ -379,22 +379,22 @@ PROCESS (LPC_CLK, LPC_RST, TSOPBOOT) BEGIN
379
379
ELSIF COUNT = 0 THEN
380
380
LPC_CURRENT_STATE <= SYNC_COMPLETE;
381
381
END IF ;
382
- WHEN SYNC_COMPLETE =>
382
+ WHEN SYNC_COMPLETE =>
383
383
IF CYCLE_TYPE = MEM_READ OR CYCLE_TYPE = IO_READ THEN
384
384
LPC_CURRENT_STATE <= READ_DATA0;
385
385
ELSE
386
386
LPC_CURRENT_STATE <= TAR_EXIT;
387
387
END IF ;
388
-
388
+
389
389
-- TURN BUS AROUND (PERIPHERAL TO HOST)
390
- WHEN TAR_EXIT =>
390
+ WHEN TAR_EXIT =>
391
391
-- D0 is held low until a few memory reads
392
392
-- This ensures it is booting from the modchip. Genuine Xenium arbitrarily
393
393
-- releases after the 5th read. This is always address 0x74
394
394
IF LPC_ADDRESS(7 DOWNTO 0 ) = x"74" THEN
395
395
D0LEVEL <= '1' ;
396
396
END IF ;
397
-
397
+
398
398
CYCLE_TYPE <= IO_READ;
399
399
LPC_CURRENT_STATE <= WAIT_START;
400
400
END CASE ;
0 commit comments