Help - Implementing Shadow RAM in CPLD

discuss both original and modern hardware for the bbc micro/electron
User avatar
BigEd
Posts: 3720
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by BigEd » Mon Nov 09, 2020 9:56 am

Might be worth noting that poking in Basic with the ? operator is an indexed operation (I think...) and so the sequence of accesses might not be quite what you expect. Might be worth trying a store absolute in assembly to see if there's any difference.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Tue Nov 10, 2020 1:12 am

BigEd wrote:
Mon Nov 09, 2020 9:56 am
Might be worth noting that poking in Basic with the ? operator is an indexed operation (I think...) and so the sequence of accesses might not be quite what you expect. Might be worth trying a store absolute in assembly to see if there's any difference.
Thank you for that piece of advice. Switching to assembly (LDA #&80:STA &FE34:RTS) gave me even stranger results. I've not figured out what's happening yet, so I've parked that for the time being. I'll come back to that once I've given it some further thought.

Earlier today it occurred to me that I shouldn't actually need a new prototype IntegraB board to test the CPLD. I've hooked up the CPLD dev board into one of my existing IntegraB boards (having removed most of the relevant discrete components), which should be sufficient to test out the Shadow RAM logic a bit more thoroughly. I'm just hoping that all these extra dupont jumper wires don't introduce too many other issues! I'll hook it up to my beeb tomorrow evening and see what happens...
20201110_005840.jpg
IntegraB with CDPL Development board attached

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Thu Nov 12, 2020 12:29 am

Well, that's been a bit more challenging that I thought it might be, but I've eventually got ROM decoding working on my development board. Currently I'm only decoding the ROMs on the main board. I'll try and get the onboard ROMs / RAM working tomorrow. I had a couple of data bus wires connected to the wrong pins on the development board, which was preventing the correct ROM decoding. That's now been fixed, and it's looking much better.

I'm actually surprised it's working at all, given the mess of dupont wires!

Oh, and the dog's been a big help!
20201112_001923.jpg
20201110_122343.jpg

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Thu Nov 12, 2020 6:16 pm

Made some further progress last night. ROM decoding is now fully working both on the IntegraB board and on the beeb main board, so all 16 banks are now available. Of these 16 banks, four are populated with RAM, and I can successfully read from and write to them, so it looks like nRDS and nWDS are both working fine.

On this journey, I did come across another problem with my Development board. Bit 5 on the databus was stuck low. I think I may have a solder bridge on the CPLD - the pin is next to a GND pin. I'll check that out later, but in the interim I've moved bit 5 over onto another pin and everything is working perfect.

That basically gets me back to where I was earlier in this thread with my V2 IntegraB board, so now onto the bit I'm really interested in; introducing shadow RAM to see how that behaves with this setup!

Edit: That's the Shadow RAM now also active, and it's behaving in the same way as my V2 IntegraB board, in that I can switch into Shadow RAM, but I can't switch out again unless I switch to a mode that sets HIMEM to &3000. That gives me hope that I should be able to fault find it easier now.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri Nov 13, 2020 9:08 am

I'm inching forward here. Earlier in this thread:
cmorley wrote:
Fri May 22, 2020 2:07 pm
KenLowe wrote:
Fri May 22, 2020 1:59 pm
...or am I misunderstanding the concept of 'clock', and are you suggesting that I shouldn't be using internal logic to generate the nFE30_4 signal that is used to clock the latch?
Yes. Do not do this. Use a global clock signal and a clock enable.
hoglet wrote:
Fri May 22, 2020 2:36 pm
Ken,

Here's a complete example that shows how I would re-write the fragment above:

Code: Select all

module test
  (
   Phi2,
   RnW,
   bbc_nRST,
   bbc_ADDRESS,
   bbc_DATA
   );

   input        Phi2;
   input        RnW;
   input        bbc_nRST;
   input [15:0] bbc_ADDRESS;
   inout [7:0]  bbc_DATA;

   wire         FE3x = (bbc_ADDRESS[15:4] == 12'hFE3);

   wire         FE34_7 = FE3x && (bbc_ADDRESS[3:2] == 2'b01);

   reg          ShEn;

   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

   assign bbc_DATA = (RnW && Phi2 && FE34_7) ? {ShEn, 7'b0000000} : 8'hZZ;

endmodule
For small designs like this, I don't find 1-bit wide submodules helps at all. It's far better to describe the behaviour you want in RTL Verilog.

Also, there is no need (or benefit) to expressing active-low versions of FE3x.

If anything is not clear in the above example, please ask. There's probably several other people following this thread as well.

If you want to post a more complete example, I'm happy to keep helping. I've been doing a lot of RTL Verilog in the last few days,

Dave
I've now moved Phi2 over to pin 22 on the CPLD which is GCK1. The behaviour is different, but still not 100% correct. What now happens is if I ?&FE34=128, further text is not repeated to screen (as I would expect). However, after typing a few characters, text does start to appear on screen again - as if shadow mode has been disabled again (which would normally be done with ?&FE34=0). I need to establish why that is happening! I'm conscious that it may still be related to the point BigEd raised earlier.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri Nov 13, 2020 9:28 am

Ken,

The XC9500XL parts are very sensitive to noise on the clock; it takes very little noise to cause additional phantom clock transitions. I think with your remote CPLD board connected with Dupont wires, noise is likely to be a significant issue.

All of the recent problems Roland had with YARRB are down to this issue of clock noise, and the symptoms it can cause are often very bizarre, like counters skipping a count, or even getting stuck.

This can be compounded if the clock has slow edges, as the CPLD input buffers appear to have very little hysteresis. The Phi1 and Phi2 clocks from NMOS 6502 can often have a really slow rising edge. So if these are being used directly by the CPLD then it can make things worse.

I would suggest probing the clock as close to the CPLD as possible; you may even find that the additional capacitance from the scope probe changes the observed behaviour.

Also, it would help those of us following along if you could publish the latest version of your HDL design (and ideally also the schematics). Without these, it's difficult to really make useful suggestions.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by BeebMaster » Fri Nov 13, 2020 9:50 am

Was the dog a lot of help? I usually find ours a hindrance.
Image

cmorley
Posts: 1400
Joined: Sat Jul 30, 2016 8:11 pm
Location: Oxford
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by cmorley » Fri Nov 13, 2020 9:58 am

Further to Hoglet's point about slow edges, poor signal integrity can ruin your day with modern fast programmable logic.

For example the outputs of CPLDs have such high transition speeds that you're likely to see coupling to other signals unless you specifically do something to mitigate it. This can couple to clocks to give you spurious clock transitions and weird behaviour. On a scope such pulses might not even look like they reach the logic level thresholds they are so narrow (<5ns).

Ramtop
Posts: 263
Joined: Tue Oct 23, 2018 1:40 pm
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by Ramtop » Fri Nov 13, 2020 10:38 am

I'll second that. There were some bizarre random issues with early revisions of my ElkSD boards on some Electrons that had me pulling my hair out, and the root cause was the XC9536XL it uses being thrown off by a noisy clock. Running the Electron's clocks through a Schmitt trigger buffer fixed the problem completely.
Gary

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri Nov 13, 2020 7:41 pm

Thank you all for the comments. I do very much appreciate all the help I'm getting, but I think I'm hitting the limits of my capabilities here, and I may have to give up on this shortly. But for now, I persevere...
hoglet wrote:
Fri Nov 13, 2020 9:28 am
The XC9500XL parts are very sensitive to noise on the clock; it takes very little noise to cause additional phantom clock transitions. I think with your remote CPLD board connected with Dupont wires, noise is likely to be a significant issue.

All of the recent problems Roland had with YARRB are down to this issue of clock noise, and the symptoms it can cause are often very bizarre, like counters skipping a count, or even getting stuck.

This can be compounded if the clock has slow edges, as the CPLD input buffers appear to have very little hysteresis. The Phi1 and Phi2 clocks from NMOS 6502 can often have a really slow rising edge. So if these are being used directly by the CPLD then it can make things worse.
The risk of introducing noise was an issue I was concerned about and I briefly mentioned it in this post but, TBH, other than trial and error with different layouts of IntegraB prototype boards I wasn't entirely sure how else to progress. The trial and error route would likely be quite an expensive route for me to go down!

For the clock signals running between the IntegraB board and the development board, dp11 had previously suggested that I use 2 cores twisted together and ground one of the cores. That is definitely something I can try; albeit I'm not entirely sure how I'm going to common up all my ground signals yet. I'll make something up.
hoglet wrote:
Fri Nov 13, 2020 9:28 am
Also, it would help those of us following along if you could publish the latest version of your HDL design (and ideally also the schematics). Without these, it's difficult to really make useful suggestions.
Sorry about that. I'm trying to find a balance between posting too much, and too little information. I'm more than happy to post up all the schematics and the latest CPLD code. I'll do that tomorrow.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri Nov 13, 2020 9:22 pm

Ramtop wrote:
Fri Nov 13, 2020 10:38 am
I'll second that. There were some bizarre random issues with early revisions of my ElkSD boards on some Electrons that had me pulling my hair out, and the root cause was the XC9536XL it uses being thrown off by a noisy clock. Running the Electron's clocks through a Schmitt trigger buffer fixed the problem completely.
I've just been having a good look at the clock signals. On the original IntegraB board the Phi2 clock passes through a small RC network before then being used in a GAL22V10 PLD. The resistor has a diode wired in parallel. I think the purpose of this circuit is charge the capacitor via the resistor on the rising edge of Phi2, and discharge it immediately on the falling edge via the diode. In effect offsetting the point at which the downstream logic recognises the rising edge as a logic 1. Whilst this seems to work fine with the original IntegraB when that delayed signal is wired into the GAL, the CPLD doesn't seem to like it as much. I just tried wiring the signal through a standard 7404 inverter, but I got a lot of ringing, so I'll try a Schmitt trigger buffer and see if that fixes it for me too.

Yellow trace: Phi2 from the CPU (referred to as zPhi2 in schematic)
Cyan trace: Phi2 measured downstream of the RC network (referred to as dPhi2 in schematic). This signal is wired into GCK1 on the CPLD
Magenta trace: Repeat output of dPhi2 from the CPLD
DS1Z_QuickPrint26.png
Phi2 trace
IC10.PNG
zPhi2 / dPhi2 on original IntegraB board

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri Nov 13, 2020 10:33 pm

Gosh, the CPLD clocks looks truly awful, I'm not surprised it doesn't work well.

How/where are you connecting the scope ground when you made those measurements?

Part of the problem is the RC filter values (270pF/1K) are quite large. They form a low pass filter with a cutoff frequency of about 600KHz. Because of this, the clock signal into the CPLD barely reaches 2V, has slow edges, and is very phase shifted. None of this is good for a fast CPLD!

I would reduce both values; I've found that 47pF / 120R works well to remove high frequency switching noise.

But really the problem here is the CPLD board dangling off a set of dupont cables, with just one or two ground wire. I think you need to move to a PCB with a reasonable ground plane to have any chance of this working reliably.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri Nov 13, 2020 10:41 pm

So, this is what's happening with my latch:

Code: Select all

   always @(negedge 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
Yellow trace: bbc_DATA[7]
Cyan trace: ShEn
Magenta trace: dPhi2
Blue trace: Phi2

The top trace is when I set data bit 7 high. I can see this latches data bit 7 into ShEn on the falling edge of dPhi2 (when FE34 is on the address bus). This is what I would expect.

The lower trace is when I then set data bit 7 low. Here I can see that ShEn briefly drops off but then latches high again - even though data bit 7 is low at this point. This is not what I would expect.
DS1Z_QuickPrint27.png
?&FE34=&80
DS1Z_QuickPrint28.png
?&FE34=&00

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri Nov 13, 2020 10:51 pm

hoglet wrote:
Fri Nov 13, 2020 10:33 pm
Gosh, the CPLD clocks looks truly awful, I'm not surprised it doesn't work well.

How/where are you connecting the scope ground when you made those measurements?

Part of the problem is the RC filter values (270pF/1K) are quite large. They form a low pass filter with a cutoff frequency of about 600KHz. Because of this, the clock signal into the CPLD barely reaches 2V, has slow edges, and is very phase shifted. None of this is good for a fast CPLD!

I would reduce both values; I've found that 47pF / 120R works well to remove high frequency switching noise.

But really the problem here is the CPLD board dangling off a set of dupont cables, with just one or two ground wire. I think you need to move to a PCB with a reasonable ground plane to have any chance of this working reliably.

Dave
I've connected the ground tab on the scope directly to a Gnd connection on the PSU. I'm not using the Gnd clips on the scope leads. I'm not sure if that's the best way to set it up, but it didn't seem to make much difference either way.

Regarding the RC filter, I assumed this was in place to deliberately introduce a phase shift and not for removing high frequency noise, but I could be wrong on that point. I can certainly change the resistor and capacitor to see if that makes any difference.

I do have a board with the CPLD directly soldered on. That's where I started. However, I couldn't get this board to work and struggled to fault find as I didn't have any reasonable means to connect the scope probes. I've have a think about the simplest way to get the best of both!

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri Nov 13, 2020 11:06 pm

KenLowe wrote:
Fri Nov 13, 2020 10:41 pm
The lower trace is when I then set data bit 7 low. Here I can see that ShEn briefly drops off but then latches high again - even though data bit 7 is low at this point. This is not what I would expect.
It's not what I would expect either...

Even with phantom clock pulses (which the top trace clearly shows), I don't see why ShEN should be going back high again, sd bbc_data[7] is clearly low on the second clock edge.

What exactly is bbc_data[7] connected to on the BBC side?

It doesn't look right for D7 on the 6502.

Can you double-check where the yellow trace is connected to?

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri Nov 13, 2020 11:22 pm

hoglet wrote:
Fri Nov 13, 2020 11:06 pm
KenLowe wrote:
Fri Nov 13, 2020 10:41 pm
The lower trace is when I then set data bit 7 low. Here I can see that ShEn briefly drops off but then latches high again - even though data bit 7 is low at this point. This is not what I would expect.
It's not what I would expect either...

Even with phantom clock pulses (which the top trace clearly shows), I don't see why ShEN should be going back high again, sd bbc_data[7] is clearly low on the second clock edge.

What exactly is bbc_data[7] connected to on the BBC side?

It doesn't look right for D7 on the 6502.

Can you double-check where the yellow trace is connected to?

Dave
Sorry Dave. I'm only giving you half the story here. There is a 74HCT245 data buffer sitting between the beeb / CPU and the IntegraB / CPLD. I'll post up the full schematic tomorrow, but here's a snip from the schematic. I've got the scope connected to pin 11 of IC3. Also worth pointing out that the data buffer outputs are only enabled when accessing onboard SWR (address &8000..&BFFF), or onboard shadow / private RAM (&3000..&AFFF), or writing to &FE3x. I'm guessing there is some kind of pull up happening on the CPLD input which is why we see the D7 signal sit at just under 3v for a period of time (ie when the data buffer outputs are disabled), even though I've got pull down resistors on the data bus:

Code: Select all

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
6502.PNG
CPU & Buffers
CPLD.PNG
Original CPLD layout

cmorley
Posts: 1400
Joined: Sat Jul 30, 2016 8:11 pm
Location: Oxford
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by cmorley » Sat Nov 14, 2020 7:19 am

KenLowe wrote:
Fri Nov 13, 2020 10:51 pm
I've connected the ground tab on the scope directly to a Gnd connection on the PSU. I'm not using the Gnd clips on the scope leads. I'm not sure if that's the best way to set it up, but it didn't seem to make much difference either way.
No this is not the best setup. It is about the worst you can do TBH. You should use the ground reference for that signal, in this case the ground of the CPLD, or as close to that as possible. You are measuring "signal" which contains return currents from totally unrelated things.

So for a dodgy clock on a chip you need to probe the clock chip pin and use the chip ground.

The little springs that come with the scope probes are the best. Even the loops of the corocodile ground clips will introduce ringing and garbage that does not exist other than in your measurement.

You can debug using the CPLD too... for example add a counter to your CPLD. Output the lower bits on spare pins. Connect the LSB (at least) to the scope and the clock to the scope. Turn on persistence (10s or infinite). Do you get 1 count per clock cycle or stray random counts?

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 14, 2020 12:19 pm

cmorley wrote:
Sat Nov 14, 2020 7:19 am
KenLowe wrote:
Fri Nov 13, 2020 10:51 pm
I've connected the ground tab on the scope directly to a Gnd connection on the PSU. I'm not using the Gnd clips on the scope leads. I'm not sure if that's the best way to set it up, but it didn't seem to make much difference either way.
No this is not the best setup. It is about the worst you can do TBH. You should use the ground reference for that signal, in this case the ground of the CPLD, or as close to that as possible. You are measuring "signal" which contains return currents from totally unrelated things.

So for a dodgy clock on a chip you need to probe the clock chip pin and use the chip ground.

The little springs that come with the scope probes are the best. Even the loops of the crocodile ground clips will introduce ringing and garbage that does not exist other than in your measurement.

You can debug using the CPLD too... for example add a counter to your CPLD. Output the lower bits on spare pins. Connect the LSB (at least) to the scope and the clock to the scope. Turn on persistence (10s or infinite). Do you get 1 count per clock cycle or stray random counts?
Thanks for the pointers. I've tidied up the dupont wiring a bit this morning and I've now connected the probe ground to ground connections on the CPLD development board (using the crocodile ground clips).

I'm not wanting to go too far down a rabbit hole here, but I've been playing around with the persistence setting on the scope and noticed some behaviour that I wasn't expecting. Can someone confirm if the 2MHz clock signal that is presented to the CPU (pin 37) can be stalled by other hardware? As is visible on the trace below, the 2MHz signal into the CPU seems to miss a cycle periodically, and when this happens it appears that the capacitor on my Phi2 circuit is being allowed to charge to a higher voltage before being reset by the next falling edge of Phi2.I had a quick look at the beeb circuit diagram and notice that there's a fair bit of latching circuitry on the 2MHz signal from the vid processor, which I suspect is what's causing this. I don't think this extra charge on the capacitor and occasional higher voltage on dPhi2 is having an overall impact, but I might be wrong.

Yellow trace: 2MHz signal on CPU pin 37
Cyan trace: dPhi2. This is monitoring the dPhi2 signal after the RC circuit
Magenta trace: Repeat output of dPhi2 from the CPLD
Blue trace: Phi2 out from CPU pin 39. This feeds into the RC circuit, which generates dPhi2
DS1Z_QuickPrint29.png
Beeb clock signals
In this next capture, the Blue trace is the 2MHz signal from pin 5 on the vid proc. There is no evidence of missed cycles on this signal which makes me suspect the latching circuit between the vid proc and the CPU is introducing these missed cycles.
DS1Z_QuickPrint30.png
More beeb clock signals

cmorley
Posts: 1400
Joined: Sat Jul 30, 2016 8:11 pm
Location: Oxford
Contact:

Re: Help - Implementing Shadow RAM in CPLD

Post by cmorley » Sat Nov 14, 2020 12:30 pm

KenLowe wrote:
Sat Nov 14, 2020 12:19 pm
Can someone confirm if the 2MHz clock signal that is presented to the CPU (pin 37) can be stalled by other hardware?
The CPU clock changes clock domain to 1MHzE when there is a 1Mhz device access.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 14, 2020 12:33 pm

cmorley wrote:
Sat Nov 14, 2020 12:30 pm
KenLowe wrote:
Sat Nov 14, 2020 12:19 pm
Can someone confirm if the 2MHz clock signal that is presented to the CPU (pin 37) can be stalled by other hardware?
The CPU clock changes clock domain to 1MHzE when there is a 1Mhz device access.
Right. That makes sense and explains what I'm seeing - particularly with the clock signal after my RC circuit. Thank you.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sat Nov 14, 2020 1:11 pm

Ken,

The CPLD code you posted earlier is using the falling edge of the clock to latch the write data. Adding a significant delay to the CPLD clock (cf the CPU Phi2 clock) is going to compromise the operation of this circuit, because the 6502 does not guarantee the write data is held for very long after the falling edge (tHW is 30ns).

Also, any time the voltage on CPLD clock is close to the switching threshold of the CPLD (typically about 1.65V), the CPLD is much more likely to see small amounts of additional noise as clock transitions, because the CPLD inputs don't have much hysteresis. Looking at the cyan waveform, it has slow edges, and it only barely reaches the switching threshold. Both of these things are bad.

The blue waveform (Phi2 from the CPU) would be a much better clock for the CPLD. There is still some noise when the clock is low, but you might get away with that.

I would suggest getting rid of the RC circuit, or at least drastically reduce the component values (e.g. 47pF/120R)

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 14, 2020 3:03 pm

hoglet wrote:
Sat Nov 14, 2020 1:11 pm
The CPLD code you posted earlier is using the falling edge of the clock to latch the write data. Adding a significant delay to the CPLD clock (cf the CPU Phi2 clock) is going to compromise the operation of this circuit, because the 6502 does not guarantee the write data is held for very long after the falling edge (tHW is 30ns).
I have previously tried using the rising edge of dPhi2, but this didn't work properly either:

Code: Select all

always @(posedge dPhi2 or negedge bbc_nRST) begin
In the original IntegraB board, this delayed clock signal is very deliberately being used to latch the data bus when the address is either &FE30 (for ROMSEL) or &FE34 (to switch in Shadow and Private RAM). In both cases this is being done with a 74HCT174 but TBH I'm not sure if the 74HCT174 latches on a rising or falling edge. It seems to work absolutely fine for &FE30. I just can't work out why &FE34 is behaving differently. There is a subtle difference in that when Shadow RAM is active (data bit 7 set, and latched by &FE34), CPU output 3 (Phi1Out) and CPU output 34 (R/W) are both intercepted by the CPLD and held high if the address bus is in the range of screen memory (&3000..&7FFF).

Hmmm. Thinking about this, the way the logic is written is probably not the best:

Code: Select all

assign to_bbc_Phi1 = !(!Phi1 & !ShAct);
assign to_bbc_RnW = !(!RnW & !ShAct);
Should this be written differently, so that it uses a global clock?
hoglet wrote:
Sat Nov 14, 2020 1:11 pm
I would suggest getting rid of the RC circuit, or at least drastically reduce the component values (e.g. 47pF/120R)
Dave
I'll certainly try that. Is there any harm in using Phi1Out (CPU pin 3) instead of Phi2 (other than the need to possibly invert), as I already have this wired into the CPLD?

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sat Nov 14, 2020 3:15 pm

KenLowe wrote:
Sat Nov 14, 2020 3:03 pm

Code: Select all

assign to_bbc_Phi1 = !(!Phi1 & !ShAct);
assign to_bbc_RnW = !(!RnW & !ShAct);
Should this be written differently, so that it uses a global clock?
Sorry, but I would need to thee the whole design.

This is where working it github saves a lot of time, and confusion, because everyone is looking at the same code.
KenLowe wrote:
Sat Nov 14, 2020 3:03 pm
I'll certainly try that. Is there any harm in using Phi1Out (CPU pin 3) instead of Phi2 (other than the need to possibly invert), as I already have this wired into the CPLD?
On the Beeb Phi1 is very heavily loaded, and has a very slow rising edge (>100ns), making the sampling point very indeterminate. So normally I would say using this as a CPLD clock is asking for trouble.

But in your case I think Phi1 from the 6502 is buffered by the Integra, so the Phi1 into the CPLD only drives the CPLD.

If so, then it should be OK, but it is introducing another variable into an already complicated system.

(The other consideration is the active edge would now be the rising edge, which is typically slower anyway)

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 14, 2020 10:02 pm

hoglet wrote:
Sat Nov 14, 2020 3:15 pm
KenLowe wrote:
Sat Nov 14, 2020 3:03 pm

Code: Select all

assign to_bbc_Phi1 = !(!Phi1 & !ShAct);
assign to_bbc_RnW = !(!RnW & !ShAct);
Should this be written differently, so that it uses a global clock?
Sorry, but I would need to thee the whole design.

This is where working it github saves a lot of time, and confusion, because everyone is looking at the same code.
Point well made. I really need to spend some time trying to get to grips with Github. In the interim, I'll try and post up the latest version of code shortly.
hoglet wrote:
Sat Nov 14, 2020 3:15 pm
KenLowe wrote:
Sat Nov 14, 2020 3:03 pm
I'll certainly try that. Is there any harm in using Phi1Out (CPU pin 3) instead of Phi2 (other than the need to possibly invert), as I already have this wired into the CPLD?
On the Beeb Phi1 is very heavily loaded, and has a very slow rising edge (>100ns), making the sampling point very indeterminate. So normally I would say using this as a CPLD clock is asking for trouble.

But in your case I think Phi1 from the 6502 is buffered by the Integra, so the Phi1 into the CPLD only drives the CPLD.

If so, then it should be OK, but it is introducing another variable into an already complicated system.

(The other consideration is the active edge would now be the rising edge, which is typically slower anyway)

Dave
Kind of. Phi1 from the CPU is wired directly into the CPLD and is connected to nothing else. A conditioned Phi1 signal is then spat back out of the CPLD and drives the rest of the beeb Phi1 clock circuitry.

On an unrelated point - Does OS1.2 read from or write to addresses in the range &FE34..&FE3F? My CPLD is decoding address &FE34 and I've wired that to a CPLD output, so I can monitor it on the scope. I'm seeing the output spike when I press a key on the keyboard - from the Basic command prompt, and also when running a ARM113 utility (*REX). It looks like a fast transient glitch as the clock switches from 2MHz to 1Mhz.

Yellow trace: d7 (irrelevant here)
Cyan trace: ShEn signal which is the latched d7 signal when the address is &FE34 (again, irrelevant here)
Magenta trace: Output from CPLD. High when address is &FE34, otherwise low.
Blue trace: Phi1 output from CPU (pin3).

The scope is set to trigger on a change of state of &FE34, and it's triggering on every key press.
DS1Z_QuickPrint34.png
FE34 spike
DS1Z_QuickPrint35.png
Zoomed in
Last edited by KenLowe on Sat Nov 14, 2020 10:11 pm, edited 1 time in total.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sat Nov 14, 2020 10:10 pm

KenLowe wrote:
Sat Nov 14, 2020 10:02 pm
On an unrelated point - Does OS1.2 read from or write to addresses in the range &FE34..&FE3F? My CPLD is decoding address &FE34 and I've wired that to a CPLD output, so I can monitor it on the scope. I'm seeing the output spike when I press a key on the keyboard - from the Basic command prompt, and also when running a ARM113 utility (*REX). It looks like a fast transient glitch as the clock switches from 2MHz to 1Mhz.
No, OS1.20 only accesses FE30 in that range.

What you are seeing is when the address bus changes from one address to another, it happens to transiently pass through an address in the &FE34..&FE3F range, due to the individual address bits changing at slightly different times.

We saw the same sort of glitches on nTUBE in PiTubeDirect.

It's very much processor dependent, and you need to make sure your design ignores them. You can see why it would be a bad idea to ever used that signal as a clock. A common technique to remove the glitches is to AND the decoded signal with PHI2, because the address bus is guaranteed to be stable while Phi2 is high.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 14, 2020 10:31 pm

hoglet wrote:
Sat Nov 14, 2020 10:10 pm
KenLowe wrote:
Sat Nov 14, 2020 10:02 pm
On an unrelated point - Does OS1.2 read from or write to addresses in the range &FE34..&FE3F? My CPLD is decoding address &FE34 and I've wired that to a CPLD output, so I can monitor it on the scope. I'm seeing the output spike when I press a key on the keyboard - from the Basic command prompt, and also when running a ARM113 utility (*REX). It looks like a fast transient glitch as the clock switches from 2MHz to 1Mhz.
No, OS1.20 only accesses FE30 in that range.

What you are seeing is when the address bus changes from one address to another, it happens to transiently pass through an address in the &FE34..&FE3F range, due to the individual address bits changing at slightly different times.

We saw the same sort of glitches on nTUBE in PiTubeDirect.

It's very much processor dependent, and you need to make sure your design ignores them. You can see why it would be a bad idea to ever used that signal as a clock. A common technique to remove the glitches is to AND the decoded signal with PHI2, because the address bus is guaranteed to be stable while Phi2 is high.

Dave
Thanks. That's confirmed what I suspected. The logic does indeed use Phi2 & R/W when decoding &FE34.

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
At least, I think that's what it's doing. Or should I also update the decoded FE34_7 signal to inlcude an AND with Phi2?

Could this also be the reason there is an RC circuit on the on the Phi2 signal on the original IntegraB board?

I was trying to use the decoded &FE34 as a scope trigger to work out why the ShEn latch is misbehaving.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat Nov 14, 2020 11:46 pm

Right, this seems to be working for me:

Code: Select all

   wire   FE3x = (bbc_ADDRESS[15:4] == 12'hFE3);
   wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01)  && !Phi1;

   always @(negedge 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
No more &FE34 glitches, and my latch now seems to be toggling correctly. I think this is as far as I've ever got!

Yellow trace: buffered d7
Cyan trace: ShEn signal which is the latched d7 signal when the address is &FE34 AND Phi1 is low
Magenta trace: Output from CPLD. High when address is &FE34 AND Phi1 is low, otherwise low.
Blue trace: Phi1 output from CPU (pin3).
DS1Z_QuickPrint36.png
LDA#&80:STA&FE34:RTS
DS1Z_QuickPrint37.png
LDA#&00:STA&FE34:RTS

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Sun Nov 15, 2020 7:40 am

KenLowe wrote:
Sat Nov 14, 2020 11:46 pm

Code: Select all

   wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01)  && !Phi1;
The && !Phi1 change really should not have been necessary.

FE34_7 is not being used as a clock, so the glitches should be harmless.

I can think of two explanations for why this in fact helped:
1. There are phantom clock transitions, and this change fudged things in the case of writing a zero.
2. The glitch itself was getting coupled back to Phi2 (through the wiring and shared ground paths) causing an additional clock transition.

Neither of these things bode well as you extend the design and more outputs switch.

This scope plot you posted earlier clearly shows a phantom clock transiton:
DS1Z_QuickPrint28.png
(the falling edge of the cyan trace is co-incident with the glitch in the cpld clock)

Is the RC network still present on Phi2?

Dave

User avatar
KenLowe
Posts: 1621
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 12:59 pm

Folks, I really appreciate your support on this. I would be struggling without your guidance.
hoglet wrote:
Sun Nov 15, 2020 7:40 am
KenLowe wrote:
Sat Nov 14, 2020 11:46 pm

Code: Select all

   wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01)  && !Phi1;
The && !Phi1 change really should not have been necessary.

FE34_7 is not being used as a clock, so the glitches should be harmless.

I can think of two explanations for why this in fact helped:
1. There are phantom clock transitions, and this change fudged things in the case of writing a zero.
2. The glitch itself was getting coupled back to Phi2 (through the wiring and shared ground paths) causing an additional clock transition.

Neither of these things bode well as you extend the design and more outputs switch.

This scope plot you posted earlier clearly shows a phantom clock transiton:
DS1Z_QuickPrint28.png
(the falling edge of the cyan trace is co-incident with the glitch in the cpld clock)

Is the RC network still present on Phi2?

Dave
Dave - In response to your query, the RC network is still in place, but I am intermittently shorting out the resistor and testing both cases. I know that I should really be removing the capacitor at the same time, but I've not got as far as doing that yet. When I reported the step forward last night, that was with the RC network still active.

However, today I have made a much bigger step forward! I was cleaning up the CPLD code to post in this thread, when I noticed something that looked wrong:

Code: Select all

 assign nWDS = !((!RnW & !Phi1 & !RamBankSel[4])
		|   (!RnW & !Phi1 & !RamBankSel[5])
		|   (!RnW & !Phi1 & !RamBankSel[6])
		|   (!RnW & !Phi1 & !RamBankSel[7])
			);
My Shadow / Private RAM chip was never being write enabled! Aaaaagh #-o #-o! So, I simplified that down to:

Code: Select all

 assign nWDS = !(!RnW & !Phi1);
and now I'm able to switch in Shadow RAM with ?&FE34=&80, and switch out with ?&FE34=&00 in ALL screen modes. The Phi2 RC network is still active, but I'll have a look at that shortly.

Next up is to figure out why I can't communicate with the RTC. Hopefully that will be an easier fix. I'll also maybe switch back to my V2 IntegraB board to see if it will work correctly with the nWDS fix...

For reference, this is what the CPLD code currently looks like:

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/>.

	 Email: xxxxxx@xxxxxxxx.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,
	input [15:0] RamWriteProt,
	input [15:8] IntegraRomSel,
	input [3:0] BeebRomSel,

	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 Monitor1,
	output Monitor2,
	output RAM_CE,
	output RAMBank45_CE, //temp for dev testing
	output RAMBank67_CE, //temp for dev testing
	output Shadow_CE, //temp for dev testing
	output [18:14] Ram_ADDRESS
	);


	// Repeat RnW & Phi1 from Input to Output
	wire Phi1;
	wire dPhi2;
	wire ShAct;
	wire RnW;
	assign Phi1 = from_CPU_Phi1;
	assign dPhi2 = 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 && !Phi1;
	assign RTC_DS  = FE3x && (bbc_ADDRESS[3:2] == 2'b11);
	
	wire   RamBankSel[15:0];

	assign nRDS = !( RnW & !Phi1);
	assign nWDS = !(!RnW & !Phi1);

	// This code looks wrong. nWDS needs to be active for Private and Shadown RAM too!
	// assign nWDS = !((!RnW & !Phi1 & !RamBankSel[4])
	// 				|   (!RnW & !Phi1 & !RamBankSel[5])
	// 				|   (!RnW & !Phi1 & !RamBankSel[6])
	// 				|   (!RnW & !Phi1 & !RamBankSel[7])
	// 					);


	//	assign nWDS = !((!RnW & !Phi1 & !RamBankSel[0]  & !RamWriteProt[0]  & !BeebRomSel[0])
	//					|   (!RnW & !Phi1 & !RamBankSel[1]  & !RamWriteProt[1]  & !BeebRomSel[1])
	//					|   (!RnW & !Phi1 & !RamBankSel[2]  & !RamWriteProt[2]  & !BeebRomSel[2])
	//					|   (!RnW & !Phi1 & !RamBankSel[3]  & !RamWriteProt[3]  & !BeebRomSel[3])
	//					|   (!RnW & !Phi1 & !RamBankSel[4]  & !RamWriteProt[4])
	//					|   (!RnW & !Phi1 & !RamBankSel[5]  & !RamWriteProt[5])
	//					|   (!RnW & !Phi1 & !RamBankSel[6]  & !RamWriteProt[6])
	//					|   (!RnW & !Phi1 & !RamBankSel[7]  & !RamWriteProt[7])
	//					|   (!RnW & !Phi1 & !RamBankSel[8]  & !RamWriteProt[8]  & !IntegraRomSel[8])
	//					|   (!RnW & !Phi1 & !RamBankSel[9]  & !RamWriteProt[9]  & !IntegraRomSel[9])
	//					|   (!RnW & !Phi1 & !RamBankSel[10] & !RamWriteProt[10] & !IntegraRomSel[10])
	//					|   (!RnW & !Phi1 & !RamBankSel[11] & !RamWriteProt[11] & !IntegraRomSel[11])
	//					|   (!RnW & !Phi1 & !RamBankSel[12] & !RamWriteProt[12] & !IntegraRomSel[12])
	//					|   (!RnW & !Phi1 & !RamBankSel[13] & !RamWriteProt[13] & !IntegraRomSel[13])
	//					|   (!RnW & !Phi1 & !RamBankSel[14] & !RamWriteProt[14] & !IntegraRomSel[14])
	//					|   (!RnW & !Phi1 & !RamBankSel[15] & !RamWriteProt[15] & !IntegraRomSel[15])
	//						);


	// 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;
	assign Monitor1  = FE34_7;
	assign Monitor2  = 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. These banks can be switched out for SWRAM on the IntegraB board instead
	// Banks 4..7 are SWRAM banks located on the IntegraB board
	// Banks 8..15 are ROM slots on the IntegraB board. These banks can be switched out for SWRAM on the IntegraB board instead
	// All SWRAM can be write protected in 16k banks.

	// Decode if address is in the range &8000..&BFFF and it's not Private RAM that's being accessed.
	assign ROMDec   = SWRAddr & !PrvAct;

	// 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
	// Check if bank is mapped to ROM on beeb motherboard, or to RAM on IntegraB board
	// GenBankSel[x] is the output of the 4..16 line decoder. Logic '1' if output is decoded
	//	BeebRomSel[x] is based on jumper selection via pull up resistor. Logic '1' selects motherboard ROM. Logic '0' selects onboard RAM
	//	assign nRomBankSel0_3	  = !(!rD3 & !rD2 & nROMDec);
	// nRomBankSelB[x] is logic '0' when bank is selected
	// wire nRomBankSelB[3:0];
	// assign nRomBankSelB[0] = !(GenBankSel[0] & BeebRomSel[0]);
	// assign nRomBankSelB[1] = !(GenBankSel[1] & BeebRomSel[1]);
	// assign nRomBankSelB[2] = !(GenBankSel[2] & BeebRomSel[2]);
	// assign nRomBankSelB[3] = !(GenBankSel[3] & BeebRomSel[3]);
	//	assign nRomBankSel0_3  = nRomBankSelB[0] & nRomBankSelB[1] & nRomBankSelB[2] & nRomBankSelB[3]; //Temporary disable option to switch between ROM and RAM
	assign nRomBankSel0_3  = !GenBankSel[0] & !GenBankSel[1] & !GenBankSel[2] & !GenBankSel[3];


	// Logic to select IntegraB ROM Banks 8..15
	// Check if bank is mapped to ROM on IntegraB board, or to RAM on IntegraB board
	// GenBankSel[x] is the output of the 4..16 line decoder. Logic '1' if output is decoded
	//	IntegraRomSel[x] is based on jumper selection via pull up resistor. Logic '1' selects motherboard ROM. Logic '0' selects onboard RAM
	// nRomBankSel[x] is logic '0' when bank is selected otherwire open collector
	//	assign nRomBankSel[8]  =  (GenBankSel[8]  & IntegraRomSel[8]) ? 1'b0 : 1'bz;
	//	assign nRomBankSel[9]  =  (GenBankSel[9]  & IntegraRomSel[9]) ? 1'b0 : 1'bz;
	//	assign nRomBankSel[10] =  (GenBankSel[10] & IntegraRomSel[10]) ? 1'b0 : 1'bz;
	//	assign nRomBankSel[11] =  (GenBankSel[11] & IntegraRomSel[11]) ? 1'b0 : 1'bz;
	//	assign nRomBankSel[12] =  (GenBankSel[12] & IntegraRomSel[12]) ? 1'b0 : 1'bz;
	//	assign nRomBankSel[13] =  (GenBankSel[13] & IntegraRomSel[13]) ? 1'b0 : 1'bz;
	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;

	// Logic to select IntegraB RAM Banks 0..15
	// Check if bank is mapped to ROM on either beeb motherboard / IntegraB board, or to RAM on IntegraB board
	// assign RamBankSel[0]	  = !(GenBankSel[0]  & !BeebRomSel[0]);
	// assign RamBankSel[1]	  = !(GenBankSel[1]  & !BeebRomSel[1]);
	// assign RamBankSel[2]	  = !(GenBankSel[2]  & !BeebRomSel[2]);
	// assign RamBankSel[3]	  = !(GenBankSel[3]  & !BeebRomSel[3]);
	// assign RamBankSel[4]	  = !(GenBankSel[4]);
	// assign RamBankSel[5]	  = !(GenBankSel[5]);
	// assign RamBankSel[6]	  = !(GenBankSel[6]);
	// assign RamBankSel[7]	  = !(GenBankSel[7]);
	// assign RamBankSel[8]	  = !(GenBankSel[8]  & !IntegraRomSel[8]);
	// assign RamBankSel[9]	  = !(GenBankSel[9]  & !IntegraRomSel[9]);
	// assign RamBankSel[10]  = !(GenBankSel[10] & !IntegraRomSel[10]);
	// assign RamBankSel[11]  = !(GenBankSel[11] & !IntegraRomSel[11]);
	// assign RamBankSel[12]  = !(GenBankSel[12] & !IntegraRomSel[12]);
	// assign RamBankSel[13]  = !(GenBankSel[13] & !IntegraRomSel[13]);
	// assign RamBankSel[14]  = !(GenBankSel[14] & !IntegraRomSel[14]);
	// assign RamBankSel[15]  = !(GenBankSel[15] & !IntegraRomSel[15]);
	//	assign RAM_CE			  = RamBankSel[0]  & RamBankSel[1]  & RamBankSel[2]  & RamBankSel[3]
	//								  & RamBankSel[4]  & RamBankSel[5]  & RamBankSel[6]  & RamBankSel[7]
	//								  & RamBankSel[8]  & RamBankSel[9]  & RamBankSel[10] & RamBankSel[11]
	//								  & RamBankSel[12] & RamBankSel[13] & RamBankSel[14] & RamBankSel[15] & !ShadowSel;

	// Currently have CPLD hooked up to a V1 IntegraB board with 3 x 32k RAM banks, so temporarily driving 3 x CE signals
	// assign RAMBank45_CE	  = RamBankSel[4]  & RamBankSel[5]; //temp for dev testing
	// assign RAMBank67_CE	  = RamBankSel[6]  & RamBankSel[7]; //temp for dev testing
	assign RAMBank45_CE	  = !GenBankSel[4]  & !GenBankSel[5]; //temp for dev testing
	assign RAMBank67_CE	  = !GenBankSel[6]  & !GenBankSel[7]; //temp for dev testing
	assign Shadow_CE		  = ShadowSel; //temp for dev testing



	// RAM addresses A0..A13 and data lines D0..D7 are wired to the CPU (via buffers on the IntegraB board)
	// assign Ram_ADDRESS[14] = rD0 & !ShadowSel
	//							  | bbc_ADDRESS[14] & ShadowSel;
	// assign Ram_ADDRESS[15] = rD1 & !ShadowSel;
	// assign Ram_ADDRESS[16] = rD2 & !ShadowSel;
	// assign Ram_ADDRESS[17] = rD3 & !ShadowSel;
	// assign Ram_ADDRESS[18] = 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
	//	assign nDE	      	  =  !SWRAddr & !FE3x
	//								  |  !nRomBankSel0_3 & !FE3x;

	//This data is latched when address is in the range FE30..FE33
	//rD0..rD3 are used to decode the selected SWROM bank
   always @(posedge dPhi2 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 @(posedge dPhi2 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 @(posedge dPhi2 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 @(posedge dPhi2 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 @(posedge dPhi2 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 @(posedge dPhi2 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 @(posedge dPhi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS1 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS1 <= bbc_DATA[4];
      end
   end
	
	always @(posedge dPhi2 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 dPhi2 or negedge bbc_nRST) begin
      if (!bbc_nRST) begin
         PrvS8 <= 1'b0;
      end else if (!RnW && FE34_7) begin
         PrvS8 <= bbc_DATA[6];
      end
   end

   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

endmodule

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » 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.

It's probably worth you looking at the bus cycle timings in the 6502 datasheet to make sure you are clear exactly when write data is valid. Specifically, look at tMDS which is 100ns for a 6502A. This means the write data is not guaranteed to be stable until 100ns after the rising edge of Phi2. The 6502 designers intended the falling edge of Phi2 to be used to write data into a peripheral. They chose a falling edge, because that edge is faster in NMOS. I might be missing the big picture here, but I would stronly recommend you do things "by the book", unless there are very good reasons not to.

Dave

Post Reply

Return to “8-bit acorn hardware”