Author Topic: FPGA VGA Controller for 8-bit computer  (Read 510759 times)

0 Members and 39 Guests are viewing this topic.

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #800 on: January 01, 2020, 11:40:21 pm »
Have looked at the level converters - I'm using a 74LVC245 to shift the data bus from 5v down to 3v3 for the FPGA - it's powered at 3v3, so it will be outputting to the Z80's data bus at 3.8v maximum, according to the datasheet and the Z80 has a buffer on its data bus anyway (a 74HCT245) which takes 2v as a high input, so I don't think there should be any voltage level issues...  :-//
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #801 on: January 02, 2020, 12:10:01 am »
Have looked at the level converters - I'm using a 74LVC245 to shift the data bus from 5v down to 3v3 for the FPGA - it's powered at 3v3, so it will be outputting to the Z80's data bus at 3.8v maximum, according to the datasheet and the Z80 has a buffer on its data bus anyway (a 74HCT245) which takes 2v as a high input, so I don't think there should be any voltage level issues...  :-//
?  How do you get more voltage out of an output buffer, IE3.8v, when powering it at 3.3v?

Do you have a scope shot?

It looks as if you may be decoding/latching the GPU ram at the wrong time, or forgetting to latch it at all.
Also, for the Z80 writes, it may be wise to scope both sides of the buffer.
As for the block writes, we rely on the cycling of the WRn from the Z80, if during a block write that signal remains low throughout multiple writes, we may need to adapt our Z80 bridge write logic.

The fact you got this far on the first day is actually a good sign.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #802 on: January 02, 2020, 09:15:38 am »
Change your Z80 buss interface so it responds on every rising clock edge, both whether it is a read or write.  Ignore the edge transitions of the mreq and wrn.  In in other words, if there are 2 or 3 consecutive mreqs across multiple clocks, trigger and respond at each one.

Also make a switch input which will allow you to switch triggering on the positive edge clock, or, the negative edge clock.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #803 on: January 02, 2020, 11:19:08 am »
Have looked at the level converters - I'm using a 74LVC245 to shift the data bus from 5v down to 3v3 for the FPGA - it's powered at 3v3, so it will be outputting to the Z80's data bus at 3.8v maximum, according to the datasheet and the Z80 has a buffer on its data bus anyway (a 74HCT245) which takes 2v as a high input, so I don't think there should be any voltage level issues...  :-//
?  How do you get more voltage out of an output buffer, IE3.8v, when powering it at 3.3v?

I was just quoting from here in the linked datasheet:



It's immaterial, anyway, as the Z80 buffer reads anything above 2v as HIGH, so there should be no issues with the voltage conversion.

Do you have a scope shot?

Scope or logic analyser?  My scope is of limited use as it's not digital and is very old - unless I'm worried about voltage levels or analogue signals, I tend to default to the logic analyser.  In either case, no, I don't have any shots (yet) - setting them up is a pain and I go to them as a last resort, usually. 

It looks as if you may be decoding/latching the GPU ram at the wrong time, or forgetting to latch it at all.

This is highly possible, as I've taken the z80_bridge module to be working since I last posted the code for it some time ago and didn't get any comments from you on it?  :o

The data output from the Z80_bridge module (Z80_rData[7:0]) is a register though, so should latch anyway? 

I've attached the latest code for the z80_bridge module below.

As for the block writes, we rely on the cycling of the WRn from the Z80, if during a block write that signal remains low throughout multiple writes, we may need to adapt our Z80 bridge write logic.

Even during 'block' writes, WR is cycled by the Z80 - the normal WR cycle is observed, it's just that LDIR (and others) simplifies the assembly for the programmer by removing the need for a loop.  You just specify the source and destination addresses, number of bytes to copy, then LDIR does the rest.  Each step in the loop is a load (RD) from the source address, then a WR to the destination address, then the Z80 increments the address pointers and decrements the number of bytes to copy before looping.  There is no RD-MODIFY-WR or anything like that on the Z80 - all the RD and WR cycles are as shown in the timing diagram in the Z80 datasheet.



According to one source I found, the Z80 latches the data during a RD operation on the falling edge of T3. This appears to be very close to the rising edges of MREQ and RD, but according to the datasheet should be no more than 60ns before the rise of RD for a Z84C008 (timing 23 in the below chart).  No minimum is given, but that's because of 'overclocking' - my Z84C008 runs at 8 MHz, so that figure should be close to 60ns.

