Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

Ads

#26 2019-10-07 17:46:15

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Initially, I was using an Atmel CPLD, atf1504asl. I think something was wrong with either the hardware or the software (WinCUPL), because some of the pins on that Atmel dev board just never seemed to work. I finally caved and bought the Xilinx Platform Cable 2 so I could use their software. It's been much better since.

Without any of the RTC code, I'm using 30 macrocells. I'm trying out the XC9572XL to see if I can pull this off with only 72 cells, if not I can upgrade to the 96-cell device. I like how this device family has 5v tolerant IO, and runs at 3v. This circuit was going to have to generate 3v anyway for my Flash and FRAM, so it works out.

I was originally looking at the XC2C128 to hold both the MBC logic and the RTC all on one device, but I'm afraid it will still drain the backup battery too fast. I think Xilinx Power Analyzer estimated about 19uA, including the CoolClock feature. I think it will also require another regulator to supply 1.8v? Also some way to switch to backup power...

Basically, device selection has been a 3-way tug of war between board space, power draw, and voltage requirements.

*EDIT: The 5v IO isn't going to be important in the end, but it's very useful for prototyping, since my flash chip and FRAM are both 5v parts.

Last edited by WeaselBomb (2019-10-07 17:58:31)

Offline

 

#27 2019-10-09 22:13:53

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

So, getting back to the RTC chip, the DS1501 really caught my eye, and the DS1511 variant includes an integrated battery and crystal in a DIP package, so I picked one up for easy prototyping.

I didn't notice this before, but powering it at 5v instead of 3v decreases the read/write cycle time from 120ns down to 70. That's quite a drop, and may be important later on.

Reading the seconds, minutes, and hours will be the easy part. The CPU is expecting these values in binary format, so a simple conversion from BCD to binary is all that's needed.
The real problem comes from the day counter. There are 10 bits that represent the day counter, with the lower 8 bits in one register, a 9th bit and a carry bit in another register. The CPU is once again expecting these in binary, but the RTC chip stores things very differently, using year, month, and date registers, all in BCD.

Plan A:
Any time the CPU wants to read either of the day counter registers, quickly read the year, month, and date registers on the RTC chip, convert them to days and add them together. To pull this off, I'm thinking it will require an oscillator clocked high enough to read multiple registers in one cycle.

Plan B:
Read the RTC data into registers on the CPLD during the Gameboy's bootup. This RTC chip can output a 32.768KHz pulse, so that could be used to keep time during gameplay. The challenge would then be handling writes to the RTC registers, since I would have to write to both the CPLD registers AND the RTC registers.

Right now, I'm not sure which option is going to be easier.

*EDIT:
After checking in Xilinx ISE, it says that the current design, without any RTC, is using 27 macrocells. If I wanted to copy the RTC data onto the CPLD, and have latch registers, I would need 61 spare macrocells, which is way over capacity for this chip.
For now, I've ordered some oscillators at 4, 5, and 6 MHz. I will use these to try and implement plan A. If that fails, I can try out a bigger CPLD.

Last edited by WeaselBomb (2019-10-10 21:26:27)

Offline

 

#28 2019-10-14 16:44:37

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

Keep going WeaselBomb, it really seems like you're gaining quite a lot experience big_smile

Too bad your original plan won't work out. Was power your only concern to remove implementing the RTC directly on the CPLD?
How did you arrive at 61 macrocells? I get 6 bit (seconds) + 6 bit (minutes) + 5 bit (hours) + 10 bit (days + carry) = 27 bits, so the rest is all routing and logic?

Offline

 

#29 2019-10-14 17:46:02

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

I may not have this correct, but my 61 cells came from:

28 cells for the RTC (I was including the halt flag)
28 cells for the RTC latch registers
4 cells to divide the 32.768KHz frequency into 1-second intervals
1 cell for the 'latch signal' (when set, latch the RTC data into the latch registers)

I guess I wouldn't have to latch the halt flag, now that I think about it.
As for dividing the 32.768 KHz frequency, I would use a 4-bit counter to increment the seconds register every time the counter hit 15. (32,768 = 2^15). I'm assuming this is how the MBC3 did it?

Tauwasser wrote:

Was power your only concern to remove implementing the RTC directly on the CPLD?

Yes, I seemed to run into lots of problems with keeping everything on the CPLD. I would prefer to do it that way, since it would be on a single chip, like the MBC3. The lowest power option I could find was the CoolRunner-II family, but even then I didn't think I could get a good battery life from those devices. If I could find a good 3v CPLD that can run from a backup battery for at least a few years, that would be perfect.

Last edited by WeaselBomb (2019-10-15 09:57:36)

Offline

 

#30 2019-10-15 21:15:12

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Oscillators are here, but I think my VHDL skills might need some work to make this happen. I could easily do it if everything were contained on the CPLD, but I haven't found a combination of parts that will allow me to do that. Maybe an FPGA could get better power consumption? I haven't every looked into those.

I'm working with the DS1501 RTC chip. I can access every register that I need with 4 address lines (0x00 through 0x0F). There are some extra RAM registers beyond that, but they use Indirect Addressing, so I'm not sure how useful those will be (it takes 2 clock cycles to access a register using indirect addressing, instead of the usual 1 cycle with direct addressing).

The DS1501 has 2 control registers, A and B. The states of these registers are unknown after initial power-on. I'm thinking it would be best to set both of these registers after every boot-up? These registers are at addresses 0x0E and 0x0F, respectively.

Code:

REGISTER MAP
Register     Description

0x00          Seconds
0x01          Minutes
0x02          Hours
0x03          DayOfWeek (1-7)
0x04          Date (1-31)
0x05          Month (1-12), Oscillator On/Off
0x06          Year
0x07          Century
...              ...
0x0E          Control A
0x0F          Control B

I will need a dedicated data bus to read/write data from/to the RTC. It can't share the same data bus as everything else, since it will need to be converted by the CPLD before it is read by the CPU (we can't have the RTC and the CPLD trying to output on the data bus at the same time!).

For control signals, I will also need to generate Write Enable (WE), Output Enable (OE) and Chip Select (CS) signals to read and write the RTC. Last, I have another clock signal, generated by my new oscillator, that will be used to "drive" the RTC register reads/writes.

The RTC has 2 sets of RTC registers, only one is accessible. I think of these like the "latch registers" on the MBC3.
The Most Significant Bit (MSB) in Control B is the Transfer Enable (TE). Clearing this bit "freezes" or "latches" the RTC registers, allowing us to read them safely, without worrying about them incrementing mid-read. Setting this bit "unfreezes" the RTC registers, and they resume incrementing once per second.

*EDIT:
If I wanted to do everything on the CPLD, I would need a very low power device, since it would need to run from a coin battery. The CoolRunner 2 is the best one I've found so far. Even then, the datasheet says its quiescent current can go as low as 12 microamps. So, that means there's no way to go below that current, right? With my CR2025 at 170 mAh, that would completely drain the battery after 14,167 hours, or 1.6 years. Ideally, I'd like it to last at least 5 years. I just don't know if that's possible on a CPLD.

Last edited by WeaselBomb (2019-10-17 17:52:57)

Offline

 

#31 2019-10-19 00:03:23

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

So, starting to learn a bit more about VHDL. Still extremely new, so if you cringe at my code, I understand. On the bright side, it's all subject to change as I learn more. So for starters...

I've made a counter variable, RtcSetupCounter, that I will use to initialize both of the Control Registers. Basically,
-if RtcSetupCounter = 2, write Register A.
-if RtcSetupCounter = 1, write Register B.

Code:

signal RtcSetupCounter        : std_logic_vector(1 downto 0) := "10";

I'm thinking 3 things will influence the Address Bus for the RTC:
-The value of the RtcSetupCounter
-The RtcLatch signal
-The RamBankReg value

The RtcLatch signal goes high when the Gameboy tries to latch the RTC data:

Code:

SetRtcLatch : process(RESET, RtcLatchClk)
begin
    if(RESET = '0') then
        RtcLatch <= '0';
    elsif(rising_edge(RtcLatchClk)) then
        RtcLatch <= DATA(0);
    end if;
end process SetRtcLatch;

Lastly, the RamBankReg is important because the RTC is only accessed when the Gameboy tries to read from 0xA000-0xBFFF and the selected Ram Bank Register is greater than 0x07. According to the wiki, the Ram Bank Register maps to the RTC registers as follows:

Code:

0x08 = Seconds
0x09 = Minutes
0x0A = Hours
0x0B = Lower 8 bits of Day Counter
0x0C = Upper Day Counter bits + Halt Flag

So, I need the RTC address bus to change depending on the states of those 3 things (RtcSetupCounter value, Latch signal value, Ram Bank Register value). I'm thinking the RtcSetupCounter should somehow take priority over the others, since it always needs to be done first, and only needs to be done once.

Last edited by WeaselBomb (2019-10-19 00:11:53)

Offline

 

#32 2019-10-20 23:33:50

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

I've been studying a little VHDL, but I'm definitely out of my comfort zone here. I don't have any solid progress to report unfortunately, just some musings about how I might approach reading and writing the RTC.

Accessing the seconds, minutes, and hours registers isn't going to be problematic. I can access those and convert to binary in one cycle easily.

Getting the day counter in the correct format will be the main challenge. I'll need to access the Date, Month, and Year registers together, all in one CPU cycle, calculate the total number of days, and convert that to binary.
For the lower 8 bits, I'm thinking just assigning the total number of days to that register will work (I'm not sure how VHDL handles overflows yet). For the 9th bit, I will need to see if the day counter is over 255. For the carry bit, I need to see if it is over 510. The halt flag will actually come from the month register (this RTC chip has an oscillator enable bit located in the Month register).

Control Registers A and B on the RTC chip will need to be set on every startup, since their values aren't "valid" when applying power for the first time. I think it's best to just set them every time.

To latch the RTC, I just have to toggle bit 7 of Control Register B (called the "transfer enable" bit in the datasheet). At first, I was confused as to how I could set this bit without affecting the other 7 bits, but I think it can be done by tri-stating the other data lines?

I wonder if this can be done with a state machine? Just spitballing, but I'm picturing these states:
-doNothing
-readDate
-readMonth
-readYear
-writeControlA
-writeControlB

On startup, I could default to state 'writeControlA', which would always move to 'writeControlB', then 'doNothing'.
If I am in state 'doNothing' and the CPU tries to access either of the day registers, I could move to 'readDate', then 'readMonth', 'readYear', and finally return to 'doNothing'. I would accumulate the day count on every state change.

Here's an incomplete draft of this idea, I'll update when I figure out more. Basically, states are enumerated from 0-5, and the state starts at 4 on startup, which should initialize both control registers.

Code:

type state_type (DoNothing, Latch, DayOfMonth, Month, Year, CtrlA, CtrlB);
signal state, nextState : state_type;

test : process(state)
begin
    case (state) is
        when DoNothing =>
            RTC_ADDR <= "0000";

                when Latch =>
                        RTC_ADDR <= "1111";
                        nextState <= DoNothing;

        when DayOfMonth =>
            RTC_ADDR <= "0100";
            nextState <= Month; --month reg next

        when Month =>
            RTC_ADDR <= "0101";
            nextState <= Year;

        when Year => --Year register
            RTC_ADDR <= "0110";
            nextState <= DoNothing;

        when CtrlA =>
            RTC_ADDR <= "1110";
            nextState <= CtrlB;

        when CtrlB =>
            RTC_ADDR <= "1111";
            nextState <= DoNothing;

        when others =>
            -- shouldn't ever reach this state
            RTC_ADDR <= "0000";
            nextState <= DoNothing;

    end case;
end process test;

Last edited by WeaselBomb (2019-10-21 17:49:14)

Offline

 

#33 2019-10-21 19:51:07

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

I don't think you need to initialize the RTC control registers on every boot, just once for initial configuration.

Calculating the day will be tricky, as you would need to account for different lengths of each month and leap years as well. I'm not sure your CPLD can handle that -- much less in a single clock cycle.
You might want to consider a simple hack using a kind of bootstrap RTC code that would run before each game and sets the date to December 31st, so a day rollover would increment the year counter. Then you could directly map the year registers with semi-minimal effort. Of course that would only work if the GameBoy isn't continuously running for a day.

The DS1501 is a relatively expensive part. I think you chose it because of its parallel address and data bus, correct?

Offline

 

#34 2019-10-22 00:29:08

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Tauwasser wrote:

I don't think you need to initialize the RTC control registers on every boot, just once for initial configuration.

I agree, it would be better to only initialize once. The only problem is I'm not sure how to detect if it has been previously initialized?

Tauwasser wrote:

The DS1501 is a relatively expensive part. I think you chose it because of its parallel address and data bus, correct?

Yes, this part is pretty pricey for what it is. I'm using it for now because it had several useful features for prototyping, like an integrated crystal and battery, plus the ability to output a 32.768 KHz frequency signal. In production, I would definitely go for a cheaper part.

Offline

 

#35 2019-10-22 15:47:48

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

WeaselBomb wrote:

I agree, it would be better to only initialize once. The only problem is I'm not sure how to detect if it has been previously initialized?

I had thought about that, too! I would personally test the internal SRAM and write a unique string to it. Of course, you'd need to implement a special by-pass in terms of addressing the SRAM for that to work.

WeaselBomb wrote:

Yes, this part is pretty pricey for what it is. I'm using it for now because it had several useful features for prototyping, like an integrated crystal and battery, plus the ability to output a 32.768 KHz frequency signal. In production, I would definitely go for a cheaper part.

Well, if that is so, maybe you'd want to check out some MCUs with integrated RTC. Many can run at <5 MHz and consume only a few mA of power in active and idle in single-digit µA. You'd need to periodically wake up to save the time and of course you'd need some kind of battery switch-over from 5V to backup battery. It's just a thought, I haven't done the math yet if that's actually viable.

Offline

 

#36 2019-10-23 14:30:24

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

I'm thinking this idea isn't going to work either. The timing is just too tight. This RTC chip has an access time of 70 - 120 ns, depending on VCC. By the time I figure out what register I need to access, AND wait for the required access time, there isn't enough time left to read 3 registers and load data on the bus. I guess I need to be able to read the day counter registers in single reads.
Maybe FPGAs can do what I need? Maybe I should re-consider a larger CPLD? I would love the ability to power down all logic EXCEPT the RTC logic, to save power when running from a backup battery. A device with a dedicated battery input pin would be even better.

At this point, I'm out of ideas and I'm not sure if I will come up with any more. I'm really not satisfied with leaving RTC unfinished, but I really don't know what to do about it.

Offline

 

#37 2019-11-05 09:48:16

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Well I had another idea for the RTC chip, but in the end it didn't really work out.

I've decided that since I'm only powering 32 macrocells from the backup battery, I'm just going to try out a CPLD and see what the power consumption is like. No complicated formulas, just a simple reading with a multimeter.
I don't think I can fit everything on 64 macrocells, so I'll probably have to look at 128 (unless there's something in between, like 96). Lattice's ispMach4000 series looks good concerning power consumption, so I think I will start with that device family. Now, I just want to write plain, simple MBC3 code.

What I'm getting hung up on is latching the RTC. I understand what the wiki says:

Code:

6000-7FFF - Latch Clock Data (Write Only)
When writing 00h, and then 01h to this register, the current time becomes latched into the RTC registers. 
The latched data will not change until it becomes latched again, by repeating the write 00h->01h procedure. 
This is supposed for <reading> from the RTC registers. 
This can be proven by reading the latched (frozen) time from the RTC registers, and then unlatch the registers to show the clock itself continues to tick in background.

From this information, I made a register, RtcLatch, and a signal, RtcLatchClk:

Code:

RtcLatchClk <= '0' when (ADDR(15 downto 13) = "011" and WR = '0') else '1';

LatchRtc : process(RtcLatchClk)
begin
     if(rising_edge(RtcLatchClk)) then
          RtcLatch <= DATA(0);
     end if;
end process LatchRtc;

So, on the rising edge of RtcLatch, the RTC registers should be latched into the 'shadow' registers. Sounds easy enough, but isn't it possible to latch while the RTC is in the process of incrementing? This would cause the wrong data to be latched. I'm not sure how to guarantee that the data gets latched correctly. Is this what the CLK signal is used for on the MBC3, maybe? I noticed it's the only MBC to use that signal...

Last edited by WeaselBomb (2019-11-05 09:53:23)

Offline

 

#38 2019-11-05 16:13:39

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

Yep, you're correct. The registers on the gameboy side and the RTC side are buffered and clock domain crossing is performed using the PHI/CLK pin on the Game Edge Connector. That's why latching the clock and reading from it is supposed to be spaced out by some clock cycles in code.

Offline

 

#39 2019-11-05 23:59:49

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Oof that sounds complicated! I've been trying to wrap my mind around this all day!
I did however find a fantastic article on this issue for anyone interested:
https://filebox.ece.vt.edu/~athanas/451 … l_cdc.html

So trying to sample the RTC registers during an increment is a violation of the setup & hold time of those flip flops? And this is what causes meta-stability? That's actually super interesting, I'll have to keep reading for a solution to this. I'm still not sure what role the PHI signal plays in all of this.

In the meantime, I've made the following registers/signals:

Code:

signal RtcCounter         : natural range 1 to 15;
signal RtcLatch             : std_logic;
signal RtcLatchClk           : std_logic;
signal RtcHalt             : std_logic;
        
signal RtcSecReg         : std_logic_vector(5 downto 0);
signal RtcMinReg         : std_logic_vector(5 downto 0);
signal RtcHourReg         : std_logic_vector(4 downto 0);
signal RtcDayReg         : std_logic_vector(8 downto 0);
signal RtcDayCarryReg    : std_logic;
        
signal RtcSecBuffer         : std_logic_vector(5 downto 0);
signal RtcMinBuffer         : std_logic_vector(5 downto 0);
signal RtcHourBuffer         : std_logic_vector(4 downto 0);
signal RtcDayBuffer         : std_logic_vector(8 downto 0);
signal RtcDayCarryBuffer : std_logic;

*RtcCounter will divide the 32.768KHz frequency (32,768 Hz / 2^15 = 1 Hz, or 1 second). Every time this hits 15, increment RtcSecReg.
*The buffer registers will hold the 'latched' RTC values
*RtcLatch will clock the Buffer registers (on the rising edge of RtcLatch, the RTC data will be sampled by the Buffer registers)

EDIT:
Wow this clock domain crossing is really confusing. I'm not really sure what I'm supposed to do.

Somebody may have to fact check me here...
I know that the RTC registers are clocked by a 1 Hz clock, which is derived from a 32.768 KHz clock. This is one clock domain (the 1 Hz and the 32 KHz clocks belong to the same domain, since one is derived from the other).
The latch registers are clocked by a combination of product terms (ADDR(15 downto 13), WR, RamBankReg), so I don't think they are clocked at a set frequency. This is the other clock domain.

Since the second clock domain doesn't use a set frequency, it isn't correct to say one is faster than the other. They are just asynchronous to each other, and have an unknown 'Clock Relationship' (or 'Phase Relationship'). I just know that I have to sample data in RtcClk's domain from RtcLatch's domain.

My gut tells me the solution is one of these:
-a handshake protocol between these 2 clock domains
-use the buffer register as a FIFO
-sample the RTC data multiple times until it matches twice in a row

Last edited by WeaselBomb (2019-11-08 12:28:25)

Offline

 

#40 2019-11-09 17:34:48

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Ok, I don't think using a synchronizer (handshake) to pass the RtcLatch signal across the clock domain would be wise here, since the 32.768 KHz clock is so much slower than the 1 MHz clock.
Each oscillation of the slow clock takes about 30.5 microseconds, whereas the fast clock takes about 1 microsecond. Passing the RtcLatch signal through a 2-flip-flop synchronizer would then require up to 61 microseconds, meaning we could potentially have to wait up to 61 cycles (at 1 MHz) to latch the clock data, which is way too slow.

Correct me if I'm wrong, but the FIFO idea doesn't work either, because it would also require synchronizing read/write signals, which would, once again, be too slow.

Sampling the data multiple times has me intrigued. I figure it might be possible to sample the RTC until 2 matching samples are read? Samples would be read on the rising edge of the 1 MHz clock. I think this is a common method for reading dedicated RTC chips, actually.
I made a flow chart to visualize the possible outcomes for this technique. The best case is labeled in green (2 cycles), and the worst case in red (4 cycles).
https://i.imgur.com/nzRsvENl.png

I'm curious if this approach could work. The idea is that within 4 cycles of the 1 MHz clock, there could only be 1 transition of the RTC data, at most.

Last edited by WeaselBomb (2019-11-09 19:59:50)

Offline

 

#41 2019-11-11 09:54:27

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Well, here's what I've come up with. When the latch signal is asserted, the RTC will be sampled on every clock until 2 consecutive samples of the RTC match.

Code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity MBCx_src is
    Port
    (
        CLK            : in std_logic;
        ADDR        : in std_logic_vector(15 downto 12);
        DATA            : inout std_logic_vector(7 downto 0);
        RD            : in std_logic;
        WR            : in std_logic;
        CS            : in std_logic;
        RAM_CS        : out std_logic;
        AA            : out std_logic_vector(16 downto 13);
        RA            : out std_logic_vector(22 downto 14);
        RESET        : in std_logic;
        RTC_CLK        : in std_logic
    );
end MBCx_src;

architecture Behavioral of MBCx_src is

        --Registers
        signal RamEnableReg    : std_logic_vector(3 downto 0);
        signal RomBankLoReg: std_logic_vector(7 downto 0);
        signal RomBankHiReg    : std_logic;
        signal RamBankReg    : std_logic_vector(3 downto 0);
        
        signal RamEnableClk    : std_logic;
        signal RomBankLoClk    : std_logic;
        signal RomBankHiClk    : std_logic;
        signal RamBankClk    : std_logic;
        
        signal RtcCounter    : std_logic_vector(3 downto 0);
        signal RtcHalt        : std_logic;

        signal RtcLatch        : std_logic;
        signal RtcReady        : std_logic;
        signal RtcLatchClk    : std_logic;
        signal RtcWriteClk    : std_logic;
        signal RtcSampleClk    : std_logic;
        
        signal RtcSecReg    : std_logic_vector(5 downto 0);        
        signal RtcMinReg    : std_logic_vector(5 downto 0);
        signal RtcHourReg    : std_logic_vector(4 downto 0);
        signal RtcDayLoReg    : std_logic_vector(7 downto 0);
        signal RtcDayHiReg    : std_logic_vector(1 downto 0);
        
        signal RtcSecBuffer    : std_logic_vector(5 downto 0);
        signal RtcMinBuffer    : std_logic_vector(5 downto 0);
        signal RtcHourBuffer    : std_logic_vector(4 downto 0);
        signal RtcDayLoBuffer    : std_logic_vector(7 downto 0);
        signal RtcDayHiBuffer    : std_logic_vector(1 downto 0);
        
        signal SecMatch    : std_logic;
        signal MinMatch    : std_logic;
        signal HourMatch    : std_logic;
        signal DayMatch    : std_logic;
        
begin

RAM_CS <=
    '0' when (CS = '0' and ADDR(14) = '0' and RamEnableReg = "1010" and CLK = '0')
    else '1';

RA(22) <= 
    '0' when (ADDR(14) = '0' or RESET = '0')
    else RomBankHiReg;
    
RA(21 downto 14) <= 
    "00000000" when (ADDR(14) = '0' or RESET = '0')
    else RomBankLoReg when (RomBankLoReg /= "00000000")
    else "00000001";
    
AA(16 downto 13) <= 
    RamBankReg;
    
RamEnableClk <=
    '0' when (ADDR(15 downto 13) = "000" and WR = '0')
    else '1';
    
RomBankLoClk <=
    '0' when (ADDR = "0010" and WR = '0')
    else '1';
    
RomBankHiClk <=
    '0' when (ADDR = "0011" and WR = '0')
    else '1';
    
RamBankClk <=
    '0' when (ADDR(15 downto 13) = "010" and WR = '0')
    else '1';

DATA <=
    ("00" & RtcSecBuffer) when (ADDR(15 downto 13) = "101" and RD = '0' and RamBankReg = x"8")
    else ("00" & RtcMinBuffer) when (ADDR(15 downto 13) = "101" and RD = '0' and RamBankReg = x"9")
    else ("000" & RtcHourBuffer) when (ADDR(15 downto 13) = "101" and RD = '0' and RamBankReg = x"A")
    else RtcDayLoBuffer when (ADDR(15 downto 13) = "101" and RD = '0' and RamBankReg = x"B")
    else (RtcDayHiBuffer(1) & RtcHalt & "00000" & RtcDayHiBuffer(0)) when (ADDR(15 downto 13) = "101" and RD = '0' and RamBankReg = x"C")
    else "ZZZZZZZZ"
    ;

RtcLatchClk <= 
    '0' when (ADDR(15 downto 13) = "011" and WR = '0')
    else '1';
    
RtcWriteClk <=
    '0' when (ADDR(15 downto 13) = "101" and RamBankReg > x"7" and WR = '0') or (RtcCounter = "1111" AND RtcHalt = '0')
    else '1';
    
RtcSampleClk <=
    '0' when (RtcLatch = '0' or (RtcReady = '0' and CLK = '0'))
    else '1';
    
SecMatch <=
    '1' when (RtcSecReg = RtcSecBuffer)
    else '0';

MinMatch <=
    '1' when (RtcMinReg = RtcMinBuffer)
    else '0';
    
HourMatch <=
    '1' when (RtcHourReg = RtcHourBuffer)
    else '0';
    
DayMatch <=
    '1' when (RtcDayLoReg = RtcDayLoBuffer and RtcDayHiReg = RtcDayHiBuffer)
    else '0';

--Register Functions
ReadRtc : process(RtcSampleClk)
begin
    if(rising_edge(RtcSampleClk)) then
        if(SecMatch = '1' and MinMatch = '1' and HourMatch = '1' and DayMatch = '1') then
            RtcReady <= '1';
        else
            RtcSecBuffer <= RtcSecReg;
            RtcMinBuffer <= RtcMinReg;
            RtcHourBuffer <= RtcHourReg;
            RtcDayLoBuffer <= RtcDayLoReg;
            RtcDayHiBuffer <= RtcDayHiReg;
        end if;
    end if;
end process ReadRtc;

LatchRtc : process(RtcLatchClk)
begin
    if(rising_edge(RtcLatchClk)) then
        RtcLatch <= DATA(0);
    end if;
end process LatchRtc;

RtcClk : process(RtcHalt, RTC_CLK)
begin
    if(RtcHalt = '1') then
        RtcCounter <= "0000";
    elsif(rising_edge(RTC_CLK)) then
        RtcCounter <= RtcCounter + 1;
    end if;
end process RtcClk;

WriteRtc : process(RtcWriteClk)
begin
    --if rtc is running, increment it.
    --if rtc is stopped, write new values to it
    if(rising_edge(RtcWriteClk)) then
        if(RtcHalt = '0') then
            if(RtcSecReg = "111011") then
                RtcSecReg <= "000000";
                
                if(RtcMinReg = "111011") then
                    RtcMinReg <= "000000";
                    
                    if(RtcHourReg = "10111") then
                        RtcHourReg <= "00000";
                        
                        if(RtcDayLoReg = "11111111") then
                            RtcDayLoReg <= "00000000";
                            
                            if(RtcDayHiReg(0) = '1') then
                                RtcDayHiReg(1) <= '1';
                                RtcDayHiReg(0) <= '0';
                            else
                                RtcDayHiReg(0) <= '1';
                            end if;                                
                        else
                            RtcDayLoReg <= RtcDayLoReg + 1;
                        end if;
                    else
                        RtcHourReg <= RtcHourReg + 1;
                    end if;
                else
                    RtcMinReg <= RtcMinReg + 1;
                end if;
            else
                RtcSecReg <= RtcSecReg + 1;
            end if;
        else
            case RamBankReg is
                when x"8" => --Seconds
                    RtcSecReg <= DATA(5 downto 0);
                when x"9" => --Minutes
                    RtcMinReg <= DATA(5 downto 0);
                when x"A" => --Hours
                    RtcHourReg <= DATA(4 downto 0);
                when x"B" => --DayLo
                    RtcDayLoReg <= DATA;
                when x"C" => --DayHi
                    RtcHalt <= DATA(6);
                    RtcDayHiReg(1) <= DATA(7);
                    RtcDayHiReg(0) <= DATA(0);
                when others =>
            end case;
        end if;
    end if;
end process WriteRtc;

RamEnable : process(RESET, RamEnableClk)
begin
    if(RESET = '0') then
        RamEnableReg <= "0000";
    elsif(rising_edge(RamEnableClk)) then
        RamEnableReg <= DATA(3 downto 0);
    end if;
end process RamEnable;

RomBankLo : process(RESET, RomBankLoClk)
begin
    if(RESET = '0') then
        RomBankLoReg <= "00000000";
    elsif(rising_edge(RomBankLoClk)) then
        RomBankLoReg <= DATA;
    end if;
end process RomBankLo;

RomBankHi : process(RESET, RomBankHiClk)
begin
    if(RESET = '0') then
        RomBankHiReg <= '0';
    elsif(rising_edge(RomBankHiClk)) then
        RomBankHiReg <= DATA(0);
    end if;
end process RomBankHi;

RamBank : process(RESET, RamBankClk)
begin
    if(RESET = '0') then
        RamBankReg <= "0000";
    elsif(rising_edge(RamBankClk)) then
        RamBankReg <= DATA(3 downto 0);
    end if;
end process RamBank;

end Behavioral;

I have no idea if this will work or not, and it will be a while before I can test it, since I will need a larger CPLD to fit everything. Xilinx ISE says it cannot route the design correctly, due to 'Function Block 1 being too congested'. Apparently I have too much fan-in on some product terms? Lattice synthesized and fit without any error, so I'll have to dig into that some more.

But yeah, besides that error, I think it might be looking good? In the meantime, I would like to revisit the RTC chip idea, but this time using an FPGA. I think Lookup Tables could be a great fit to the problems I had.

Last edited by WeaselBomb (2019-11-11 09:57:30)

Offline

 

#42 2019-11-11 18:21:51

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

Hi WeaselBomb,

sorry for not getting back to you sooner. Anyway, your thoughts on meta-stability assume that you can detect meta-stability when that is usually not the case. Meta-stability means that it takes a long time for an output to settle to a final value. The two register pipeline works because while the first stage might become meta-stable due to the inputs transitioning while the register was clocked, the second stage will still see a logical 0 or 1 due to threshold voltages. Each additional register stage makes true metastability mucht more unlikely. This means if you can encode the value you are trying to synchronize between clock domains appropriately, you will only ever have an uncertainty of a single bit (the bit that switched). Gray coding is one popular solution to this problem, which is why you often read about FIFOs for design with rational clocks as they employ gray counters for their address counters.

However, your problem isn't that complicated, since your "count pulse" is only a single bit, so at most you might miss one edge. And that count pulse signifies when it's safe to transfer the clock registers (many bits) as they are not counting up at that moment. The other way around (going from high-speed clock to low-speed clock) takes even more synchronization time as the slow clock needs to be able to recognize the write and overwrite the register in the slow clock domain. Nintendo indicates that one should wait 4 clock cycles between these register accesses when writing individual registers and between latching the registers and reading them.

As for your fitting problem, you rightfully concluded that too many signals are being read at one place in your design. Seeing your current design, I strongly suspect the cascaded sequence of if statements that cause the problem. They all act on the rising edge, so they would all have to go through multiple Look-Up Tables (LUTs) in order to be available at one specific FB all at once. I'm not sure how you currently constraint timing, but you definitely should look into that. Adding sensible timing constraints will give you more insight into your design and allow the fitter to make proper decisions about placement and propagation delays.

Offline

 

#43 2019-11-11 22:06:46

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

You don't have to apologize! You've given me so much advice already I feel like a mooch. Honestly though, thank you, I feel like I've learned a ton from this. I had some time to read up on meta-stability in the meantime anyway.

Right, so I shouldn't have to use Gray coding or FIFOs for something this simple, since only one signal is being synchronized. So when RtcLatch is asserted, I should synchronize the "count pulse"? What I'm imagining is passing the count pulse through a 2-FF synchronizer, clocked by PHI, and when the 1st stage and 2nd stage match, then it's safe to latch the registers. Is this close to what you mean? The "count pulse" being the signal that clocks the RTC registers?

Do I really have to synchronize writes to the RTC registers? I figured those would always go through instantly, since the RTC should be halted before writes.

EDIT:

So, I could have a signal:

Code:

RtcCountPulse <= '1' when (RtcCounter = "1111") else '0';

and whenever RtcLatch is asserted, I could pass that signal through a synchronizer:

Code:

RtcSync : std_logic_vector(1 downto 0);

process(RtcSyncClk)
begin
     if(rising_edge(RtcSyncClk)) then
          RtcSync(0) <= RtcCountPulse;
          RtcSync(1) <= RtcSync(0)
     end if;
end process;

That part is easy enough, but what do I do with the signal after its been synchronized into the other clock domain?
The value of RtcSync(1) by itself seems arbitrary, like it doesn't matter if it's 0 or 1. It makes me think I need to use  the values of RtcSync(0) and RtcSync(1) together to know when latching is safe.
I could keep clocking the synchronizer until:
RtcSync(1) = RtcSync(0)

When this condition happens, it should be safe to latch the RTC?
But if the first flip-flop, RtcSync(0), is metastable, then I can't compare them, can I?

I could forget the synchronizer, and just wait until I read a valid logic level from RtcCountPulse:
SafeToLatch <= (NOT RtcCountPulse OR RtcCountPulse) AND Clk;

I have no clue if that idea even works or not, and I feel like it's bad design.

Honestly this part still feels a bit over my head. Either way, it feels like this is so close to being complete.

Thanks again, I probably wouldn't have gotten this far without your help.

Last edited by WeaselBomb (2019-11-17 01:05:41)

Offline

 

#44 2019-12-13 13:19:29

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Real life has been pretty busy lately, so not much has been done as far as coding.

I think in the end, the best solution will probably be using the MachX02 FPGA from Lattice (40 I/O pins, 256 cells). It would be nice to use a Xilinx FPGA, but all of their current offerings have way too many I/O, and ultra-low voltages that I don't want to use.
I've bought a Lattice JTAG programmer from China, and I plan on getting a MachX02 breakout board sometime in the next 2 weeks. This FPGA should have enough cells to do everything I need, and I could even read the RTC data into its registers on startup. The only real challenge would be writing to both copies of the RTC data during gameplay.

Anyways, that's where I'm at for now. Still not sure if my latching logic is OK, but we'll get there when we get there I guess.

Offline

 

#45 2019-12-23 23:00:03

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

I wasn't sure if everything would fit, but I think the PCB might work out.
The parts:
-Voltage Translators: 74ALVC164245 (these take 2 power sources, 3v and 5v, to guarantee proper CMOS levels)
-8 MB Flash: S29GL064S70TFI040 (should be enough to play the largest games in the library)
-128 KB F-RAM: ‎FM28V100 (will still hold save data when the power goes out)
-FPGA: ‎LCMXO256C-3TN100C (The best overall MBC3 replacement I could find)
-Serial RTC: ‎DS1390U (Went with serial to save board space, has automatic battery switchover)
-5 to 3 Volt Switching Regulator (LDO regulator would have been easier, but the switching regulator will be more power efficient)
-CR2025 Coin Cell Battery
-32.768 KHz Oscillator (used to keep RTC running during gameplay)

There isn't much left to route, unless I find something terribly wrong. For a first revision, I'm pretty happy with it. The track width is about 8 mil, with track clearance of 8 mil. I was unsure of via size, so I decided to have a drill of 8 mil, with an outer diameter of 16 mil. I was thinking as long as there is as much 'conductive material' within the vias as there is in the traces, that would be good enough. I really hope it is. I still need to upsize the vias in the power rails to accommodate the larger trace sizes.

If some traces may look awkward, they are probably placeholders for copper pours that I haven't put in.

@Tauwasser , do you see any glaring issues with this design? I've only ever made one PCB before, so any and all criticism is welcome.

EDIT: Finished board design, getting ready to order it now. Hope I didn't miss anything in my schematic.
EDIT2: Upsized vias to 16 mil inner, 26 mil outer (.4 mm, .65 mm).

https://i.imgur.com/vAmy8uMl.png

Last edited by WeaselBomb (2019-12-30 00:41:48)

Offline

 

#46 2019-12-29 23:10:07

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

Whoa, that's looking really good.

I don't have experience with MachXO devices, but obviously double check decoupling and power sequencing. Most of these devices don't like it when voltage is applied to pins before the core voltage has stabilized.
I see you chose to have a ground plane without thermal relief. That might make soldering harder for the RTC chip and the decoupling capacitors of the MachXO (U4). I presume X1 is an SMD part, else you might have too little space for a discrete crystal.

Your vias are smaller than what many cheap pcb manufacturers specify without surcharge (most use 0.3mm, e.g. OSH Park, Seeed Studio). Minimum annular ring therefore doesn't match either.
You have a little neckdown from pad to trace but you didn't really center the traces for each pad. That's probably negligible though as you will hand-solder and presumably not rework the board multiple times.

If the cyan region is where gold is applied, you might not want the edge of the pads and the end of this region overlapping exactly. Instead ease off a little so a bit of the upper part of each pad is covered by solder resist.
I see you chose to use AIN as WE# for the flash, but I don't see a pull-up on the pin which might cause spurious writes if the pin is not connected to a Game Boy or a device that properly pulls it high.
You might also want to add a capacitor to the #WE line which you leave unpopulated in the initial run. That way you can adjust setup times in case the timing between the two Game Boy and the requirements of your components does not match or the timing of the two voltage translators is off.

cYa,

Tauwasser

Offline

 

#47 2019-12-30 00:42:47

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Tauwasser wrote:

I see you chose to have a ground plane without thermal relief. That might make soldering harder for the RTC chip and the decoupling capacitors of the MachXO (U4)

Yes, thermal relief is a topic I don't know much about, let me make sure I understand. The problem is that the ground plane is overlapping the pads, which will cause the plane to act as a heatsink? Meaning the iron will have to be applied for longer? How would I fix this? Could I run a trace to connect the pad to the ground plane instead?

I was planning on soldering these boards either on a hot plate or in a reflow oven. Will this still be an issue in that case? I'm thinking since the entire board will be heated at the same time, the thermal relief wouldn't be necessary.

Maybe the ideal solution would be to not connect these pads to copper pours, but instead connect them to vias which will connect to copper pours underneath?

Tauwasser wrote:

Your vias are smaller than what many cheap pcb manufacturers specify without surcharge (most use 0.3mm, e.g. OSH Park, Seeed Studio). Minimum annular ring therefore doesn't match either.

I went back and upsized the vias to .4 mm inner, .65 outer. So the .4 mm inner should satisfy that first problem. Do you think I should increase  difference between inner and outer to at least .3 mm, or are these values ok? I'm unfamiliar with minimum annular ring specifications.

Tauwasser wrote:

You have a little neckdown from pad to trace but you didn't really center the traces for each pad.

I actually hadn't heard of neckdown before now, and I'm not sure what to do about it. I originally thought it would be best to have the trace width around the same width as the pad, to reduce impedance as much as possible. So I should probably reduce the trace width if I run into 'tombstoning' during reflow?

Tauwasser wrote:

I see you chose to use AIN as WE# for the flash, but I don't see a pull-up on the pin which might cause spurious writes if the pin is not connected to a Game Boy or a device that properly pulls it high.

For this, I went with a 10K pull-up. It's displayed as R1 near the center of the board.

Tauwasser wrote:

You might also want to add a capacitor to the #WE line which you leave unpopulated in the initial run. That way you can adjust setup times in case the timing between the two Game Boy and the requirements of your components does not match or the timing of the two voltage translators is off.

That is an excellent idea, I will add that in if I can squeeze it in somewhere.

Thank you for all the helpful insight. I would have never thought of some of these things.

Last edited by WeaselBomb (2019-12-30 00:44:07)

Offline

 

#48 2019-12-31 12:00:55

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

WeaselBomb wrote:

Tauwasser wrote:

I see you chose to have a ground plane without thermal relief. That might make soldering harder for the RTC chip and the decoupling capacitors of the MachXO (U4)

Yes, thermal relief is a topic I don't know much about, let me make sure I understand. The problem is that the ground plane is overlapping the pads, which will cause the plane to act as a heatsink? Meaning the iron will have to be applied for longer? How would I fix this? Could I run a trace to connect the pad to the ground plane instead?

Yes, you understood the problem. In most EDA tools, this is just an option when creating the polygon pour (e.g. KiCad) or a design rule (e.g. Circuit Studio, Altium):

https://pics.tauwasser.eu/images/2019/12/31/KiCad_PolyPour.md.pnghttps://pics.tauwasser.eu/images/2019/12/31/CircuitStudio_PolyPour.md.png

This automatically results in these pad connections:

https://pics.tauwasser.eu/images/2019/12/31/CircuitStudio_Result_4Spokes.th.png

WeaselBomb wrote:

I was planning on soldering these boards either on a hot plate or in a reflow oven. Will this still be an issue in that case? I'm thinking since the entire board will be heated at the same time, the thermal relief wouldn't be necessary.

It can become an issue, because islands of differences of heat can still result. On a hot plate this shouldn't matter too much, but reflowing can result in cold solder joints.

WeaselBomb wrote:

Maybe the ideal solution would be to not connect these pads to copper pours, but instead connect them to vias which will connect to copper pours underneath?

No, don't do that unnecessarily. It will make production more difficult and you don't really gain anything here.
I usually connect pads to polygon pours with 0.2mm spokes or 0.4mm/0.5mm if a larger current is supposed to go through them and the size permits it.

WeaselBomb wrote:

I went back and upsized the vias to .4 mm inner, .65 outer. So the .4 mm inner should satisfy that first problem. Do you think I should increase  difference between inner and outer to at least .3 mm, or are these values ok? I'm unfamiliar with minimum annular ring specifications.

These measures are close for OSH Park for instance. Basically, the annular ring measurement is half of the pad diameter minus the drill size, so (0.65mm-0.4mm) / 2  = 0.25mm/2 = 0.125mm, which is 0.002 less than 5 mil OSH Park requires. I personally go for 0.3mm drill and 0.6mm or 0.7mm pad diameter when there aren't any other considerations.

WeaselBomb wrote:

I actually hadn't heard of neckdown before now, and I'm not sure what to do about it. I originally thought it would be best to have the trace width around the same width as the pad, to reduce impedance as much as possible. So I should probably reduce the trace width if I run into 'tombstoning' during reflow?

Tombstoning will only be an issue for light components with few pads like resistors and capacitors. For a whole IC to tombstone or short circuit pads would be unusual. For ICs it's more done to make soldering easier and when reworking the change of accidentally ripping a whole track off along with a pad is greatly reduced. In your case here, I'd do nothing for now. You're above the limit that cheap places can safely manufacture, so I wouldn't push it to 0.15mm track for 0.2mm pads or something like that.

WeaselBomb wrote:

For this, I went with a 10K pull-up. It's displayed as R1 near the center of the board.

Ah, I missed that one.  smile

You might want to put a series resistor between the battery plus lead and the V_Backup pin of the DS1390 to limit inrush current. 10k should be more than adequate.

You can also aim to minimize cross-talk by spacing some of the tracks out a bit more. That's especially visible on the 5V-side of the high address lines and the data lines.

You're doing pretty well for this being your second board.

Offline

 

#49 2020-01-01 01:46:31

WeaselBomb
Member
Registered: 2018-03-06
Posts: 86
Website

Re: MBC5 in WinCUPL (problem)

Ok, I found the thermal settings in DipTrace and added thermal reliefs to my copper pour. Good to know how that works now.

Tauwasser wrote:

I personally go for 0.3mm drill and 0.6mm or 0.7mm pad diameter when there aren't any other considerations.

That sounds good. I can easily fit 0.3 and 0.65 right now, so I'll go ahead and use those values. I might try to bump the pad diameter up if I get ambitious.

Tauwasser wrote:

You might want to put a series resistor between the battery plus lead and the V_Backup pin of the DS1390 to limit inrush current. 10k should be more than adequate.

This must be what that resistor is for on retail cartridges! I remember trying to figure out why that was there a long time ago. So it actually protects the battery? I assume this is pretty standard practice for boards that use batteries then?

Tauwasser wrote:

You can also aim to minimize cross-talk by spacing some of the tracks out a bit more. That's especially visible on the 5V-side of the high address lines and the data lines.

Is there a good rule of thumb for track clearance? I just decided to use the same clearance as the width of the track (.204 mm). That's something I spent a lot of time thinking about and trying to read up on before saying forget it. It seemed like everyone had a different opinion.
I've gone ahead and spaced out some of those 5v traces.

Cross-talk is something I'm concerned about on this board since it seems so dense in the center.

EDIT:
Well I got ambitious. Vias are now .4 & .7 mm. Track width is still .204, same for clearance.
Also, for driving DIR on the voltage translators, I noticed it goes from 5v side to 3v side when DIR = low. So it should be fine to drive that using the /WR signal from the cart edge?
I did notice the DIR pin was referenced to the 3v VCC, so the 5v /WR signal might cause it to transition from high to low too slowly. To compensate, I've added a pull-down resistor, R5.

https://i.imgur.com/TBEsPvil.png

Last edited by WeaselBomb (2020-01-01 22:19:24)

Offline

 

#50 2020-01-02 23:13:51

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: MBC5 in WinCUPL (problem)

WeaselBomb wrote:

Ok, I found the thermal settings in DipTrace and added thermal reliefs to my copper pour. Good to know how that works now.

Oh, that's what that is. I was wondering what software package that was smile

WeaselBomb wrote:

This must be what that resistor is for on retail cartridges! I remember trying to figure out why that was there a long time ago. So it actually protects the battery? I assume this is pretty standard practice for boards that use batteries then?

It's one of the reasons it's there. There are also industry requirements to get certification to minimize reverse charging current. Basically, the current must be limited as well if there was a (possibly destructive) event in the rest of the circuit that would connect a higher voltage to the positive battery terminal and thus "charge" the battery. If the current is too high, the battery might leak or explode and that's supposed to be avoided as well. UL for instance requires either two diodes in series or a diode and a series resistor.

Your ‎DS1390U is already rated to fulfill the UL requirement on that pin (which is curious, since they allow trickle charge by software). Therefore I expect some kind of diode to already be present in the device, like the MM1134 used by Nintendo (which uses a Schottky diode internally). However, actual resistors that can dissipate energy are physically big (and thus take up a lot of area in comparison to transistors) and usually not included on-chip.

WeaselBomb wrote:

Is there a good rule of thumb for track clearance? I just decided to use the same clearance as the width of the track (.204 mm). That's something I spent a lot of time thinking about and trying to read up on before saying forget it. It seemed like everyone had a different opinion.

You're right that everybody has their own opinion. I use track width or a bit more as a rule of thumb as well. In serious cases you would want to compute the coupling for high-frequency signals using a program like Si9000 to make sure that your design fulfills desired impedance requirements, but the Game Boy signals are super slow so you can get away with pretty much anything.

WeaselBomb wrote:

I've gone ahead and spaced out some of those 5v traces.

Looks better to me.

WeaselBomb wrote:

Cross-talk is something I'm concerned about on this board since it seems so dense in the center.

Well, you haven't shown the bottom side yet smile

WeaselBomb wrote:

Also, for driving DIR on the voltage translators, I noticed it goes from 5v side to 3v side when DIR = low. So it should be fine to drive that using the /WR signal from the cart edge?
I did notice the DIR pin was referenced to the 3v VCC, so the 5v /WR signal might cause it to transition from high to low too slowly. To compensate, I've added a pull-down resistor, R5.

I would expect it to be fine. I don't see the need for a pull-down resistor at all, since the datasheet (Nexperia) indicates that the threshold voltages are the same for 3V3 and 5V0. If anything, I'd be concerned about the #WR not rising quickly enough, because old CMOS/TTL stuff like the Game Boy tends to drive signals high by using a FET in its linear (resistive) region whereas driving low is usually through a FET in saturation region (so acts like a short).

However, it's highly unlikely that this is going to be a problem since your voltage translator has a propagation delay in the nanosecond region.
When I originally talked about adding a capacitor in my last post I was only thinking about the MachXO's setup/hold time requirements.

WeaselBomb wrote:

https://pics.tauwasser.eu/images/2020/01/03/RTC_Crystal_Ground.png

You really want to have the ground plane surround the RTC crystal pads and possibly connect the ground island north of the RTC's GND pin to the pin as well.
This will help avoid leakage current and capacitance mismatch. Often you even see a so-called guard ring around the pads that forms a star connection (only connected in one point) with the actual ground plane, e.g. see this Stackoverflow Answer.

cYa,

Tauwasser

Last edited by Tauwasser (2020-01-02 23:14:07)

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson