Help - Implementing Shadow RAM in CPLD

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

Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Thu May 21, 2020 11:18 pm

Hi Guys,

Not sure if this is the right forum, but I'm hoping someone can help me here. Perhaps an issue I take forward to the next virtual meet. I'll try and keep this post short, but provide enough detail to explain the issue.

I've run into a problem trying to move the discrete logic components from my IntegraB ROM / RAM board into a Xilinx XC95144 CPLD implementation. I've spent the last few nights trying to identify what's going wrong, but I'm not making much progress.

BACKGROUND
The problem I'm having is with Shadow RAM switching. Shadow RAM is enabled by latching bit 7 of the databus when the address bus is set between &FE34 and &FE37. This latched bit is referred to as 'ShEn'. Typing ?&FE34=128 should switch in Shadow RAM. The code for doing this is as follows:

Code: Select all

	// Latch data bus (Shadow / Private RAM selection status) when address is in range &FE34..&FE37
	assign nFE3x	=  !(bbc_ADDRESS[15] &  bbc_ADDRESS[14] &  bbc_ADDRESS[13] &  bbc_ADDRESS[12]
			&    bbc_ADDRESS[11] &  bbc_ADDRESS[10] &  bbc_ADDRESS[9]  & !bbc_ADDRESS[8]
			&   !bbc_ADDRESS[7]  & !bbc_ADDRESS[6]  &  bbc_ADDRESS[5]  &  bbc_ADDRESS[4]);

	assign nFE34_7	= !(!nFE3x & !bbc_ADDRESS[3] &  bbc_ADDRESS[2] & !RnW & dPhi2); // &FE34..&FE37

	// Data Latch
	dff_asyncres ShEnLogic(
		.D(bbc_DATA[7]),
		.CLK(nFE34_7),
		.nCLR(bbc_nRST),
		.Q(ShEn)
	);
dPhi2 is the CPU Phi2 signal put through a RC circuit, and is used to slow the rising edge of the clock. A reverse diode ensures the falling edge is not delayed. Switching between dPhi2 and Phi1 doesn't seem to make any difference in the CPLD implementation. There is similar code for &FE30..&FE33 to latch in four data bits for the SWROM selection, and that code's working just fine.

There is logic to define when ShadowRAM is active. It's basically just decoding addresses between &3000 and &7FFF and checking that Shadow RAM is enabled. This is then used to determine if the system needs to write to main RAM on the beeb board or to shadow RAM on the IntegraB board. The code is as follows (ignore !MemSel. I've forced that to logic 1 for now):

Code: Select all

	assign nShAct   = !(!bbc_ADDRESS[15] & !bbc_ADDRESS[14] &  bbc_ADDRESS[13] &  bbc_ADDRESS[12] &  ShEn & !MemSel  //address decodes to &3000..&3FFF
			|   !bbc_ADDRESS[15] &  bbc_ADDRESS[14] & !bbc_ADDRESS[13] & !bbc_ADDRESS[12] &  ShEn & !MemSel	 //address decodes to &4000..&4FFF
			|   !bbc_ADDRESS[15] &  bbc_ADDRESS[14] & !bbc_ADDRESS[13] &  bbc_ADDRESS[12] &  ShEn & !MemSel	 //address decodes to &5000..&5FFF
			|   !bbc_ADDRESS[15] &  bbc_ADDRESS[14] &  bbc_ADDRESS[13] & !bbc_ADDRESS[12] &  ShEn & !MemSel	 //address decodes to &6000..&6FFF
			|   !bbc_ADDRESS[15] &  bbc_ADDRESS[14] &  bbc_ADDRESS[13] &  bbc_ADDRESS[12] &  ShEn & !MemSel);//address decodes to &7000..&7FFF
Finally, Phi1 and RnW from the CPU are intercepted by the CPLD and spat back out the main beeb board after being conditioned as follows:

Code: Select all

	assign to_bbc_Phi1 = !(!from_CPU_Phi1 & nShAct);
	assign to_bbc_RnW  = !(!from_CPU_RnW  & nShAct);
To avoid complicating things, there's a bunch of additional logic that I've not included in this post, including logic that enables the data buffer and switches the data bus direction, and logic that enables the onboard RAM.

THE PROBLEM
What happens, is that if I type ?&FE34=128, ShEn latches at logic 1, the beeb switches to shadow mode, and any further typing is not visible on the screen. The cursor moves as I type and blindly typing VDU7 generates a beep, so I'm happy the beeb is still running. This matches what happens on my working IntegraB boards. However, if I then blind type ?&FE34=0 the beeb should switch out of shadow mode and further typing should be visible. Unfortunately, this does not happen if I'm in any mode other than 0, 1 or 2 (all of which start at address &3000). ShEn remains at logic 1 and the system stubbornly stays in Shadow mode until I switch to modes 0, 1 or 2 and then repeat the command ?&FE34=0, at which point ShEn switches to logic 0 and the system switches back to Main memory.

I can obviously provide a lot more information, but just wanted to get the basics out there initially. I suspect a subtle timing issue, but I've got very limited spare I/O that I can hook a scope up to, and everything's surface mounted making it difficult to connect scope probes, and type stuff on the beeb at the same time!

Help, please!!!!

TIA.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by cmorley » Fri May 22, 2020 8:41 am

It isn't a good idea to use complicated expressions for generating clocks. These will propogate slowly and could well be glitchy. Use clock enables instead.

So in raw verilog (but you could use your library primatives if you select the one with a clock enable):

Code: Select all

reg en;
always @(posedge clk or posedge rst)
	if (rst) en <= 1'b0;
	else if (...expression...) en <= data[7];
Pseudocode... you'd need to change posedge/negedge to suite clock phase and reset active high low... exercise for the reader.

I don't know if that is your problem but weird clocks cause all sorts of problems which can come and go each time the fitter moves things around! The main clock lines in the CPLD are fast paths with guaranteed latency to FFs.

I would compare addresses as numbers because creating bit wise patterns long hand is error prone.

Code: Select all

wire match = addr[15:4] == 12'hFE3;
There are don't care compares depending on verilog/system verilog. Don't assume a compare with x does what you think it might.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 12:06 pm

cmorley wrote:
Fri May 22, 2020 8:41 am
I don't know if that is your problem but weird clocks cause all sorts of problems which can come and go each time the fitter moves things around! The main clock lines in the CPLD are fast paths with guaranteed latency to FFs.
This in spades!

Don't ever use internal logic to generate a signal that is then used as a clock. There is no guarantee after logic optimization that it will be glitch free. TTL designers (who really new what they were doing) could get away with this back in the day, but when replicating a design in a CPLD or FPGA it's almost always wrong to to simply copy this style.

Follow the pattern Chris suggests above and you won't go far wrong.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 1:59 pm

Thanks guys.

cmorley wrote:
Fri May 22, 2020 8:41 am
It isn't a good idea to use complicated expressions for generating clocks. These will propogate slowly and could well be glitchy. Use clock enables instead.

So in raw verilog (but you could use your library primatives if you select the one with a clock enable):

Code: Select all

reg en;
always @(posedge clk or posedge rst)
	if (rst) en <= 1'b0;
	else if (...expression...) en <= data[7];
Pseudocode... you'd need to change posedge/negedge to suite clock phase and reset active high low... exercise for the reader.

What I didn't show in my original post is the code used for the latches:

Code: Select all

module dff_asyncres(
	input D,
	input CLK,
	input nCLR,
	output reg Q
	);

	always @ (posedge CLK or negedge nCLR)
	begin
		if (~nCLR) Q <= 1'b0;
		else Q <= D;
	end
endmodule
Are you suggesting I need to use similar code in the other places where I'm making reference to Phi1?
hoglet wrote:
Fri May 22, 2020 12:06 pm
cmorley wrote:
Fri May 22, 2020 8:41 am
I don't know if that is your problem but weird clocks cause all sorts of problems which can come and go each time the fitter moves things around! The main clock lines in the CPLD are fast paths with guaranteed latency to FFs.
Don't ever use internal logic to generate a signal that is then used as a clock. There is no guarantee after logic optimization that it will be glitch free.
Hmmm. So the fact that I'm routing Phi1 from the CPU, through the CPLD for conditioning before spitting it back out to the beeb motherboard is a bad idea?

...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?
cmorley wrote:
Fri May 22, 2020 8:41 am
I would compare addresses as numbers because creating bit wise patterns long hand is error prone.

Code: Select all

wire match = addr[15:4] == 12'hFE3;
There are don't care compares depending on verilog/system verilog. Don't assume a compare with x does what you think it might.
It was always my intention to clean up the logic at some point, as I've basically just copied over the Wincupl logic that I used to program the original GALs. I assume it doesn't make any real difference to the final compiled .jed?

I've clearly got a lot to learn with programming the CPLD.

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

Re: Help - Implementing Shadow RAM in CPLD

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

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

Re: Help - Implementing Shadow RAM in CPLD

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

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 4:44 pm

Thank you folks. That helps a lot. I'll take the code that Dave has written, and see if I can apply it to some of the other logic.
hoglet wrote:
Fri May 22, 2020 2:36 pm
Also, there is no need (or benefit) to expressing active-low versions of FE3x.
This was just a carry over from the old design, where nFE3x was the output of one PAL that was then wired into a second PAL. I was planning to tidy that up once I was happy that everything was working as expected.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 5:31 pm

hoglet wrote:
Fri May 22, 2020 2:36 pm

Code: Select all

   assign bbc_DATA = (RnW && Phi2 && FE34_7) ? {ShEn, 7'b0000000} : 8'hZZ;
Dave
Just looking at your example a bit further, I don't think this specific bit of code is doing what I want. All the CPLD is trying to do is enable a RAM_CE signal on the IntegraB board when Shadow RAM (ShEn) is active, and the address bus is in the range &3000..&7FFF. The CPLD is never actually writing anything to the data bus. Unless I'm misunderstanding what the code above is trying to do? I'll post up the entire code shortly. I just need to remove all the test code I've added, as that will complicate things.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 5:34 pm

KenLowe wrote:
Fri May 22, 2020 5:31 pm
Just looking at your example a bit further, I don't think this specific bit of code is doing what I want. All the CPLD is trying to do is enable a RAM_CE signal on the IntegraB board when Shadow RAM (ShEn) is active, and the address bus is in the range &3000..&7FFF. The CPLD is never actually writing anything to the data bus. Unless I'm misunderstanding what the code above is trying to do? I'll post up the entire code shortly. I just need to remove all the test code I've added, as that will complicate things.
It was just an example of how you might handle a tri-state bus. If it's not needed, then just take it out.

As I said, without seeing the whole design I was guessing at what was included.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 7:27 pm

I've implemented the logic as suggested, but it doesn't seem to have made any difference. So far, I've only implemented the clock change on the d7 / FE34_7 latch. I'll implement the FE30_3 latches in the same way to see if it makes any difference, but the FE30_3 latches are working fine with the current arrangement, so I'm not overly optimistic. It's as if the data being written to FE34..FE37 is not getting through the IntegraB data buffer when the screen is not in mode 0, 1 or 2, but the nDE logic which enables the data buffer looks fine.

As you will no doubt see, there's still a lot of other optimisation to be done!
IntegraBV2.zip
IntegraB V2 CPLD logic
(813.11 KiB) Downloaded 2 times
.

Edit: I've now implemented the same clock changes to all latches, but again, it's not made any difference.
IntegraBV2-2.zip
Updated IntegraB V2 CPLD logic
(814.94 KiB) Downloaded 4 times

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 8:39 pm

I'm not sure if it's the cause of your problems, but you should remove the DPhi2 (and probably also !RnW) from these signals:

Code: Select all

   wire   nFE30_3 = !(FE3x && (bbc_ADDRESS[3:2] == 2'b00) && !RnW && dPhi2);
   wire   nFE34_7 = !(FE3x && (bbc_ADDRESS[3:2] == 2'b01) && !RnW && dPhi2);
   wire   FE30_3  = FE3x && (bbc_ADDRESS[3:2] == 2'b00);
   wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01);
	wire	 RTC_AS  = FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && !Phi1;
Unless there's still a reason for them to be there, which I've missed.

The other cause for concern is your clock inputs are on normal I/O pins:

Code: Select all

from_CPU_Phi1                                     FB5_14  43   I/O     I
from_CPU_dPhi2                                    FB5_17  49   I/O     I
It would be better if they were on the Global Clock (GCLK) pins. If you don't do this, the clock has to come through the logic array, which means more skew is possible.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 8:51 pm

hoglet wrote:
Fri May 22, 2020 8:39 pm
I'm not sure if it's the cause of your problems, but you should remove the DPhi2 (and probably also !RnW) from these signals:

Code: Select all

   wire   nFE30_3 = !(FE3x && (bbc_ADDRESS[3:2] == 2'b00) && !RnW && dPhi2);
   wire   nFE34_7 = !(FE3x && (bbc_ADDRESS[3:2] == 2'b01) && !RnW && dPhi2);
   wire   FE30_3  = FE3x && (bbc_ADDRESS[3:2] == 2'b00);
   wire   FE34_7  = FE3x && (bbc_ADDRESS[3:2] == 2'b01);
	wire	 RTC_AS  = FE3x && (bbc_ADDRESS[3:2] == 2'b10) && !RnW && !Phi1;
Unless there's still a reason for them to be there, which I've missed.
This is the code that I extracted from the PALs on my original IntegraB board. I assumed the dPhi2 was there to allow some settle time on the data bus before latching the data. I think I've already tried with both dPhi2 and !RnW removed, but I'll try again and report back.
hoglet wrote:
Fri May 22, 2020 8:39 pm
The other cause for concern is your clock inputs are on normal I/O pins:

Code: Select all

from_CPU_Phi1                                     FB5_14  43   I/O     I
from_CPU_dPhi2                                    FB5_17  49   I/O     I
It would be better if they were on the Global Clock (GCLK) pins. If you don't do this, the clock has to come through the logic array, which means more skew is possible.
Yeah, rookie error, I'm afraid. Trouble is it's difficult for me to change this now without getting a new board built, and I'd like to get some confidence that this would address the issue before committing.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 9:16 pm

KenLowe wrote:
Fri May 22, 2020 8:51 pm
This is the code that I extracted from the PALs on my original IntegraB board. I assumed the dPhi2 was there to allow some settle time on the data bus before latching the data. I think I've already tried with both dPhi2 and !RnW removed, but I'll try again and report back.
I don't expect it to make a difference. It's just unusual, and might confuse the tool chain.

At this stage, I would probably try to run a simulation (using something like iverilog) just to make sure there wasn't a mistake in the Verilog.

I just spent two days trying to track down a bug in my new Beeb 1MHz Bus Full HD Life project by staring at the Verilog and drawing endless timing diagrams. In the end, I spent a about an hour writing a mininal Verilog test harness and running a simulation. I spotted the issue within about 5 minutes. Here's the test harness:
https://github.com/hoglet67/Beeb1MHzBus ... /life_tb.v

If you run out of other options, I'm happy to help out by doing this. It's more to rule out logic errors. This might best be done over a zoom call.

One last question. In your original post, you said:
(ignore !MemSel. I've forced that to logic 1 for now)
Looking at the logic, it looks like MemSel is bit D7 of &FE30, and that would need to be set to 0 for the ShAct to be asserted.
dPhi2 is the CPU Phi2 signal put through a RC circuit, and is used to slow the rising edge of the clock. A reverse diode ensures the falling edge is not delayed.
Is this RC network still in place? I don't think it's needed, and it could be cause issues (slow clock edges).

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by cmorley » Fri May 22, 2020 9:24 pm

hoglet wrote:
Fri May 22, 2020 9:16 pm
I just spent two days trying to track down a bug in my new Beeb 1MHz Bus Full HD Life project by staring at the Verilog and drawing endless timing diagrams. In the end, I spent a about an hour writing a mininal Verilog test harness and running a simulation. I spotted the issue within about 5 minutes.
Dave writes wise words. Unless it is trivial and you can get a logic analyser on everything then simulation saves a lot of time.
KenLowe wrote:
Fri May 22, 2020 8:51 pm
Trouble is it's difficult for me to change this now without getting a new board built, and I'd like to get some confidence that this would address the issue before committing.
Craft knife, thin wire, flux, solder and magnification. :D

edit: and patience

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 10:06 pm

hoglet wrote:
Fri May 22, 2020 9:16 pm
One last question. In your original post, you said:
(ignore !MemSel. I've forced that to logic 1 for now)
Looking at the logic, it looks like MemSel is bit D7 of &FE30, and that would need to be set to 0 for the ShAct to be asserted.
Turns out I was talking complete rubbish there. I had forced it to logic 0 at one stage, but it's now being driven by the latch again. What I probably meant to say in my earlier post was that I had forced nPrvAct to logic 1, but that would actually have been irrelevant in my original post.
hoglet wrote:
Fri May 22, 2020 9:16 pm
dPhi2 is the CPU Phi2 signal put through a RC circuit, and is used to slow the rising edge of the clock. A reverse diode ensures the falling edge is not delayed.
Is this RC network still in place? I don't think it's needed, and it could be cause issues (slow clock edges).
It is still in place, and is wired into the CPLD, but Phi2 is not used for anything else, so I didn't think it would cause any other problems. If I want to use a non delayed clock, can I not just use Phi1 in place of dPhi2 in the CPLD?
hoglet wrote:
Fri May 22, 2020 9:16 pm
At this stage, I would probably try to run a simulation (using something like iverilog) just to make sure there wasn't a mistake in the Verilog.

I just spent two days trying to track down a bug in my new Beeb 1MHz Bus Full HD Life project by staring at the Verilog and drawing endless timing diagrams. In the end, I spent a about an hour writing a mininal Verilog test harness and running a simulation. I spotted the issue within about 5 minutes. Here's the test harness:
https://github.com/hoglet67/Beeb1MHzBus ... /life_tb.v

If you run out of other options, I'm happy to help out by doing this. It's more to rule out logic errors. This might best be done over a zoom call.
That sounds like a complicated option, but I'm always happy to learn! Really appreciate your offer of help here, but let me persevere with my investigations for a while.

To be clear what happens is that in Modes 0, 1 & 2, if I type ?&FE34=128 subsequent text is not written to screen. If I then blind type ?&FE34=0 subsequent text is written to the screen again. This is the behaviour I expect.
Conversely, in Modes 3 thru 7, if I type ?&FE34=128 subsequent text is not written to screen as expected. However, in these modes, if I then blind type ?&FE34=0 subsequent text is still not written to the screen. I need to switch to either mode 0, 1 or 2 and blind type ?&FE34=0 again to get text to start appearing on screen again.

Monitoring the ShEn bit via a temporary CPLD output I can see it is not getting set low again when typing ?&FE34=0 in modes 3 thru 7. This happens very consistently.
cmorley wrote:
Fri May 22, 2020 9:24 pm
KenLowe wrote:
Fri May 22, 2020 8:51 pm
Trouble is it's difficult for me to change this now without getting a new board built, and I'd like to get some confidence that this would address the issue before committing.
Craft knife, thin wire, flux, solder and magnification. :D

edit: and patience
It might come to that, but I would like to eliminate as much as possible before starting down a destructive path!

Once again guys, thank you very much for your guidance and offers of help. It's much appreciated.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 10:15 pm

KenLowe wrote:
Fri May 22, 2020 10:06 pm
That sounds like a complicated option, but I'm always happy to learn! Really appreciate your offer of help here, but let me persevere with my investigations for a while.
Honestly it's not a lot of work, in fact it's mostly done:

Code: Select all

`timescale 1ns/1ns

module IntergraBV2_tb();

   reg            clk = 0;
   wire           dPhi2;
   wire           Phi1;
   reg            RnW = 1;
   reg            nRST = 0;
   reg [7:0]      DATA = 8'hZZ;
   reg [15:0]     ADDRESS = 0;
   reg [15:0]     RamWriteProt = 0;
   reg [15:8]     IntegraRomSel = 0;
   reg [3:0]      BeebRomSel = 0;

   wire           o_to_bbc_Phi1;
   wire           o_to_bbc_RnW;
   wire           o_to_bbc_rD0;
   wire           o_to_bbc_rD1;
   wire           o_nDE;
   wire           o_IntegraRnW;
   wire           o_nWDS;
   wire           o_nRDS;
   wire           o_nRTC_AS;
   wire           o_nRTC_DS;
   wire [15:8]    o_nRomBankSel;
   wire           o_RAM_CE;
   wire           o_nRomBankSel0_3;
   wire [18:14]   o_Ram_ADDRESS;


   task bus_write;
      input [15:0] a;
      input [7:0] d;
      begin
         @(negedge dPhi2);
         #50;
         ADDRESS = a;
         RnW     = 1'b0;
         @(posedge dPhi2)
         DATA    = d;
         @(negedge dPhi2)
         #50
         DATA    = 8'hZZ;
         ADDRESS = 16'h0000;
         RnW     = 1'b1;
      end
   endtask

   task test_memory;
      begin
         bus_write(16'h0000, 8'h00);
         bus_write(16'h1000, 8'h11);
         bus_write(16'h2000, 8'h22);
         bus_write(16'h3000, 8'h33);
         bus_write(16'h4000, 8'h44);
         bus_write(16'h5000, 8'h55);
         bus_write(16'h6000, 8'h66);
         bus_write(16'h7000, 8'h77);
      end
   endtask


IntegraBV2 dut
  (
   // Inputs
   .from_CPU_RnW(RnW),
   .from_CPU_Phi1(Phi1),
   .from_CPU_dPhi2(dPhi2),
   .bbc_nRST(nRST),
   .bbc_DATA(DATA),
   .bbc_ADDRESS(ADDRESS),
   .RamWriteProt(RamWriteProt),
   .IntegraRomSel(IntegraRomSel),
   .BeebRomSel(BeebRomSel),
   // Outputs
   .to_bbc_Phi1(o_Phi1Out),
   .to_bbc_RnW(o_RnWOut),
   .to_bbc_rD0(o_rD0),
   .to_bbc_rD1(o_rD1),
   .nDE(o_nDE),
   .IntegraRnW(o_IntegraRnW),
   .nWDS(o_nWDS),
   .nRDS(o_nRDS),
   .nRTC_AS(o_nRTC_AS),
   .nRTC_DS(o_nRTC_DS),
   .nRomBankSel(o_nRomBankSel),
   .RAM_CE(o_RAM_CE),
   .nRomBankSel0_3(o_nRomBankSel0_3),
   .Ram_ADDRESS(o_Ram_ADDRESS)
    );


   always
     #250 clk = ~clk;

   assign dPhi2 = ~clk;
   assign Phi1 = clk;


   initial begin
      $dumpvars;

      nRST = 1'b1;
      @(negedge dPhi2);
      nRST = 1'b0;
      @(negedge dPhi2);
      nRST = 1'b1;

      bus_write(16'hFE30, 8'h00);
      bus_write(16'hFE34, 8'h00);

      test_memory();

      bus_write(16'hFE30, 8'h00);
      bus_write(16'hFE34, 8'h80);

      test_memory();

      bus_write(16'hFE30, 8'h00);
      bus_write(16'hFE34, 8'h00);

      test_memory();

      // Wait 10 more us
      #10000
        $finish();
   end

endmodule
It seems to be doing something vagley sensible:
sim1.png
(Here's the screen shot in a zip file, so it doesn't get compressed):
sim1.zip
(105.55 KiB) Downloaded 3 times

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 10:33 pm

That's very impressive. I'm just having a look at the simulation output now to see if I can work out whats happening! One thing that does look odd is that nWDS is sitting high throughout. I would have expected that to be toggling. However, it's not really relevant to the issue we're looking at.
And I didn't realise that Phi2 was out of phase of Phi1. Or is that just how you've set up the simulation?

Edit: Ah. I see:

Code: Select all

   always
     #250 clk = ~clk;

   assign dPhi2 = ~clk;
   assign Phi1 = clk;
Edit 2: And Write Protect must be active, which is what is holding nWDS high!
Last edited by KenLowe on Fri May 22, 2020 10:39 pm, edited 1 time in total.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 10:39 pm

Maybe have a think about a sequence of bus reads and writes that would be a good test. The point of simulations like this is mostly to exclude logic errors. They won't easily catch timing errors, ground issues, noise issues, clock issues, pins being connected to the wrong place.

I'm also doing this somewhat blind, because I don't have a good understanding of IntegraB.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 10:42 pm

KenLowe wrote:
Fri May 22, 2020 10:33 pm
And I didn't realise that Phi2 was out of phase of Phi1. Or is that just how you've set up the simulation?
I assume these are the two clock signals output by the 6502?

Those are non-overlapping, out of phase clocks.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 10:45 pm

If you install GTKWave you can look at the waveform dump file yourself:
waveform1.zip
(3.4 KiB) Downloaded 3 times
Last edited by hoglet on Fri May 22, 2020 10:50 pm, edited 1 time in total.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 10:49 pm

hoglet wrote:
Fri May 22, 2020 10:39 pm
Maybe have a think about a sequence of bus reads and writes that would be a good test. The point of simulations like this is mostly to exclude logic errors. They won't easily catch timing errors, ground issues, noise issues, clock issues, pins being connected to the wrong place.

I'm also doing this somewhat blind, because I don't have a good understanding of IntegraB.

Dave
The IntegraB is actually very simple. It's just a standard ROM / RAM board with a 4..16 line decoder and an extra 32k shadow RAM chip that is switched in at certain memory addresses by a couple of flags at FE30 & FE34. It also inhibits Phi1 and RnW to the beeb mainboard when accessing this RAM chip. I've made this new board a bit more complicated by installing a larger memory chip, which can be mapped into individual ROM banks by jumper selection, as well as providing the 32K shadow RAM.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 10:49 pm

The Simulator I'm using is Icarus iverilog (aka iverilog). The preferred envorinment for this is Linux.

Are you a Windows, MAC or Linux user?

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 10:50 pm

hoglet wrote:
Fri May 22, 2020 10:42 pm
KenLowe wrote:
Fri May 22, 2020 10:33 pm
And I didn't realise that Phi2 was out of phase of Phi1. Or is that just how you've set up the simulation?
I assume these are the two clock signals output by the 6502?

Those are non-overlapping, out of phase clocks.
That's correct, these are the two signals from the 6502. I didn't realise they were out of phase.

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 10:52 pm

KenLowe wrote:
Fri May 22, 2020 10:50 pm
That's correct, these are the two signals from the 6502. I didn't realise they were out of phase.
You would normally try to register write data from a 6502 and the end of the 6502 bus cycle.

The preferred clock to use for this is Phi2, and the falling edge of Phi2 marks the end of the bus cycle.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 10:53 pm

hoglet wrote:
Fri May 22, 2020 10:49 pm
The Simulator I'm using is Icarus iverilog (aka iverilog). The preferred envorinment for this is Linux.

Are you a Windows, MAC or Linux user?
Primarily windows, but I can set up a Linux environment. I've got a CentOS setup somewhere, but it's only command line. I'd need to do another install if it needs a GUI. Should I be installing any particular distro?

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

Re: Help - Implementing Shadow RAM in CPLD

Post by hoglet » Fri May 22, 2020 11:08 pm

KenLowe wrote:
Fri May 22, 2020 10:53 pm
Primarily windows, but I can set up a Linux environment. I've got a CentOS setup somewhere, but it's only command line. I'd need to do another install if it needs a GUI. Should I be installing any particular distro?
The simulator is command line only, and produces a VCD (value-change dump) file (like the one I attached).

It's available for just about any flavour of Linux:
https://pkgs.org/download/iverilog

If there is one you are familar with, then use it. I'm currently using Ubuntu 18.04.

GTKWave reads the VCD file, and will run on Windows.

Dave

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 11:11 pm

hoglet wrote:
Fri May 22, 2020 10:52 pm
KenLowe wrote:
Fri May 22, 2020 10:50 pm
That's correct, these are the two signals from the 6502. I didn't realise they were out of phase.
You would normally try to register write data from a 6502 and the end of the 6502 bus cycle.

The preferred clock to use for this is Phi2, and the falling edge of Phi2 marks the end of the bus cycle.

Dave
Am I correct in understanding that the Beeb doesn't use Phi2 (pin 39), and the Beeb 2MHz clock is derived from an inverted Phi1 (pin 3) instead?

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Fri May 22, 2020 11:16 pm

hoglet wrote:
Fri May 22, 2020 11:08 pm
KenLowe wrote:
Fri May 22, 2020 10:53 pm
Primarily windows, but I can set up a Linux environment. I've got a CentOS setup somewhere, but it's only command line. I'd need to do another install if it needs a GUI. Should I be installing any particular distro?
The simulator is command line only, and produces a VCD (value-change dump) file (like the one I attached).

It's available for just about any flavour of Linux:
https://pkgs.org/download/iverilog

If there is one you are familar with, then use it. I'm currently using Ubuntu 18.04.

GTKWave reads the VCD file, and will run on Windows.

Dave
Ok, I see there's a CentOS7 version in there, so that should work for me. I'll dig out my Linux box tomorrow and give it a try.

I just tried the ISim package from Xilinx, but it's only giving me a lite version with my free licence. It doesn't seem to recognise the vcd file from iverilog either. So I've downloaded and installed GTKWave for windows, and I'm now able to load up the vcd file. Thanks. Looks good. Just need to work out what's going wrong now!

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

Re: Help - Implementing Shadow RAM in CPLD

Post by KenLowe » Sat May 23, 2020 1:09 pm

Today I decided to strip the board and CPLD back to minimal config. On the IntegraB board I've removed all the ROMs, and I've moved Basic back to the east most socket on the main board. I've restored the links S20, S21 & S22 so ROM selection is once again done on the beeb motherboard.

In the CPLD, I've
  • removed all logic associated with ROM / RAM selection
  • removed all logic associated with Private RAM
  • forced the chip enable flag for the IntegraB RAM to 1, so that it is permanently disabled
  • forced the data direction flag for the IntegraB data buffer to 0, so that data is always flowing from CPU to the IntegraB board
  • set the output enable flag for the IntegraB data buffer so that data is only ever on the IntegraB data bus when the address is in the range FE&34..&FE37
  • the only latch remaining is the ShEn latch
  • the nShAct logic remains active, and nShAct will be driven 0 when address is in the range &3000..&7FFF and ShEn is active.
  • the Phi1 signal to the beeb mainboard is still being conditioned, and will be disabled when nSHAct is low
  • the RnW signal to the beeb mainboard is still being conditioned, and will be disabled when nSHAct is low
Even with this minimal config, it's still doing the same thing. I still can't get ShEn to delatch (with ?&FE34=15) unless I'm in modes 0, 1 or 2. I need to set it to 15, since writing to &FE34 on the main board is the same as writing to &FE30, and will therefore do a ROM selection. I've got BASIC in beeb bank 15 which is why I therefore need set it to 15! Similarly, to enable ShEn I now need to ?&FE34=143 (128+15) to avoid switching out of Basic whilst trying to set the flag.

My next step is to pull the Phi1 conditioning logic out of the CPLD and implement in discrete logic. I can do this non-destructively. Out with the soldering iron...

Edit: I implemented the to_bbc_Phi1 = !(!Phi1 & !ShAct) conditioning logic via an external 74HCT00 by picking up Phi1 direct from the CPU pin 3 and !ShAct as an output from the CPLD , but that hasn't made any difference. Next up, I'll probably try generating an external clock signal to drive the ShEn data latch, to see if that makes any difference. Again, I could probably do that non destructively, but it's starting to get more complicated as I'll need to do quite a lot of external address decoding.

Post Reply

Return to “8-bit acorn hardware”