900886-2

900890-3

The fact you got this far on the first day is actually a good sign.

I was actually hugely surprised, to be honest, that I got it working at all.  It's a rat's nest of wires at the moment - will be glad when I've got a Lattice dev board done and have some confidence in BGA soldering...  but that's a way off yet!  :o
« Last Edit: January 02, 2020, 11:33:32 am by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #804 on: January 02, 2020, 11:52:13 am »
Without an analog scope shot, how can you be certain that the CMOS buffer output signals cleanly clears 2v when driving the CPU's input loads?

A logic analyzer is a powerful debug tool, but if it considers 1.5v a high and the CMOS buffer is outputting a 1.9v signal, you still need to verify everything is ok.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #805 on: January 02, 2020, 01:17:36 pm »
Without an analog scope shot, how can you be certain that the CMOS buffer output signals cleanly clears 2v when driving the CPU's input loads?

:o Fair point.  Well, I wrote a (very) short program to repeatedly read the first address in GPU RAM and loop.  Literally two lines of code (well, three as I had to disable interrupts).  I have to get repeating signals otherwise my scope will just display garbage - it has no hold/freeze.  From what I can tell, at least 3v are going out of the converter.

If the voltages weren't high enough to be read as HIGHs, surely the corrupt values would be missing bits (LOWs) or bytes coming out as zeroes, rather than the current case where the corrupt bits are high or low?  I'm sometimes getting $FF instead $00, for example, which leads me to think it's a timing issue rather than a voltage one.  :-//
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #806 on: January 02, 2020, 01:39:45 pm »
It looks as if you may be decoding/latching the GPU ram at the wrong time, or forgetting to latch it at all.

Still thinking about this - I'm not sure the Z80_bridge module is 100% correct - I'm not latching the data at all, other than the output to the Z80 is a register?  Should I have some DFFs on the output to the Z80 from the Z80_bridge like you did with the RS232 outputs to the GPU RAM, but clocked from the Z80 (or the Z80's RD?) instead of the GPU clock?
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #807 on: January 02, 2020, 11:39:12 pm »
So close...

Console output:
901292-0

GPU output:
901296-1

EDIT: Yes - I know the year is out on my RTC!  ;)
« Last Edit: January 03, 2020, 12:09:01 am by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #808 on: January 03, 2020, 12:21:58 am »
Start with my recommended changes to the Z80 bridge code.  I don't know if I have time to look at it myself.  Maybe on the weekend.

Also think about assigning 'Fast Input Registers' and 'Fast Output Registers' and 'Fast Output Enable' registers in Quartus.  Note that these don't get assigned in the verilog, they are project assignments.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #809 on: January 03, 2020, 12:28:42 am »
Start with my recommended changes to the Z80 bridge code.  I don't know if I have time to look at it myself.  Maybe on the weekend.

Also think about assigning 'Fast Input Registers' and 'Fast Output Registers' and 'Fast Output Enable' registers in Quartus.  Note that these don't get assigned in the verilog, they are project assignments.

Okay, will take a look at the changes tomorrow.  Will do some research on these Fast Input/Fast Output registers too.  Thanks.  :)
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #810 on: January 03, 2020, 05:44:00 am »
Try this:

   if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1;            // set 245 dir toward FPGA
   if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0;            // set FPGA pins to input (should be by default)

   if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0;            // enable 245 output

   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wdata        <= Z80_wData;      // latch data bus onto GPU data bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b1;            // turn on FPGA RAM we

   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  gpu_wr_ena       <= 1'b0;            // turn off FPGA RAM we
   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  Z80_245_oe       <= 1'b1;            // disable 245 output


This will force 2 sequential write pulses, perhaps patching a bug within the MUX algorithm.

Also in the MUX, take a 1-shot approach to read and writes from the RS232 debugger port.  (Make the read and write req go through a 1 clk delay and run once only if the signal does a low to high transition.)   Since the RS232 operates at 50MHz, a write or read command remains on for multiple clocks.


 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #811 on: January 03, 2020, 12:03:31 pm »
Try this:

   if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1;            // set 245 dir toward FPGA
   if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0;            // set FPGA pins to input (should be by default)

   if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0;            // enable 245 output

   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wdata        <= Z80_wData;      // latch data bus onto GPU data bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b1;            // turn on FPGA RAM we

   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  gpu_wr_ena       <= 1'b0;            // turn off FPGA RAM we
   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  Z80_245_oe       <= 1'b1;            // disable 245 output


This will force 2 sequential write pulses, perhaps patching a bug within the MUX algorithm.

Also in the MUX, take a 1-shot approach to read and writes from the RS232 debugger port.  (Make the read and write req go through a 1 clk delay and run once only if the signal does a low to high transition.)   Since the RS232 operates at 50MHz, a write or read command remains on for multiple clocks.

Ah - the changes above seem to have fixed it (including one-shotting the RS232 read/writes)! ^-^

I'm getting no errors, either reading from or writing to the GPU now from the Z80 (and the RS232_debugger is unaffected) - I'm able to do block memory ops as well, so clearing the screen (eg) is dead easy now.  I'll keep an eye on the interface stability as I develop the driver for the GPU, but it's looking good so far.  :-+

 ;D ^-^ ;D ^-^ ;D ^-^ ;D
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #812 on: January 03, 2020, 12:11:00 pm »
You have cornered the problem and made a quick workaround according to my recommendations.  Do not assume it is wise not to properly fix the code.  For now, you are fine, but with the addition of a hardware accelerated drawing engine in the future, you will by that time want to get the read and write mux and Z80 interface to properly work with a single write pulse as you do not want to waste R/W cycles when you have a fast drawing engine sharing the GPU ram bus.

The proper thing is within the MUX would be to unilaterally acknowledge a single read and write pulse, holding it internally until that address and write_ena makes it way out to the GPU ram.
« Last Edit: January 03, 2020, 12:14:25 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #813 on: January 03, 2020, 11:22:24 pm »
You have cornered the problem and made a quick workaround according to my recommendations.  Do not assume it is wise not to properly fix the code.  For now, you are fine, but with the addition of a hardware accelerated drawing engine in the future, you will by that time want to get the read and write mux and Z80 interface to properly work with a single write pulse as you do not want to waste R/W cycles when you have a fast drawing engine sharing the GPU ram bus.

The proper thing is within the MUX would be to unilaterally acknowledge a single read and write pulse, holding it internally until that address and write_ena makes it way out to the GPU ram.

I've been trying to get the mux to hold off all other requests until a read cycle is completed, but not had much luck so far.  I presume this is what you're talking about above?  I've attached the files below for reference - data_mux has the work I've tried to hold off on requests, although the lines are commented-out at the moment.

It seems I spoke too soon about the interface stability earlier - whilst I am able to block-write zeros to part of the GPU RAM as part of a CLS (or clear screen) command, it really doesn't like me trying to scroll the screen data upwards one line when the cursor tries to go past the bottom of the screen (the idea being to scroll all lines up 'one line' apart from the top line, which would be overwritten, and blank the bottom line).  I'm getting all kinds of write/read errors when I try to copy the data (I'm basically starting at the second line, copying each byte to an address 50 bytes earlier (one line up) and cycling through to the bottom of the screen before blanking the last 50 bytes of data).

Change your Z80 buss interface so it responds on every rising clock edge, both whether it is a read or write.  Ignore the edge transitions of the mreq and wrn.  In in other words, if there are 2 or 3 consecutive mreqs across multiple clocks, trigger and respond at each one.

Also make a switch input which will allow you to switch triggering on the positive edge clock, or, the negative edge clock.

I haven't tried these modifications yet.  You're asking me to ignore MREQ and WR, just respond to ANY RD or WR trigger?  I guess the 'valid_address' would gate reads or writes to non-GPU RAM space effectively.

One other thing I've failed miserably at is in z80_bridge.v (attached below).  I want it to ignore reads or writes to addresses above the GPU's RAM space.  The GPU window is 512KB, but I'd like the GPU to return $FF for any reads to addresses above 32 KB (or a user-definable value, at least).  This is important for two reasons - it prevents bad data being returned and the Microcom determines if a memory bank is RAM, ROM, or something else by the values it receives when it reads the last page of a 16KB block of memory.  I'd like the GPU to be able to return a pre-defined value if a read to that page is detected.  What I've tried in z80_bridge just isn't working - I'm just getting garbled data (all the time), even when accessing the proper GPU RAM.  mem_valid is the trigger I'd set up, commented out in the z80_bridge code.  Would appreciate some tips (from anyone!) on getting that particular requirement working.
« Last Edit: January 03, 2020, 11:28:29 pm by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #814 on: January 04, 2020, 11:52:09 am »
.....
Ok,...
Here we go....

I replaced your data_mux with a dumb AB, back and forth version.
I changed RS232_Debugger to operate at 125MHz.
I corrected your Z80_bridge as it wasn't posting and releasing the reads correctly.

Using the PC RS232_Debugger software, you can set debug port bits 'OUT3[6]' and 'OUT3[7]' to change which edge or edges of the  Z80_CLK input the bus controls will be latched on.

OUT3[6] is active low, when low, the Z80_bridge will latch the Z80 bus controls on the falling edge of the Z80_CLK input.  When high, the falling edge clock is disabled.

OUT3[7] is active high, when high, the Z80_bridge will latch the Z80 bus controls on the rising edge of the Z80_CLK input.  When low, the rising edge clock is disabled.

Enabling both clock edge control bits means that the Z80_bridge double clocks, once on the rising, then again on the falling.


*** You did not do your assignments 'Fast Input/Output/OE' for all your bus controls and OEs.  You have 2 choices, assign setup and hold timing settings in nanoseconds, or, use the 'Fast ***' feature to achieve the best possible logic cell placement of each IO for best clocking capability.  Without these assignments, every time you compile your project, each IO pin will randomly be slower or faster since the compiler will try to best locate the internal logic and not care about the speed and performance of your IOs.  This means every compile, your Z80 bus may get random IO errors which may have nothing to do with any code changes.  This is FPGA 101.

« Last Edit: January 04, 2020, 11:53:59 am by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #815 on: January 04, 2020, 12:51:40 pm »
.....
Ok,...
Here we go....

I replaced your data_mux with a dumb AB, back and forth version.
I changed RS232_Debugger to operate at 125MHz.
I corrected your Z80_bridge as it wasn't posting and releasing the reads correctly.

Using the PC RS232_Debugger software, you can set debug port bits 'OUT3[6]' and 'OUT3[7]' to change which edge or edges of the  Z80_CLK input the bus controls will be latched on.

OUT3[6] is active low, when low, the Z80_bridge will latch the Z80 bus controls on the falling edge of the Z80_CLK input.  When high, the falling edge clock is disabled.

OUT3[7] is active high, when high, the Z80_bridge will latch the Z80 bus controls on the rising edge of the Z80_CLK input.  When low, the rising edge clock is disabled.

Enabling both clock edge control bits means that the Z80_bridge double clocks, once on the rising, then again on the falling.


*** You did not do your assignments 'Fast Input/Output/OE' for all your bus controls and OEs.  You have 2 choices, assign setup and hold timing settings in nanoseconds, or, use the 'Fast ***' feature to achieve the best possible logic cell placement of each IO for best clocking capability.  Without these assignments, every time you compile your project, each IO pin will randomly be slower or faster since the compiler will try to best locate the internal logic and not care about the speed and performance of your IOs.  This means every compile, your Z80 bus may get random IO errors which may have nothing to do with any code changes.  This is FPGA 101.

Thanks for the patch - I'm looking at the assignments currently and am getting them sorted first.  It may be FPGA 101, but as I'm starting out learning about FPGAs then maybe I can be forgiven for not knowing about this just yet?  ;)  Just to make sure, I'm in the Assignment Editor, going down the list of pins/IO connections, and changing 'Location' in the 'Assignment Name' column to Fast Output or Fast Input Register as appropriate, then selecting 'On' in the 'Value' column in place of the PIN_xx number that was there?  What do I do with the bi-directional Z80_data pins?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #816 on: January 04, 2020, 01:16:10 pm »
You have other errors:
---------------------------------
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[13] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[13] and I/O node Z80_ADDR[13] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[12] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[12] and I/O node Z80_ADDR[12] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[10] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[10] and I/O node Z80_ADDR[10] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[11] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[11] and I/O node Z80_ADDR[11] -- I/O node is a dedicated I/O pin
----------------------------------------------

Also, something weird, is says that :

   Warning (13410): Pin "245_DIR" is stuck at GND

This needs to be fixed...
Give me 30 minutes...

 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #817 on: January 04, 2020, 01:20:43 pm »
 ???

I didn't get those errors - but just compiled the project and got some messages about ignoring invalid assignments (funnily enough, all the fast assignments I'd made) and when running the GPU, the RS232_debugger reads/writes just fine, but nothing is displaying from the Microcom.  :-//
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #818 on: January 04, 2020, 01:40:53 pm »
Here you go, latest assignments added and fixed the Z80_bridge code, it should now work, but:

902340-0

I've added the assignments, 4 errors appear on 4 address lines.  Check the compilation reports now.
Did you wire those to dedicated inputs?  Their timing will not match the other address inputs if you do that.

Code: [Select]
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[13] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[13] and I/O node Z80_ADDR[13] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[12] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[12] and I/O node Z80_ADDR[12] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[10] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[10] and I/O node Z80_ADDR[10] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[11] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[11] and I/O node Z80_ADDR[11] -- I/O node is a dedicated I/O pin
Warning (176250): Ignoring invalid fast I/O register assignments. See the Ignored Assignments panel in the Fitter Compilation Report for more information.

You may want to move those 4 pins to regular IOs, they may create addressing errors.

Try out the new attached version.

 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #819 on: January 04, 2020, 01:46:29 pm »
OOOPPPSSS Change this 1 line, LINE #62 in the Z80_bridge to what I've written below:

Code: [Select]
assign Read_GPU_RAM_END =  Z80_clk_trig && (~Z80_read || ~Z80_mreq || ~mem_window) ;   // Define the ending of a Z80 read request of GPU Ram.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #820 on: January 04, 2020, 02:01:37 pm »
Here you go, latest assignments added and fixed the Z80_bridge code, it should now work, but:

(Attachment Link)

I've added the assignments, 4 errors appear on 4 address lines.  Check the compilation reports now.
Did you wire those to dedicated inputs?  Their timing will not match the other address inputs if you do that.
...
You may want to move those 4 pins to regular IOs, they may create addressing errors.

Oooh... maybe.  I just connected up the wires consecutively to the IO pins on the dev board, I didn't give any thought as to the type of pin they were... Chalk that one up to learning about FPGAs!  :-//

So I'm going to need to find alternative pins for those connections then.  ::)  Running out of pins if I want to use 24-bit RGB output as well (I've got 8 left, not including the mass of pins over the other side of the board I'd reserved for the video output...)

OOOPPPSSS Change this 1 line, LINE #62 in the Z80_bridge to what I've written below:

Code: [Select]
assign Read_GPU_RAM_END =  Z80_clk_trig && (~Z80_read || ~Z80_mreq || ~mem_window) ;   // Define the ending of a Z80 read request of GPU Ram.

Haha! Caught me mid-compilation, too.  ;)

Okay, hmmm... it's not working - I'm getting the usual display output on the screen, but when I start up the Microcom it displays the usual 'Press space to begin' in the console, but when I press space nothing happens - it just locks up - and that's before it does anything with trying to access the GPU RAM...  ???
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #821 on: January 04, 2020, 02:04:45 pm »
In the RS232 debugger, try setting the OUT3[7] bit to 1.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #822 on: January 04, 2020, 02:10:18 pm »
In the RS232 debugger, try setting the OUT3[7] bit to 1.

Okay, that stops the Microcom from hanging - but there's no output on the screen because it seems the writes are not being received properly at all.  The GPU RAM is getting corrupted badly, with $FFs where there's no writing going on, and $00s where a value should be written...
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #823 on: January 04, 2020, 02:11:25 pm »
Try changing these 3 lines:

Code: [Select]
assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  ~Z80_read ;   // Define the ending of a Z80 read request of GPU Ram.

This ignores the clocks and makes the FPGA look like static ram.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #824 on: January 04, 2020, 02:16:24 pm »
Ok, here is a new fix for the Z80 bridge:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END, mem_valid_range;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay;
reg [9:0] Z80_write_sequencer;
//reg [18:0] rd_addr;

//assign mem_valid  = (rd_addr[15] == 1'b0); // HIGH if address is inside GPU RAM bounds (GPU RAM may not fill the 512KB host memory window, so this flag determines if the address is within GPU RAM bounds)

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  ~Z80_read ;   // Define the ending of a Z80 read request of GPU Ram.

assign mem_valid_range    = (gpu_addr <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir     <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena     <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END && ~Write_GPU_RAM ) begin
Z80_245_oe <= 1'b1; // disable 245 output
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


//last_Z80_WR <= Z80_WRn;
//last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


When not reading, it would always reset the 245 buffer even if a write was being performed.  I had to make a few changes...
« Last Edit: January 04, 2020, 02:18:47 pm by BrianHG »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf