The famicom needed much more interest, its bottom is smooth (right), not like most (left) of the famicoms I met before.
//shell-bottom.jpg
The PCB also has traces on both sides, not obscured by the soldermask like I always spotted.
//pcb-top.jpg
But to my surprise, it has problems in playing many pirate famiclone cartridges. LIke this Doki MMC3 Doki Yuuenchi cartridge that shakes or does IRQ split scroll not when it is needed. It turns out the software is not a culprit as thie same game played in this console on my KrzysioCart flashcart works fine. It passes CPU-RAM and PPU-RAM tests, also games like BattleToads works just fine.
//doki_doki_bad.jpg
//doki_doki_bad.gif Looks like the RP2A03 revisionless CPU is causing some troubles. Its M2 duty cycle is 76.34% (19/24) and that probably fools the cartridge scanline detector.
//clk.png
It has also troubles running Everdrive
//ed-bad.jpg
I would replace the CPU with another NTSC model but I dont have any of them so I figured out why not to replace it with UA6527P (dendy CPU) multiply the crystal frequency that is fed to CPU with 16/12 = 4/3 = 1.33.
I already did similar approach using 100MHz crystal and CPLD to create edges of 33ns clock cycles that are in sync with 21.7M .
viewtopic.php?p=299076&hilit=ua6527p#p299076
Disadvantages are:
- requirement of two crystals (100MHz + 21.7MHz)
- Clock is generated using 74HCU04 that requires a few resistors/capacitors
- output clock have jitter
One of the users (borishim) suggested using ICS501 as a cheap frequency multiplier so I bought few of them and now it was good moment to test them.
Advantages are:
+ only single 21.7MHz crystal is required
+ no extra resistors/capacitors
+ output clock does not have any jitter
So I designed a small PCB with that chip + EPM3064 that divides that frequency by two different factors, one is fed to CPU and the other to PPU:
//proj-sch.png
//proj-pcb.png
//proj-pcb-soldered.jpg
In fact, this CPLD can be selected by one of its pin to be used with either old UA6527P (16div) or the other with new UA6527P (15div).
Code: Select all
+-------------------+
----------------------------->|mode | +----+--+--|---------------+------------+-------------------+
+---------------+ | | |mode|S1|S0| cpu_clk_out | ppu_clk_in | note |
| S1|<-<| | +----+--+--+---------------+------------+-------------------+
| S0|<-<| cpu_clk_out| |0 | 0| 1|clk_in * 5 / 4 | clk_in / 5 |new-UA6527P (15div)|
-21.477M->|clk_in clk_out|>->|clk_in ppu_clk_Out| |1 | 0| 0|clk_in * 4 / 3 | clk_in / 4 |old-UA6527P (16div)|
+---------------+ +-------------------+ +----+--+--+---------------+------------+-------------------|
ICS502 EPM3064
Code: Select all
+-------------------------------------------------------+-------------------------------------------------------+
| CLOCK DIVISION BY 3 | CLOCK DIVISION BY 5 |
+-------------------------------------------------------+-------------------------------------------------------+
| clk_in ___---___---___---___---___---___---___---___ | clk_in ___---___---___---___---___---___---___---___ |
| pos_cnt 000111111222222000000111111222222000000111111 | pos_cnt 000111111222222333333444444000000111111222222 |
| neg_cnt 000000111111222222000000111111222222000000111 | neg_cnt 000000111111222222333333444444000000111111222 |
| clk_out ---------_________---------_________--------- | clk_out ---------_______________---------------______ |
| | |
| if rising_edge(clk_in) then | if rising_edge(clk_in) then |
| if pos_cnt /= 2 then | if pos_cnt /= 4 then |
| pos_cnt <= pos_cnt + 1; | pos_cnt <= pos_cnt + 1; |
| else | else |
| pos_cnt <= "00"; | pos_cnt <= "000"; |
| end if; | end if; |
| end if; | end if; |
| | |
| if falling_edge(clk_in) then | if falling_edge(clk_in) then |
| if neg_cnt /= 2 then | if neg_cnt /= 4 then |
| neg_cnt <= neg_cnt + 1; | neg_cnt <= neg_cnt + 1; |
| else | else |
| neg_cnt <= "00"; | neg_cnt <= "000"; |
| end if; | end if; |
| end if; | end if; |
| | |
| clk_out <= | clk_out <= |
| '0' when pos_cnt = "10" or neg_cnt = "10" else | '0' when pos_cnt = "010" or pos_cnt = "011" or |
| '1'; | neg_cnt = "010" or neg_cnt = "011" else |
| | '1'; |
+-------------------------------------------------------+-------------------------------------------------------+
Code: Select all
+-------------------------------------------------------+-------------------------------------------------------+
| CLOCK DIVISION BY 2 | CLOCK DIVISION BY 4 |
+-------------------------------------------------------+-------------------------------------------------------+
| clk_in ___---___---___---___---___---___---___---___ | clk_in ___---___---___---___---___---___---___---___ |
| pos_cnt 000111111000000111111000000111111000000111111 | pos_cnt 000111111222222333333000000111111222222333333 |
| neg_cnt 000000111111000000111111000000111111000000111 | neg_cnt 000000111111222222333333000000111111222222333 |
| clk_out ___------______------______------______------ | clk_out ___------------____________------------______ |
| | |
| if rising_edge(clk_in) then | if rising_edge(clk_in) then |
| if pos_cnt /= 1 then | if pos_cnt /= 3 then |
| pos_cnt <= pos_cnt + 1; | pos_cnt <= pos_cnt + 1; |
| else | else |
| pos_cnt <= "0"; | pos_cnt <= "00"; |
| end if; | end if; |
| end if; | end if; |
| | |
| if falling_edge(clk_in) then | if falling_edge(clk_in) then |
| if neg_cnt /= 1 then | if neg_cnt /= 3 then |
| neg_cnt <= neg_cnt + 1; | neg_cnt <= neg_cnt + 1; |
| else | else |
| neg_cnt <= "0"; | neg_cnt <= "00"; |
| end if; | end if; |
| end if; | end if; |
| | |
| clk_out <= | clk_out <= |
| '0' when pos_cnt = "0" else | '0' when pos_cnt = "00" or neg_cnt = "11" else |
| '1'; | '1'; |
| | |
+-------------------------------------------------------+-------------------------------------------------------+
//final.jpg
My website:
My NES/FC flashcart: