Help - Implementing Shadow RAM in CPLD

discuss both original and modern hardware for the bbc micro/electron
User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 15, 2020 1:34 pm

hoglet wrote:
Sun Nov 15, 2020 1:24 pm
Ken,

This VHDL is different (to what you posted earlier):

Code: Select all

   always @(posedge dPhi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         ShEn <= 1'b0;
      end else if (!RnW && FE34_7) begin
         ShEn <= bbc_DATA[7];
      end
   end
Specifically, this is now latching data on the rising edge of dPhi2, your earlier example used the falling edge.

This may be what the original harware did, but it's a nasty cludge. The 6502 write data is not guaranteed to be stable on the rising edge of Phi2, and generally is not. Especially on the model B with it's 18 loads on the data bus. Plus there is an additional buffer on Integra delaying things. The hack to make this work is to delay the Phi2 clock, which I guess is what the RC network is doing.
I switched to rising edge after checking the datasheet for the 74HCT174 (which is what the original hardware used). As you suggest, since the original IntegraB was using a latch that works on rising edge, the original designers may have felt the need to delay the Phi2 clock, and did this with the RC network.

Given that I don't have that same hardware limitations and can latch on a falling edge, I'll try as you suggest with a non delayed Phi2 (I'll actually try initially with a non delayed, inverted Phi1). I'm hopeful that may work...

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 15, 2020 1:39 pm

So, this seems to work equally as well even better:

Code: Select all

   always @(posedge Phi1 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         ShEn <= 1'b0;
      end else if (!RnW && FE34_7) begin
         ShEn <= bbc_DATA[7];
      end
   end
If I want to use an non delayed Phi2, I'll need to make some wiring mods to my board.

Edit: Brilliant! That's actually made a big difference. I now have Lancelot (a game that uses both shadow and sideways RAM) running correctly =D> =D> =D>. Woo hoo!

I'm now going to port this code back over to my V2 IntegraB board, and see how it runs on that. I'm hopeful it can only be better, as I don't have any dupont wires to worry about. There's still the issue that neither Phi1 or Phi2 are wired into clock inputs on my V2 board, but having said that, Phi1 is not wired into a clock input on this test setup of mine right now and that seems to be working ok. I'll obviously address that in time.

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Mon Nov 16, 2020 12:13 am

KenLowe wrote:
Sun Nov 15, 2020 1:39 pm
I'm now going to port this code back over to my V2 IntegraB board, and see how it runs on that. I'm hopeful it can only be better, as I don't have any dupont wires to worry about. There's still the issue that neither Phi1 or Phi2 are wired into clock inputs on my V2 board, but having said that, Phi1 is not wired into a clock input on this test setup of mine right now and that seems to be working ok. I'll obviously address that in time.
Right, I've ported the Shadow RAM code back across to my V2 IntegraB board, but have come across an issue with the onboard RAM module. I put the nCE signal through a MAX6366 Supervisory IC, but I think that's getting in the way. I can read and write the onboard RAM fine, but I can't reliably run code from the onboard RAM.

Instead of using the onboard RAM, I've added a couple of 32k RAM ICs into the ROM sockets, and hooked up A14 to pin 1 on one of the RAM ICs with a flying lead (for use with the Shadow RAM), and both Shadow and Sideways RAM functions seem to be working perfectly in that configuration. Lancelot is running nicely on the machine. So I'm happy that my CPLD code is working correctly now.

Next step is to try and get the RTC running...

User avatar
BeebMaster
Posts: 3736
Joined: Sun Aug 02, 2009 5:59 pm
Location: Lost in the BeebVault!
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by BeebMaster » Mon Nov 16, 2020 12:54 pm

Good good, getting there, which I am glad about as I've never really got over this disappointment from 29 years ago:

Image
Image

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Mon Nov 16, 2020 1:06 pm

Given the closeness in the dates, and the similar hole punching, I'm guessing this was your letter too:

viewtopic.php?f=3&t=19683&p=273781&hilit=Acorn#p273781

User avatar
BeebMaster
Posts: 3736
Joined: Sun Aug 02, 2009 5:59 pm
Location: Lost in the BeebVault!
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by BeebMaster » Mon Nov 16, 2020 1:33 pm

Yes, that was the previous one, although I've been censored there. Whole history here:

http://www.beebmaster.co.uk/AcornLetter ... tters.html

The most remarkable thing about it is that back then when you posted a letter, it arrived the next day!
Image

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Mon Nov 16, 2020 11:01 pm

KenLowe wrote:
Mon Nov 16, 2020 12:13 am
KenLowe wrote:
Sun Nov 15, 2020 1:39 pm
I'm now going to port this code back over to my V2 IntegraB board, and see how it runs on that. I'm hopeful it can only be better, as I don't have any dupont wires to worry about. There's still the issue that neither Phi1 or Phi2 are wired into clock inputs on my V2 board, but having said that, Phi1 is not wired into a clock input on this test setup of mine right now and that seems to be working ok. I'll obviously address that in time.
Right, I've ported the Shadow RAM code back across to my V2 IntegraB board, but have come across an issue with the onboard RAM module. I put the nCE signal through a MAX6366 Supervisory IC, but I think that's getting in the way. I can read and write the onboard RAM fine, but I can't reliably run code from the onboard RAM.

Instead of using the onboard RAM, I've added a couple of 32k RAM ICs into the ROM sockets, and hooked up A14 to pin 1 on one of the RAM ICs with a flying lead (for use with the Shadow RAM), and both Shadow and Sideways RAM functions seem to be working perfectly in that configuration. Lancelot is running nicely on the machine. So I'm happy that my CPLD code is working correctly now.
Confirmed that the MAX6366 Supervisory IC is indeed causing the issue. This has been bypassed temporarily, and I've now been able to remove all the extra 32k RAM ICs that I installed yesterday:

viewtopic.php?f=3&t=21049

I'm sure I'll be able find a work around for that. I'm thinking of using Phi2 clock as the watchdog. That should be more reliable and consistent than the A13 signal I'm currently using.

Anyway, both shadow and sideways RAM is now working perfectly. I've had a couple of games that use both Shadow and Sideways RAM running on the board all day, and it hasn't missed a beat.

Through the onboard 512k RAM IC, I now have access to a full compliment of 16 battery backed RAM banks, which can be individually write protected via jumpers. This V2 IntegraB board is hugely flexible, and 12 of these RAM banks (0..3 and 8..15) can be individually switched out (also via jumpers) and physical ROMs (or PALPROMs) used instead. If using ROM instead of RAM, then banks 8..15, which are located on the IntegraB board, can accept 4 x 32k ROM (or RAM, FRAM, EEPROM, Flash) modules instead of 16k ROMs (as per the original V1 board). This is configurable by yet more jumpers! I'm not sure why you'd want to put RAM into these sockets, though, since that comes as standard with the 512k RAM IC.

Final hurdle is getting the RTC working. It's stubbornly refusing to kick into life, and I need to work out why.

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Wed Nov 18, 2020 12:00 am

KenLowe wrote:
Mon Nov 16, 2020 11:01 pm
Final hurdle is getting the RTC working. It's stubbornly refusing to kick into life, and I need to work out why.
Started working on this earlier this evening, but didn't get too far before I accidentally fried the CPLD on my development board. Fortunately I've got some spare boards and spare CPLDs, and I'm getting a bit better at drag soldering, so I've now got another board up and running. I've also significantly tidied up the tangle of dupont wires by reassigning the CPLD I/O so that wires aren't criss-crossing nearly as much. Much to my surprise the board sprung into life at almost the first attempt!

RTC is still not working, though - even though there's nothing obviously different between this CPLD version of the IntegraB board and the original discrete component version. I even wired an external hex inverter into the RTC data and address strobe lines to match the original board configuration (I obviously also had to invert the CPLD outputs), but still nothing. There's not really that much to the RTC (CDP6818E) - a shared 8 bit address / data bus and the data and address strobe lines, which are triggered by accessing memory locations &FE38 and &FE3C respectively. This code is a direct copy from the original PAL:

Code: Select all

	wire   FE3x = (bbc_ADDRESS[15:4] == 12'hFE3);
	assign RTC_AS  = FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && !Phi1;
	assign RTC_DS  = FE3x && (bbc_ADDRESS[3:2] == 2'b11);
I can see the data and address strobes pulsing on my scope as the IntegraB OS (IBOS) attempts to communicate with the RTC, but the computer just hangs (I think IBOS is waiting for some response from the RTC). I'm going to have to get a bit more intrusive with a logic analyser to see where it's failing. That should be a lot easier to hook up now that I've tidied up all the wiring. A job for tomorrow evening.

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 21, 2020 12:34 am

KenLowe wrote:
Wed Nov 18, 2020 12:00 am
KenLowe wrote:
Mon Nov 16, 2020 11:01 pm
Final hurdle is getting the RTC working. It's stubbornly refusing to kick into life, and I need to work out why.
Started working on this earlier this evening, but didn't get too far before I accidentally fried the CPLD on my development board. Fortunately I've got some spare boards and spare CPLDs, and I'm getting a bit better at drag soldering, so I've now got another board up and running. I've also significantly tidied up the tangle of dupont wires by reassigning the CPLD I/O so that wires aren't criss-crossing nearly as much. Much to my surprise the board sprung into life at almost the first attempt!

RTC is still not working, though - even though there's nothing obviously different between this CPLD version of the IntegraB board and the original discrete component version. I even wired an external hex inverter into the RTC data and address strobe lines to match the original board configuration (I obviously also had to invert the CPLD outputs), but still nothing. There's not really that much to the RTC (CDP6818E) - a shared 8 bit address / data bus and the data and address strobe lines, which are triggered by accessing memory locations &FE38 and &FE3C respectively. This code is a direct copy from the original PAL:

Code: Select all

	wire   FE3x = (bbc_ADDRESS[15:4] == 12'hFE3);
	assign RTC_AS  = FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && !Phi1;
	assign RTC_DS  = FE3x && (bbc_ADDRESS[3:2] == 2'b11);
I can see the data and address strobes pulsing on my scope as the IntegraB OS (IBOS) attempts to communicate with the RTC, but the computer just hangs (I think IBOS is waiting for some response from the RTC). I'm going to have to get a bit more intrusive with a logic analyser to see where it's failing. That should be a lot easier to hook up now that I've tidied up all the wiring. A job for tomorrow evening.
So, I now have the RTC function working on my Development board. Another stupid error in my CPLD code. Well, this one was a bit less obvious, and stems from a well known (by me anyway) misprint in the IntegraB manual. There are three Private Memory latches, PrvS1, PrvS4 and PrvS8, which are mapped to data bits 6, 5 and 4 respectively. The manual wrongly shows them mapped to 4, 5 & 6 and this is what I stupidly had in the CPLD code. It's something that gets a mention in these threads:

viewtopic.php?f=3&t=17401#p244949
viewtopic.php?f=3&t=14744&p=200634#p200634

With that corrected, all functions of the V1 IntegraB are now running correctly from the Development CPLD, so a major step forward! I now need to port this code over to the V2 IntegraB and see if I can get that working too. It uses a slightly different clock, that I've never been able to get working even on my V1 board, so confidence is still a bit low.

Anyway, here's the corrected code that I'm using on my Development board:

Code: Select all

	//This data is latched when address is in the range FE34..FE37

   always @(posedge Phi1 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS8 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS8 <= bbc_DATA[4];
      end
   end
	
	always @(posedge Phi1 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS4 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS4 <= bbc_DATA[5];
      end
   end

   always @(posedge Phi1 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS1 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS1 <= bbc_DATA[6];
      end
   end

   always @(posedge Phi1 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         ShEn <= 1'b0;
      end else if (!RnW && FE34_7) begin
         ShEn <= bbc_DATA[7];
      end
   end

User avatar
hoglet
Posts: 9617
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sat Nov 21, 2020 7:34 am

KenLowe wrote:
Sat Nov 21, 2020 12:34 am
With that corrected, all functions of the V1 IntegraB are now running correctly from the Development CPLD, so a major step forward! I now need to port this code over to the V2 IntegraB and see if I can get that working too. It uses a slightly different clock, that I've never been able to get working even on my V1 board, so confidence is still a bit low.
What clock is the V2 board using?

Dave

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 21, 2020 8:33 am

hoglet wrote:
Sat Nov 21, 2020 7:34 am
KenLowe wrote:
Sat Nov 21, 2020 12:34 am
With that corrected, all functions of the V1 IntegraB are now running correctly from the Development CPLD, so a major step forward! I now need to port this code over to the V2 IntegraB and see if I can get that working too. It uses a slightly different clock, that I've never been able to get working even on my V1 board, so confidence is still a bit low.
What clock is the V2 board using?

Dave
Hi Dave,

It's the Dallas DS12885. I'm trying to use it in place of a Harris CDP6818. The Harris CDP6818A and the Motarola MC146818A both also work fine in my original V1 board as long as I pull pins 1 and 16 up to 5v. I've also tried the Unitrode BQ3285 which appears to be an equivalent of the DS12885 but I've not been able to get that one working either.

I'm trying to use the DS12885 because I can still get the SMT version of this IC, and the only external component needed for the OSC circuit is the Crystal, simplifying the board layout slightly.

Edit: Here's the schematics from both the V1 and V2 boards. The three jumpers on the V1 board are to allow me to switch between the various RTC types. In the default positions, the layout is suitable for the CDP6818, CPD6818A and MC146818A.
RTC CDP6818.PNG
V1 board schematic
RTC DS12885.PNG
V2 board schematic

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 21, 2020 6:39 pm

The DS12885 is actually working nicely in my V1 IntegraB with the Dev board. The BQ3285 *almost* works too. Unfortunately, the DS12885 is still not working in my V2 board. I think timings must be marginal, and I'm looking for a wee bit of help here again. Does anything look particularly wrong in the traces below? I've attached a copy of the datasheet, that describes how the various signals should behave.

My scope is set up as follows:

Yellow trace: Address Strobe
Magenta trace: Data Strobe
Cyan trace: R/W
Blue trace: Phi1

and the following code is loaded in my CPLD (all other functions have been temporarily disabled):

Code: Select all

	wire   FE3x		= (bbc_ADDRESS[15:4] == 12'hFE3);
	assign RTC_AS  = FE3x && (bbc_ADDRESS[3:0] == 4'h8) && !RnW && !Phi1; //FE38
	assign RTC_DS  = FE3x && (bbc_ADDRESS[3:0] == 4'hC) && !Phi1;  //FE3C
Note that I have also tried with the !Phi1 term removed altogether, but that didn't change anything.

Firstly, during the write phase, and executing the following commands

Code: Select all

LDA #30: Select RTC address 30
STA &FE38: Strobe in address to RTC
LDA #&55: Value to be stored at address 30
STA &FE3C: Strobe in value to RTC address 30
RTS
...this is what I see:
DS1Z_QuickPrint41.png
Write: AS followed by DS
DS1Z_QuickPrint42.png
Write: Zoom in of AS
DS1Z_QuickPrint43.png
Write: Zoom in of DS
If I then move on to the read phase, and execute the following commands:

Code: Select all

LDA #30: Select RTC address 30
STA &FE38: Strobe in address to RTC
LDA &FE3C: Strobe out value from address 30
STA &80: Save a copy at &80
RTS
If I then check what's stored in &80, it varies, but the most recent time was 2.

This is what I see on the scope...
DS1Z_QuickPrint44.png
Read: AS followed by DS
DS1Z_QuickPrint45.png
Read: Zoom in of AS
DS1Z_QuickPrint46.png
Read: Zoom in of DS
Attachments
DS12885-DS12C887A.pdf
(262.8 KiB) Downloaded 5 times

User avatar
hoglet
Posts: 9617
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sat Nov 21, 2020 7:45 pm

KenLowe wrote:
Sat Nov 21, 2020 6:39 pm
The DS12885 is actually working nicely in my V1 IntegraB with the Dev board. The BQ3285 *almost* works too. Unfortunately, the DS12885 is still not working in my V2 board. I think timings must be marginal, and I'm looking for a wee bit of help here again. Does anything look particularly wrong in the traces below? I've attached a copy of the datasheet, that describes how the various signals should behave.
I can't see anything obviously wrong in the traces.
KenLowe wrote:
Sat Nov 21, 2020 6:39 pm
Note that I have also tried with the !Phi1 term removed altogether, but that didn't change anything.
The Phi1 term is definitely needed in this case. If you omit it, the falling edge of AS and DS will happen somewhat later than it should, and the address/data signals may no longer be valid.

I would try to figure out whether its the reads or the writes that are unreliable, by writing a slightly more complex test program (which could mostly be in basic, apart from the code to actual do the FE38/FE3C read/write)

The program could do:
- write
- read
- read
- read

By reading back multiple times, you should be able to determine if reads are consistent (and therefore it's likely it's the write that is broken).

Dave

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 21, 2020 9:17 pm

hoglet wrote:
Sat Nov 21, 2020 7:45 pm
I would try to figure out whether its the reads or the writes that are unreliable, by writing a slightly more complex test program (which could mostly be in basic, apart from the code to actual do the FE38/FE3C read/write)

The program could do:
- write
- read
- read
- read

By reading back multiple times, you should be able to determine if reads are consistent (and therefore it's likely it's the write that is broken).

Dave
It can actually all be done in Basic. On a working system ?&FE38=xx will set the address. If that's then followed with a P.?&FE3C, it will read the data correctly from that address. Similarly, if it's then followed with a ?&FE3C=xx, it will save the data correctly to that address.

On my problematic V2 board, repeat read backs are not giving me consistent results.

On my V2 board I've disabled the onboard DS12885 RTC and I'm now trying to interface with an offboard CDP6818 to see if I can get that working. I'm picking up all the necessary signals (D0..D7, R/nW & nRST) directly from the CPU apart from the AS & DS signals that I've got wired out to temporary pins. Unfortunately it's not responding either, and I'm struggling to work out why. I thought it may have been due to the fact that the oscillator was not running, but I've confirmed on another machine that the oscillator doesn't need to be running to communicate with the chip. Next up is to get the scope on one of my working systems to see if I can spot any differences.

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 2:09 am

As is the way of these things, I went backwards a bit this evening :(. But it has allowed me to move forward again more positively.

I thought the DS12885 was running reliably on my Dev board machine. However, I started having problems with evening with unreliable reads from the RTC IC. So, I switched back to the normally more reliable CDP6818 but was getting similar unreliable reads from it too. Trying this simple test, which does repeated reads from the RTC IC would cause the computer to hang after a very short period. The same code runs absolutely fine with one of my old V1 IntegraB boards (I've had it running on a couple of beebs for a few hours without any errors):

Code: Select all

10*STATUS
20G.10
After much head scratching I realised that the Phi1 clock on my Dev board had found its way back onto a standard CPLD input. This happened after I fried my old dev board and I had to rewire everything onto a new board. I've moved this clock signal back over to a global clock input and the results have been much better. The same simple test code has now been running for about 30 minutes without any errors. It did error out once before that after running for about 15 mins, but I'm putting that down to the fact that I'm still using a bunch of dupont wires with that dev board arrangement.

Unfortunately I'm still not getting reliable results using the DS12885, and I'm still not sure why. I may have to dig out my logic analyser and set that up. Worst case here, I may switch to using a 146818 in a PLCC-28 package. I can still buy some of those. Overall, it's not much bigger than the DS12885 I was trying to use, and I think it should be easy enough to solder onto the board. It does mean that I will need to add some other external components, though, to get the oscillator running. That's a small price to pay.

Also worth noting that to get the reliable reads, I had to remove the Phi1 term from the RTC_DS line. This code now matches the code in the original PLD for the V1 board.

User avatar
hoglet
Posts: 9617
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sun Nov 22, 2020 8:39 am

KenLowe wrote:
Sun Nov 22, 2020 2:09 am
Also worth noting that to get the reliable reads, I had to remove the Phi1 term from the RTC_DS line. This code now matches the code in the original PLD for the V1 board.
That's a bit concerning and slightly unexpected.

I wonder if this comes back using Phi1 (with it's slow active rising edge), rather than Phi2 (with it's fast active falling edge)?

(The recommended clock for 6502 timing is always Phi2 for this reason.)

Or there may be something else going on that both of us are missing.

Is the RTC data bus directly connected to the 6502 data bus?

The risk with not really understanding why a particular change fixes a problem is that often it come back and bits you. For example, when someone uses a different brand of 6502 with slightly different timings. If that's always under your control, then that's a risk you might choose to take. Personally I would want to get to the bottom of this before I was happy.

Dave

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 10:07 am

hoglet wrote:
Sun Nov 22, 2020 8:39 am
That's a bit concerning and slightly unexpected.

I wonder if this comes back using Phi1 (with it's slow active rising edge), rather than Phi2 (with it's fast active falling edge)?

(The recommended clock for 6502 timing is always Phi2 for this reason.)
That could well be the case. Over the course of yesterday I was swapping between Phi1 and dPhi2 (inverted) but it didn't make a lot of difference. I still couldn't get reliable comms. But that's more likely down to the fact that dPhi2 still has the RC circuit (which is why I temporarily moved over to use inverted Phi1). On my dev system it would be fairly straight forward to pick up Phi2 directly, so I'll do that today and see what difference it makes.
hoglet wrote:
Sun Nov 22, 2020 8:39 am
Is the RTC data bus directly connected to the 6502 data bus?
No. It goes through a 74HCT245 data buffer on both my Dev board setup and the V2 IntegraB board. However, when I was trying to get a clock running on my V2 IntegraB board yesterday, at one stage I disabled the onboard DS12885 RTC and hooked up an external CDP6818. This CDP6818 was connected directly to the 6502 data bus (I was using a 6502 breakout board to make it easier to pick up the signals). I couldn't get this CDP6818 to work at all. For this test, I could also pick up a buffered data bus by making a small adaptor board and plugging that into one of my 8 onboard SWROM sockets if you think that would be more appropriate.
hoglet wrote:
Sun Nov 22, 2020 8:39 am
The risk with not really understanding why a particular change fixes a problem is that often it come back and bits you. For example, when someone uses a different brand of 6502 with slightly different timings. If that's always under your control, then that's a risk you might choose to take. Personally I would want to get to the bottom of this before I was happy.
I agree, and I've got a couple of thoughts on this. Firstly, get the logic analyser onto it. But secondly, I was thinking I may try to hook up the various RTCs to the User port to see if I can make any sense of what's happening, and to get a bit of confidence on my interpretation of the timing diagrams in the data sheets. If I hook it up to the User port I will have more control over the length of DS and AS pulses and the R/nW signal. I would need 8 x I/O for the data bus and 3 outputs for the control signals, which is more than I can get from the User port, so I could pick up one of the control signals from the Printer port, or alternatively I could just use User port data bit 7 for control and tie that bit down to Gnd on the RTC. That would be fine for the tests I want to conduct.


Worth noting that I set off the simple test again on my dev machine this morning (same configuration as yesterday), and it's been running fine for about 30 mins now. No hang ups yet...

User avatar
hoglet
Posts: 9617
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sun Nov 22, 2020 11:28 am

Ken,

I'm happy to try to answer any questions you have about the DS12885 data sheet.

I find it helps to print out the timing diagram and annotate it with the actual timings in ns.

The device support two different bus timing modes, Intel and Motorla. Your schematic indicate you have selected the Motorola mode. It's worth double checking the MOT pin (1) really is tied high, and is not floating. Also, I just noticed there are two ground pins (12) and (16) so make sure both of these are connected to 0V.

Dave

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 12:06 pm

hoglet wrote:
Sun Nov 22, 2020 11:28 am
Ken,

I'm happy to try to answer any questions you have about the DS12885 data sheet.

I find it helps to print out the timing diagram and annotate it with the actual timings in ns.

The device support two different bus timing modes, Intel and Motorla. Your schematic indicate you have selected the Motorola mode. It's worth double checking the MOT pin (1) really is tied high, and is not floating. Also, I just noticed there are two ground pins (12) and (16) so make sure both of these are connected to 0V.

Dave
Thanks Dave. I do really appreciate your help and guidance.

Firstly, I can confirm that I am indeed using the Motorola mode, and that I have pin 1 tied to Vcc. I can also confirm that pins 12 and 16 are both tied to Gnd. Annoyingly, pin 16 needs to be tied to Vcc for some of the RTCs (CDP6818A for example) as this is used for a Standby function and will go into Standby if held low.

Moving back to my development system, I have done some further work here. Firstly, I have removed the RC network from the IntegraB board and now have Phi2 wired directly into the CPLD. I have also rejigged some of the patch wiring between the IntegraB board and the CPLD dev board so I'm not using the global pins for general I/O. I've then wired Phi1, Phi2 & RST into those global pins.

Having done that, I then updated the CPLD code to use the falling edge of Phi2 instead of the rising edge of Phi1 in almost all locations. I've also added the Phi2 term back into the RTC_DS line. It's working perfectly with the CDP6818 RTC. I've had the test code running now for over 30mins without a single issue. I'm away to try the DS12885 again, to see how I get on with that.

One further question for you. The beeb doesn't use Phi2, and instead uses Phi1 throughout. On my IntegraB board, I intercept Phi1 from the CPU. It's wired directly into the CPLD, where I then condition it, before then outputting this on another CPLD pin to drive all the beeb Phi1 circuitry (via IC37 hex inverter on the beeb). This is what the CPLD code currently looks like:

Code: Select all

	assign Phi1 = from_CPU_Phi1;
	assign Phi2 = from_CPU_dPhi2;
	assign RnW = from_CPU_RnW;
	assign to_bbc_Phi1 = !(!Phi1 & !ShAct);
	assign to_bbc_RnW = !(!RnW & !ShAct);
Should I drive the 'to_bbc_Phi1' signal from Phi2 instead of !Phi1, or should I leave that as-is?

User avatar
hoglet
Posts: 9617
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sun Nov 22, 2020 12:25 pm

KenLowe wrote:
Sun Nov 22, 2020 12:06 pm
Should I drive the 'to_bbc_Phi1' signal from Phi2 instead of !Phi1, or should I leave that as-is?
I would leave as is, unless there are any issues with the current arrangement.

The problem here is that the timing on the Model B is a bit of a minefield, with negative margins in some places. i.e. correct operation relies on the parts in practice being faster that the worst case specified in the data sheet. This is why certain components (IC14 for example) are very critical. It's also possibly why some people have problems with random failures when the ambient temperature is very high (as this slows parts down a bit).

In theory, there shouldn't be much difference in the edge timings of Phi1 and Phi2 (less that 10ns between the falling edge of one clock and the rising edge of the other, assuming both are equally loaded).

But in practice any change may be significant.

(If changing to Phi2 does cause issues, then it's an indication that the timing when using Phi1 may well be marginal as well)

Dave

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 3:36 pm

Ok. I'll leave it as-is. It seems to be working fine with that configuration.

I must admit, I get the feeling this thing is fighting me all the way. Once I was happy that the RTC was behaving, having made all the Phi2 changes, I thought I would fire up one of the games that would test both shadow and sideways RAM. Only to discover that it was now hanging at a certain point.

Long story short, I think my RAM chips were a little bit loose in their socket, so once that was resolved everything started working again.

I now appear to have Sideways RAM, Shadow RAM and CDP6818 based RTC all working reliably from a CPLD on my dev machine. I still can't get the DS12885 working, but I've not really looked at that much today. I will when I get a chance.

Anyway, here's a copy of the latest CPLD code running in the dev machine:

Code: Select all

`timescale 1ns / 1ps
/************************************************************************
	 IntegraBV2.v

	 IntegraB V2 - A fully expanded ROM / RAM Board for BBC Micro
    Copyright (C) 2020 Ken Lowe

    IntegraBV2 is free software: you can redistribute it and/or modify
	 it under the terms of the GNU General Public License as published by
	 the Free Software Foundation, either version 3 of the License, or
	 (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	 Note:
	 This code is to interface CPLD Dev Board with an existing
	 V1 IntegraB Board. Not to be used on V2 IntegraB Board

	 Email: xxxxx@yyyyyyy.co.uk

************************************************************************/
module IntegraBV2(
	input from_CPU_RnW,
	input from_CPU_Phi1,
	input from_CPU_dPhi2,
	input bbc_nRST,
	input [7:0] bbc_DATA,
	input [15:0] bbc_ADDRESS,

	output to_bbc_Phi1,
	output to_bbc_RnW,
	output to_bbc_rD0,
	output to_bbc_rD1,
	output nDE,
	output IntegraRnW,
	output nWDS,
	output nRDS,
	output nRomBankSel0_3,
	output [15:8] nRomBankSel,
	output RTC_AS,
	output RTC_DS,
	output RAM_CE,
	output RAMBank45_CE,
	output RAMBank67_CE,
	output Shadow_CE
	);


	// Repeat RnW & Phi1 from Input to Output
	wire Phi1;
	wire Phi2;
	wire ShAct;
	wire RnW;
	assign Phi1 = from_CPU_Phi1;
	assign Phi2 = from_CPU_dPhi2;
	assign RnW = from_CPU_RnW;
	assign to_bbc_Phi1 = !(!Phi1 & !ShAct);
	assign to_bbc_RnW = !(!RnW & !ShAct);
	assign IntegraRnW = !RnW;


	wire   FE3x = (bbc_ADDRESS[15:4] == 12'hFE3);
	wire   FE30_3  = FE3x && (bbc_ADDRESS[3:2] == 2'b00);
	wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01);
	wire   FE34    = FE3x && (bbc_ADDRESS[3:0] == 4'h4);
	assign RTC_AS  = (FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && !Phi2);
	assign RTC_DS  = (FE3x && (bbc_ADDRESS[3:2] == 2'b11) && !Phi2);
	
	assign nRDS = !( RnW & Phi2);
	assign nWDS = !(!RnW & Phi2);


	// If address is in range &8000..&BFFF then SWRAddr = 1, otherwise 0
	wire SWRAddr  =  (bbc_ADDRESS[15:14] == 2'b10);

	reg PrvEn;
	reg PrvS8;
	reg PrvS4;
	reg PrvS1;
	assign PrvAct    =   (((bbc_ADDRESS[15:12] == 4'h8) & (bbc_ADDRESS[11:10] == 2'b00) & PrvS1 & PrvEn)   //address decodes to &8000..&83FF
						  |    ((bbc_ADDRESS[15:12] == 4'h8) &  PrvS4 & PrvEn)   										 //address decodes to &8000..&8FFF
						  |    ((bbc_ADDRESS[15:12] == 4'h9) &  PrvS8 & PrvEn)											 //address decodes to &9000..&9FFF
						  |    ((bbc_ADDRESS[15:12] == 4'hA) &  PrvS8 & PrvEn));										    //address decodes to &A000..&AFFF


	reg ShEn;
	reg MemSel;

	// This logic sets ShAct to logic state '1' if the addresses in the screen range &3000..&7FFF and if Shadow Memory is active. 
	wire ScreenMem	  =   ((bbc_ADDRESS[15:12] == 4'h3)    //address decodes to &3000..&3FFF
							  | (bbc_ADDRESS[15:14] == 2'b01)); //address decodes to &4000..&7FFF
	assign ShAct     = ScreenMem & ShEn & !MemSel;

	// ShadowSel is logic '1' when either Shadow or Private RAM is being accessed. 
	wire ShadowSel   = !(!ShAct & !PrvAct);


	reg rD0;
	reg rD1;
	reg rD2;
	reg rD3;
	wire ROMDec;
	assign to_bbc_rD0  = rD0;
	assign to_bbc_rD1  = rD1;
	

	// The following logic is used to demux the ROM banks.
	// Banks 0..3 are located on the Beeb mainboard.
	// Banks 4..7 are SWRAM banks located on the IntegraB board
	// Banks 8..15 are ROM slots on the IntegraB board. 

	// Decode if address is in the range &8000..&BFFF and it's not Private RAM that's being accessed.
	wire   nROMBankSel0_3;
	assign ROMDec   =  (SWRAddr & !PrvAct & !Phi2
						 |	  SWRAddr & !PrvAct & !nROMBankSel0_3);
	
	// GenBankSel[x] is logic '1' when bank is selected
	wire GenBankSel[15:0];
	assign GenBankSel[0]   = !rD3 & !rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[1]   = !rD3 & !rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[2]   = !rD3 & !rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[3]   = !rD3 & !rD2 &  rD1 &  rD0 & ROMDec;
	assign GenBankSel[4]   = !rD3 &  rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[5]   = !rD3 &  rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[6]   = !rD3 &  rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[7]   = !rD3 &  rD2 &  rD1 &  rD0 & ROMDec;
	assign GenBankSel[8]   =  rD3 & !rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[9]   =  rD3 & !rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[10]  =  rD3 & !rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[11]  =  rD3 & !rD2 &  rD1 &  rD0 & ROMDec;
	assign GenBankSel[12]  =  rD3 &  rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[13]  =  rD3 &  rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[14]  =  rD3 &  rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[15]  =  rD3 &  rD2 &  rD1 &  rD0 & ROMDec;
	

	// Logic to select Motherboard ROM Banks 0..3
	// GenBankSel[x] is the output of the 4..16 line decoder. Logic '1' if output is decoded
	assign nRomBankSel0_3  = !GenBankSel[0] & !GenBankSel[1] & !GenBankSel[2] & !GenBankSel[3];

	// Logic to select IntegraB ROM Banks 8..15
	// nRomBankSel[x] is logic '0' when bank is selected otherwire open collector
	assign nRomBankSel[8]  =  (GenBankSel[8]) ? 1'b0 : 1'bz;
	assign nRomBankSel[9]  =  (GenBankSel[9]) ? 1'b0 : 1'bz;
	assign nRomBankSel[10] =  (GenBankSel[10]) ? 1'b0 : 1'bz;
	assign nRomBankSel[11] =  (GenBankSel[11]) ? 1'b0 : 1'bz;
	assign nRomBankSel[12] =  (GenBankSel[12]) ? 1'b0 : 1'bz;
	assign nRomBankSel[13] =  (GenBankSel[13]) ? 1'b0 : 1'bz;
	assign nRomBankSel[14] =  (GenBankSel[14]) ? 1'b0 : 1'bz;
	assign nRomBankSel[15] =  (GenBankSel[15]) ? 1'b0 : 1'bz;

	assign RAMBank45_CE	  = !GenBankSel[4]  & !GenBankSel[5];
	assign RAMBank67_CE	  = !GenBankSel[6]  & !GenBankSel[7];
	assign Shadow_CE		  = ShadowSel;

	assign nDE	      	  =  !SWRAddr & !ShAct & !PrvAct & !FE3x
								  |  !nRomBankSel0_3 & !ShAct & !PrvAct & !FE3x; // this line ensures the IntegraB data buffer not active when accessing off board SWR

	//This data is latched when address is in the range FE30..FE33
	//rD0..rD3 are used to decode the selected SWROM bank
   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD0 <= 1'b0;
      end else if (!RnW && FE30_3) begin
         rD0 <= bbc_DATA[0];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD1 <= 1'b0;
      end else if (!RnW && FE30_3) begin
        rD1 <= bbc_DATA[1];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD2 <= 1'b0;
      end else if (!RnW && FE30_3) begin
         rD2 <= bbc_DATA[2];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD3 <= 1'b0;
      end else if (!RnW && FE30_3) begin
         rD3 <= bbc_DATA[3];
      end
   end

	//PrvEn is used in conjunction with addresses in the range &8000..& to select Private RAM
   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvEn <= 1'b0;
      end else if (!RnW && FE30_3) begin
         PrvEn <= bbc_DATA[6];
      end
   end
 
	always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         MemSel <= 1'b0;
      end else if (!RnW && FE30_3) begin
         MemSel <= bbc_DATA[7];
      end
   end


	//This data is latched when address is in the range FE34..FE37

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS8 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS8 <= bbc_DATA[4];
      end
   end
	
	always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS4 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS4 <= bbc_DATA[5];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS1 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS1 <= bbc_DATA[6];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         ShEn <= 1'b0;
      end else if (!RnW && FE34_7) begin
         ShEn <= bbc_DATA[7];
      end
   end

endmodule

User avatar
hoglet
Posts: 9617
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sun Nov 22, 2020 3:53 pm

Ken,

These lines look suspicious to me:

Code: Select all

	assign RTC_AS  = (FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && !Phi2);
	assign RTC_DS  = (FE3x && (bbc_ADDRESS[3:2] == 2'b11) && !Phi2);
In both cases, I would expect these to use Phi2 rather than !Phi2, so the strobe happens in the second half of the bus cycle, when all the 6502 signals are stable.

For the address strobe it actually doesn't matter, because the 6502 address is valid on both edges of Phi2. But for the data strobe, I'm really surprised this is working. The write is happening mid-cycle, rather than at the end of the cycle. The data must be barely stable at that point.

And also this (though I'm less sure about this, because I haven't followed the logic through):

Code: Select all

	assign ROMDec   =  (SWRAddr & !PrvAct & !Phi2
			|   SWRAddr & !PrvAct & !nROMBankSel0_3);
Dave

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 5:09 pm

You're absolutely right on both fronts. The RTC_AS and RTC_DS lines had previously been using !Phi1 and I did correctly change this to Phi2 when I swapped the clocks around earlier today. I switched briefly to !Phi2 when testing the DS12885 and forgot to switch this back before posting. ROMDec was also previously using !Phi1, and again I had correctly changed this to Phi2 when I swapped the clocks, but again switched this briefly when trying to establish why I was getting the OS 'Language ?' error when the DS12885 was plugged in. I think I now understand why I'm getting that error.

Earlier today I replaced the pull down resistor networks on the IntegraB data and address lines. They were originally 47k and I've replaced them with 4k7. Since doing that, if I try to read data an empty ROM bank it returns with the value 0. Previously it would typically return the value of the ROM bank. I think this is also what's happening when I try to read from the DS12885 RTC. If I run a *STATUS command, the command reports a value of 0 for every parameter. IBOS tries to start a language in Bank 0. Since there's nothing in Bank 0, the OS reports a 'Language?' error. What I need to establish now is why the DS12885 RTC is not putting any data onto the bus! I don't see these issues with the CDP6818. Everything works as expected.

Anyway, corrected CPLD code below:

Code: Select all

`timescale 1ns / 1ps
/************************************************************************
	 IntegraBV2.v

	 IntegraB V2 - A fully expanded ROM / RAM Board for BBC Micro
    Copyright (C) 2020 Ken Lowe

    IntegraBV2 is free software: you can redistribute it and/or modify
	 it under the terms of the GNU General Public License as published by
	 the Free Software Foundation, either version 3 of the License, or
	 (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	 Note:
	 This code is to interface CPLD Dev Board with an existing
	 V1 IntegraB Board. Not to be used on V2 IntegraB Board

	 Email: ken@skidog.co.uk

************************************************************************/
module IntegraBV2(
	input from_CPU_RnW,
	input from_CPU_Phi1,
	input from_CPU_dPhi2,
	input bbc_nRST,
	input [7:0] bbc_DATA,
	input [15:0] bbc_ADDRESS,

	output to_bbc_Phi1,
	output to_bbc_RnW,
	output to_bbc_rD0,
	output to_bbc_rD1,
	output nDE,
	output IntegraRnW,
	output nWDS,
	output nRDS,
	output nRomBankSel0_3,
	output [15:8] nRomBankSel,
	output RTC_AS,
	output RTC_DS,
	output RAM_CE,
	output RAMBank45_CE,
	output RAMBank67_CE,
	output Shadow_CE
	);


	// Repeat RnW & Phi1 from Input to Output
	wire Phi1;
	wire Phi2;
	wire ShAct;
	wire RnW;
	assign Phi1 = from_CPU_Phi1;
	assign Phi2 = from_CPU_dPhi2;
	assign RnW = from_CPU_RnW;
	assign to_bbc_Phi1 = !(!Phi1 & !ShAct);
	assign to_bbc_RnW = !(!RnW & !ShAct);
	assign IntegraRnW = !RnW;


	wire   FE3x = (bbc_ADDRESS[15:4] == 12'hFE3);
	wire   FE30_3  = FE3x && (bbc_ADDRESS[3:2] == 2'b00);
   wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01);
   wire   FE34    = FE3x && (bbc_ADDRESS[3:0] == 4'h4);
	assign RTC_AS  = (FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && Phi2);
	assign RTC_DS  = (FE3x && (bbc_ADDRESS[3:2] == 2'b11) && Phi2);
	
	assign nRDS = !( RnW & Phi2);
	assign nWDS = !(!RnW & Phi2);


	// If address is in range &8000..&BFFF then SWRAddr = 1, otherwise 0
	wire SWRAddr  =  (bbc_ADDRESS[15:14] == 2'b10);

	reg PrvEn;
	reg PrvS8;
	reg PrvS4;
	reg PrvS1;
	assign PrvAct    =   (((bbc_ADDRESS[15:12] == 4'h8) & (bbc_ADDRESS[11:10] == 2'b00) & PrvS1 & PrvEn)   //address decodes to &8000..&83FF
						  |    ((bbc_ADDRESS[15:12] == 4'h8) &  PrvS4 & PrvEn)   										 //address decodes to &8000..&8FFF
						  |    ((bbc_ADDRESS[15:12] == 4'h9) &  PrvS8 & PrvEn)											 //address decodes to &9000..&9FFF
						  |    ((bbc_ADDRESS[15:12] == 4'hA) &  PrvS8 & PrvEn));										    //address decodes to &A000..&AFFF


	reg ShEn;
	reg MemSel;

	// This logic sets ShAct to logic state '1' if the addresses in the screen range &3000..&7FFF and if Shadow Memory is active. 
	wire ScreenMem	  =   ((bbc_ADDRESS[15:12] == 4'h3)    //address decodes to &3000..&3FFF
							  | (bbc_ADDRESS[15:14] == 2'b01)); //address decodes to &4000..&7FFF
	assign ShAct     = ScreenMem & ShEn & !MemSel;

	// ShadowSel is logic '1' when either Shadow or Private RAM is being accessed. 
	wire ShadowSel   = !(!ShAct & !PrvAct);


	reg rD0;
	reg rD1;
	reg rD2;
	reg rD3;
	wire ROMDec;
	assign to_bbc_rD0  = rD0;
	assign to_bbc_rD1  = rD1;
	

	// The following logic is used to demux the ROM banks.
	// Banks 0..3 are located on the Beeb mainboard.
	// Banks 4..7 are SWRAM banks located on the IntegraB board
	// Banks 8..15 are ROM slots on the IntegraB board. 

	// Decode if address is in the range &8000..&BFFF and it's not Private RAM that's being accessed.
	wire   nROMBankSel0_3;
	assign ROMDec   =  (SWRAddr & !PrvAct & Phi2
						 |	  SWRAddr & !PrvAct & !nROMBankSel0_3);
	
	// GenBankSel[x] is logic '1' when bank is selected
	wire GenBankSel[15:0];
	assign GenBankSel[0]   = !rD3 & !rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[1]   = !rD3 & !rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[2]   = !rD3 & !rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[3]   = !rD3 & !rD2 &  rD1 &  rD0 & ROMDec;
	assign GenBankSel[4]   = !rD3 &  rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[5]   = !rD3 &  rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[6]   = !rD3 &  rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[7]   = !rD3 &  rD2 &  rD1 &  rD0 & ROMDec;
	assign GenBankSel[8]   =  rD3 & !rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[9]   =  rD3 & !rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[10]  =  rD3 & !rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[11]  =  rD3 & !rD2 &  rD1 &  rD0 & ROMDec;
	assign GenBankSel[12]  =  rD3 &  rD2 & !rD1 & !rD0 & ROMDec;
	assign GenBankSel[13]  =  rD3 &  rD2 & !rD1 &  rD0 & ROMDec;
	assign GenBankSel[14]  =  rD3 &  rD2 &  rD1 & !rD0 & ROMDec;
	assign GenBankSel[15]  =  rD3 &  rD2 &  rD1 &  rD0 & ROMDec;
	

	// Logic to select Motherboard ROM Banks 0..3
	// GenBankSel[x] is the output of the 4..16 line decoder. Logic '1' if output is decoded
	assign nRomBankSel0_3  = !GenBankSel[0] & !GenBankSel[1] & !GenBankSel[2] & !GenBankSel[3];

	// Logic to select IntegraB ROM Banks 8..15
	// nRomBankSel[x] is logic '0' when bank is selected otherwire open collector
	assign nRomBankSel[8]  =  (GenBankSel[8]) ? 1'b0 : 1'bz;
	assign nRomBankSel[9]  =  (GenBankSel[9]) ? 1'b0 : 1'bz;
	assign nRomBankSel[10] =  (GenBankSel[10]) ? 1'b0 : 1'bz;
	assign nRomBankSel[11] =  (GenBankSel[11]) ? 1'b0 : 1'bz;
	assign nRomBankSel[12] =  (GenBankSel[12]) ? 1'b0 : 1'bz;
	assign nRomBankSel[13] =  (GenBankSel[13]) ? 1'b0 : 1'bz;
	assign nRomBankSel[14] =  (GenBankSel[14]) ? 1'b0 : 1'bz;
	assign nRomBankSel[15] =  (GenBankSel[15]) ? 1'b0 : 1'bz;

	assign RAMBank45_CE	  = !GenBankSel[4]  & !GenBankSel[5];
	assign RAMBank67_CE	  = !GenBankSel[6]  & !GenBankSel[7];
	assign Shadow_CE		  = ShadowSel;

	assign nDE	      	  =  !SWRAddr & !ShAct & !PrvAct & !FE3x
								  |  !nRomBankSel0_3 & !ShAct & !PrvAct & !FE3x; // this line ensures the IntegraB data buffer not active when accessing off board SWR

	//This data is latched when address is in the range FE30..FE33
	//rD0..rD3 are used to decode the selected SWROM bank
   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD0 <= 1'b0;
      end else if (!RnW && FE30_3) begin
         rD0 <= bbc_DATA[0];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD1 <= 1'b0;
      end else if (!RnW && FE30_3) begin
        rD1 <= bbc_DATA[1];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD2 <= 1'b0;
      end else if (!RnW && FE30_3) begin
         rD2 <= bbc_DATA[2];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         rD3 <= 1'b0;
      end else if (!RnW && FE30_3) begin
         rD3 <= bbc_DATA[3];
      end
   end

	//PrvEn is used in conjunction with addresses in the range &8000..& to select Private RAM
   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvEn <= 1'b0;
      end else if (!RnW && FE30_3) begin
         PrvEn <= bbc_DATA[6];
      end
   end
 
	always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         MemSel <= 1'b0;
      end else if (!RnW && FE30_3) begin
         MemSel <= bbc_DATA[7];
      end
   end


	//This data is latched when address is in the range FE34..FE37

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS8 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS8 <= bbc_DATA[4];
      end
   end
	
	always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS4 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS4 <= bbc_DATA[5];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS1 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS1 <= bbc_DATA[6];
      end
   end

   always @(negedge Phi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         ShEn <= 1'b0;
      end else if (!RnW && FE34_7) begin
         ShEn <= bbc_DATA[7];
      end
   end

endmodule

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 7:51 pm

Well, that's interesting. I've got a batch of Maxim thru hole DS12885 RTCs, and a batch of Unitrode thru hole BQ3285 RTCs. A quick look over the data sheet and they appear to be identical products. However, every BQ3285 that I've tried in my development setup works, whereas every DS12885 that I've tried so far fails. I can't remember for sure, but I think they came from China, so I'm now wondering if I bought a dodgy batch. Either that, or there's some subtle timing difference between the two manufacturers that's throwing out my setup!

The SMD version of the BQ3285 is still an available product, which is a bonus. I might order a few and see if I can get those to work with my board, whilst I mess around with the DS12885.

Edit: And on the V2 IntegraB board I've found temporary a way to get Phi2 onto a global clock without having to cut and solder! I've now ported across all the changes we made on the Dev system to this V2 board with no ill effects. Everything that was working before is still working. I still can't communicate with the onboard DS12885, but that's not really a surprise, given that I can't even get it to work on the Dev system.

Next up I'm going to disable the onboard DS12885 and try to get an external BQ3285 working with it.

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sun Nov 22, 2020 10:12 pm

Success!!!!

That's me now got the offboard BQ3285 working with the V2 IntegraB board \:D/ \:D/ \:D/ \:D/

Since the RTC data bus is temporarily connected direct to the CPU data bus, I need to temporarily disable the IntegraB data buffer when accessing the RTC via the Address and Data strobes. That's why it wasn't working when I tried it yesterday. I needed to change the data buffer chip enable from:

Code: Select all

	wire   FE3x	  = (bbc_ADDRESS[15:4] == 12'hFE3);
	assign nDE	  =  !SWRAddr & !ShadowSel & !FE3x
			  |  !nRomBankSel0_3 & !ShadowSel & !FE3x; 
to:

Code: Select all

	wire   FE3x	  = (bbc_ADDRESS[15:4] == 12'hFE3);
	wire   FE30_7	  = FE3x && (bbc_ADDRESS[3] == 1'b0);
	assign nDE	  =  !SWRAddr & !ShadowSel & !FE30_7
			  |  !nRomBankSel0_3 & !ShadowSel & !FE30_7;
Even the DS12885 works on the V2 IntegraB board when hooked up directly to the CPU data bus. I'm not entirely sure why the DS12885 won't work behind the data buffer :?.

For those who are interested, here's a couple of photos showing my rather messy setup. One photo shows my CPLD development board hooked up to a V1 IntegraB board. This board has the standard 3 x 32k RAM ICs. The other photo shows my V2 IntegraB board with an offboard RTC wired in to it. This V2 board has more RAM than I know what to do with. All 16 ROM slots can be mapped to the RAM IC is 16k blocks. There's also 32k assigned to Shadow & Private RAM.
20201122_221438.jpg
V2 IntegraB board with temporary offboard RTC
20201122_221452.jpg
V1 IntegraB board with CPLD development board wired in

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Mon Nov 23, 2020 1:03 pm

Working on my machine with the V2 IntegraB board and offboard RTC... I've now wired the offboard RTC data bus so that it's on the IntegraB side of the data buffer (buffered from the CPU). In the CPLD I've put the data buffer chip enable code back to the original configuration, and it's working with both my external DS12885 & BQ3285!!!

I can only assume I've either got a faulty internal DS12885 RTC, or a bad solder connection. Time to investigate further.

I'm almost there. Within touching distance!

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Mon Nov 23, 2020 8:58 pm

This is a bit weird.

I'm testing with a remote SMT version of the DS12885 soldered onto a carrier board. It is hooked up into my V2 IntegraB board, and is using the buffered data bus. The various RTC I/O is wired as follows:
  • To get the 8 buffered data bus signals, I've plugged an adaptor board into one of the IntegraB ROM sockets.
  • The RST, IRQ & R/nW are coming directly from a CPU breakout board I built previously.
  • VBat is wired directly to the rechargeable battery.
  • CE is tied to Gnd.
  • The RTC_AS & RTC_DS are wired to two 'spare' outputs from the CPLD.
  • The oscillator inputs are routed to a SMD crystal that is pre-soldered onto the carrier board for this purpose.
This RTC works reliably.

I have exactly the same DS12885 RTC onboard and, except for the RTC_AS & RTC_DS signals and the two oscillator inputs, everything is wired to exactly the same I/O on the IntegraB board. This one doesn't work. The onboard RTC has even been replaced, because I managed to damage the original one when I was lifting one of the legs to test a theory. I'm confident that the soldering is good. There is good continuity between the RTC IC and the various test points on the IntegraB board. This one still doesn't work.

I don't understand why it's behaving differently :? ](*,) ](*,)

Edit: Do I perhaps need a bit of resistance on the data lines? Is this what I get with the remote RTC connected with dupont wires?

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Tue Nov 24, 2020 12:09 am

KenLowe wrote:
Mon Nov 23, 2020 8:58 pm
Edit: Do I perhaps need a bit of resistance on the data lines? Is this what I get with the remote RTC connected with dupont wires?
Right, switched back to my Dev machine, because I couldn't get the thru hole DS12885 RTC to work in that machine yesterday, and it's easier for me to add some series resistance into the data lines on that machine. Lowest value I had spare was 100R, so I stuck one in series with each of the data lines, and it looks like success! In fact, the entire batch of DS12885 ICs I couldn't get working yesterday are now all working today (well, apart from one that I can't get to work in either machine, so I suspect it's faulty). So that's both the DS12885 and the BQ1285 now working on that machine. Happy days!

Unfortunately, I can't see a particularly easy way to test this on my V2 IntegraB board because the RTC is surface mounted and I cant see any easy way to graft in the resistors. The track routing goes [CPU] -> [Data buffer] -> [..Stuff..] -> [ROM socket 13] -> [ROM socket 15] -> [RAM IC] -> [RTC]. I could possibly cut the tracks between socket 13 and 15 and jumper between the two sockets with the resistors, but this would also impact the RAM which is also surface mounted on the board. Thoughts?

More generally, does anyone have any comments on what I've done here to get the RTC working? Is that a reasonable solution. It kinda mirrors what's done on the data lines for the Tube & 1MHz level shifters. Is 100R a reasonable value to use in production, or should I drop that a bit?

Once again, TIA for any words of wisdom.

User avatar
daveejhitchins
Posts: 6004
Joined: Wed Jun 13, 2012 6:23 pm
Location: Newton Aycliffe, County Durham
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by daveejhitchins » Tue Nov 24, 2020 6:57 am

KenLowe wrote:
Tue Nov 24, 2020 12:09 am
More generally, does anyone have any comments on what I've done here to get the RTC working? Is that a reasonable solution. It kinda mirrors what's done on the data lines for the Tube & 1MHz level shifters. Is 100R a reasonable value to use in production, or should I drop that a bit?
Reflections . . . e.g. Fast edges being reflected back from a miss matched termination/line impedance. Usually around 33R to 68R is used. Long tracks suffer more from this issue. The addition of the resistor also acts as a low pass filter using the capacitance of the inputs of any ICs it's connected to.

Dave H.

User avatar
KenLowe
Posts: 1525
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Tue Nov 24, 2020 10:59 pm

daveejhitchins wrote:
Tue Nov 24, 2020 6:57 am
KenLowe wrote:
Tue Nov 24, 2020 12:09 am
More generally, does anyone have any comments on what I've done here to get the RTC working? Is that a reasonable solution. It kinda mirrors what's done on the data lines for the Tube & 1MHz level shifters. Is 100R a reasonable value to use in production, or should I drop that a bit?
Reflections . . . e.g. Fast edges being reflected back from a miss matched termination/line impedance. Usually around 33R to 68R is used. Long tracks suffer more from this issue. The addition of the resistor also acts as a low pass filter using the capacitance of the inputs of any ICs it's connected to.

Dave H.
Thanks for providing that detail. That's helpful. My level shifters are using 33R resistors, so I'll likely go with that. Those resistors have definitely made a positive impact, but unfortunately, once the machine has been running for perhaps 30 mins I started running into problems again and the RTC stopped responding. I tried adding a series resistor into the AS and DS lines, but that didn't make any difference. So now I've wired each of the AS and DS lines through two series inverters (I'm actually using NAND gates to get the invert function) and it's been running fine now for about 30 mins. It's still too early to tell if it's really made a difference, but fingers crossed [-o< [-o< [-o<.

It does appear that the timing is a bit marginal and once the machine warms up there's enough of a shift in the CPU clock timings to throw out the RTC. I'll try and capture this through some scope / logic analyser traces at the weekend. My guess is that these gates are delaying the strobe pulses enough to pull everything back in spec. Is there a way to do this on the CPLD instead? The fitter output slew rate is already set to slow.

Edit 1: So, after about an hour that's the DS12885 misbehaving again #-o. I don't think it's the DS12885 that's failing, because if I then swap it out for another one, it behaves the same. Leave the computer off for a while and it'll start working again. With everything still warm, I swapped out the CPU, but that didn't make any difference. I then swapped out the DS12885 for the BQ1285 and as before, it works just fine.

Edit 2: Interesting. If I disconnect the battery from RTC pin 16 and tie this input to Gnd, it starts working again. I think I see what might be happening, and it's nothing to do with temperature. The RTC datasheet indicates that the VBat input (pin 20) should not exceed 4v. I've just measured it, and it's currently sitting at 4.2v. I think what's happening is that when I switch off the computer for a period of time, the battery is discharging back down to the nominal 3.6v, VBat input is coming back within tolerance and the RTC starts working. When I switch the computer on, it recharges back up to greater than 4v, and that's when the RTC starts to fail.

The 4.2 volts that I measured seems a bit high for the Varta battery, which should sit at 3.6v. The charging circuit is a very simple resistor / diode arrangement and is a direct copy across from the original IntegraB board. I did previously consider using a non rechargeable battery for the RTC & backup RAM. Given what I've just discovered, I'll now need to rethink that.

Right now, I've connected the RTC VBat input to Gnd, and I'm powering the RTC directly from the battery instead. The datasheet says that Vcc should greater than 4v, so I'll see if the RTC has retained anything tomorrow morning once the battery has discharged back down to 3.6v. I know that's not a long term solution! I've also removed the additional inverters on the AS and DS lines, as they didn't seem to be doing much. I'll also remove the series resistors tomorrow and test again with those removed and VBat tied to Gnd.

Edit 3: Overnight, the battery voltage has dropped to 3.9v, which is just under the 4v threshold for the RTC Vcc, but it's still holding it's config and the oscillator is still running. The RTC is still responding, so I'm hopeful I've now found the culprit. I'm going to disable the charging circuit on the IntegraB board so I can reconnect the standard 5v to RTC pin 24 (Vcc) and the battery 3.6v feed to pin 20 (VBat), and test again with that configuration.
Last edited by KenLowe on Wed Nov 25, 2020 8:40 am, edited 1 time in total.

Post Reply

Return to “8-bit acorn hardware”