Electronics > FPGA

FPGA VGA Controller for 8-bit computer

<< < (681/734) > >>

nockieboy:

--- Quote from: BrianHG on June 23, 2022, 08:05:36 pm ---
--- Quote from: nockieboy on June 23, 2022, 11:42:26 am ---
--- Quote from: nockieboy on June 23, 2022, 07:48:04 am ---I'll keep plugging away at the side projects in the meantime - moving the MMU to HDL will be my first priority.  Once that's done I'll be able to read the MMU and discover the current bank mappings (it's write-only at the moment) without having to keep trace of them in a set of variables (which has hardly proved that accurate so far!) ;)
--- End quote ---

Hmmph, well that didn't take me long. I guess I'll start playing with the AY-8910 PSG HDL and integrate that into the design. :-/O

--- End quote ---
Ok.  So quick and simple, care to share what you did?
What did the code look like?
Can you address all 512mb?
--- End quote ---

I've been able to address all 512MB for some time now, with a couple of additional registers accessible to the host via IO that give the host access to the full DDR3 memory space by changing the 512KB 'window' that is presented.  The changes I made today were more about upgrading my existing hardware MMU, the original one that gives the Z80 access to 4MB of memory space in 16KB pages using two 74LS670s (which seem to be getting more and more scarce).  The big problem with the existing MMU setup was that it was write-only, so I had no easy way of knowing which bank was mapped to which area without keeping track of every write to the MMU in four bytes of RAM.  I was still unable to work out exactly which ROM bank the DMI or Bootstrap was loading from at cold boot.

What I did this morning was more a quick hack than a true solution to the HDL MMU task, but it gives me the same results - I'm just copying the writes to the MMU's IO addresses in the Z80_Bridge and recording the bank values.  Any reads to the MMU's four Area addresses are responded to by Bridgette with the stored value (current Bank #).  Simples.

The github project has been updated with the latest project code, including the fully working SD interface (1-bit mode currently).

Now I'm fully aware that I haven't actually replaced the hardware MMU on the uCOM's memory card just yet, but what I've done in about 10 minutes work is provide all the benefits of the HDL MMU and none of the headaches (the HDL MMU will still be limited to 16KB banks because of how the EA bus is wired on the DECA interface card).  When I decide later that I've got to build another memory card and can't find any spare LS670s any more, I can just add a few lines of HDL to Bridgette swapping the direction of the EA bus buffer and where it intercepts memory read/writes I can tell it to output the appropriate additional address data according to the current mapping value for the 16KB Area being addressed and output the correct address lanes via the EA bus.

I did have the thought this morning that I could just get the HDL MMU to map the Z80's entire 64KB RAM space into the DDR3 and remove the memory card entirely from the stack- but at the moment I feel that's a step too far in reducing my hardware project that I have enjoyed learning about, designing and building to bland HDL.  I could also make the banks smaller - say 4KB instead of the current 16KB - which would provide more flexibility.  That's a job for another day, though.  My 'quick hit' objective was completed, so it's time to move on to the sound (hopefully!) 

BrianHG:
Replicating the 74LS670 shouldn't be a problem to replicate in HDL with nothing more than a logic array: x bits by x words.

Feeding bank address bits position into that logic array, where the logic data output is wired to the upper address of the DDR3 controller to address all your ram bank by bank should also be easy.

Reset clears the array to 0,1,2,3.... to feed through the full Z80 upper address bits, 64k uninterrupted.
Also, I assume you have a write data or port into the array to fill the upper address for each bank group.


--- Code: ---IE: to get the full rw addr:

// register to hold 16 banks of 4096 words each with an extra 16 address bits.
// (This is a 256 megabyte example)
logic [15:0] page_remap [0:15] = '{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} ; // Default passes through the Z80's upper address bits untouched.

// Drive the DDR3 address with the stored banks inserted above the first 12 address bits.
assign DDR3_addr[31:0] = {4'd0, page_remap[z80_addr[15:12]], z80_addr[11:0] };

// To set a bank :
if (reset) page_remap <= '{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} ; // After reset, everything runs as a direct address feed-through.
else if (port_data_bankset_pulse) page_remap[port_data_bankset[3:0]] <= {port_data_bankadr_h,port_data_bankadr_l} ;
--- End code ---

If so, how is this so difficult to implement?
Obviously, you can parameterize the width and address bit locations, like making each bank size like 4 banks of 16k instead of 16 banks of 4k, leaving you with 1gbyte addressable space.

Also, you can make 2x page_remap arrays.  One for write data, and one for read data.

You can also pipe out an asynchronous EA bus with 1 line:

--- Code: ---EA_bus <= page_remap[z80_addr[15:12]];
--- End code ---
generating your FPGA based MMU upper address bits for external use, just don't forget to move the address bits on your peripherals.

You can go extra dumb by just using 32 ports, every 2 ports being 16 bit word of your 'page_remap' saving Z80 cpu cycles when filling the MMU table.  The 'page_remap' could also be 32 bytes of writable ram, but this will leave a hole in your address space as the MMU needs access no matter what it's contents are whereas ports wont.  Also remember, you can read as well as write ports.  Just tie the 32 port outputs into 32 port inputs of the same port number.

IE:

--- Code: ---wire [15:0] page_remap [0:15] = '{ // assign 16 banks of 4kb
{port0,port1},
{port2,port3},
{port4,port5},
{port6,port7},
{port8,port9},
{port10,port11},
{port12,port13},
{port14,port15},
{port16,port17},
{port18,port19},
{port20,port21},
{port22,port23},
{port24,port25},
{port26,port27},
{port28,port29},
{port30,port31}};

--- End code ---

or:
IE:

--- Code: ---wire [15:0] page_remap [0:3] = '{  // assign 4 banks of 16kb
{port0,port1},
{port2,port3},
{port4,port5},
{port6,port7}};

--- End code ---

Only now your reset needs to be setting ports #0-31 or 0-7.

Dont forget you can also have a separate page_remap for data and another for OP-code since our Z80 bus already decodes the op-code VS data.

nockieboy:

--- Quote from: BrianHG on June 23, 2022, 09:55:35 pm ---Replicating the 74LS670 shouldn't be a problem to replicate in HDL with nothing more than a logic array: x bits by x words.

Feeding bank address bits position into that logic array, where the logic data output is wired to the upper address of the DDR3 controller to address all your ram bank by bank should also be easy.

Reset clears the array to 0,1,2,3.... to feed through the full Z80 upper address bits, 64k uninterrupted.
Also, I assume you have a write data or port into the array to fill the upper address for each bank group.

....

If so, how is this so difficult to implement?
--- End quote ---

I didn't say it was, just that having thought through it all yesterday, there's no advantage to implementing it fully yet and my short gaps of time to work on this project are better spent elsewhere for the time being.


--- Quote from: BrianHG on June 23, 2022, 09:55:35 pm ---You can go extra dumb by just using 32 ports, every 2 ports being 16 bit word of your 'page_remap' saving Z80 cpu cycles when filling the MMU table.  The 'page_remap' could also be 32 bytes of writable ram, but this will leave a hole in your address space as the MMU needs access no matter what it's contents are whereas ports wont.  Also remember, you can read as well as write ports.  Just tie the 32 port outputs into 32 port inputs of the same port number.

...

Only now your reset needs to be setting ports #0-31 or 0-7.
--- End quote ---

I think ports are the way to go - no memory holes, I have the free ports etc.


--- Quote from: BrianHG on June 23, 2022, 09:55:35 pm ---Dont forget you can also have a separate page_remap for data and another for OP-code since our Z80 bus already decodes the op-code VS data.
--- End quote ---

Although the Z80 can differentiate opcodes from data, it is still a von Neumann processor; it doesn't separate commands from data like a Harvard processor does.  It has variable-length opcodes which would make the task of separating code from data an epically tedious process, requiring the writing of custom assemblers/disassemblers and so on, with no real benefit that I can perceive whilst writing this.

Off on a tangent now - is there any easy way to convert VHDL to Verilog other than manually?  Way back when I started this project, the choice of developing in Verilog or VHDL was a toss-of-a-coin for me as I had no experience (or knowledge) of either and I went with what the expert helping me out was familiar with. ;D  I find myself now looking at some VHDL and really wishing I could translate it to Verilog so I could understand it better and, personal opinion, I'm glad I learned Verilog and not VHDL - it looks unnecessarily wordy!

BrianHG:

--- Quote from: nockieboy on June 24, 2022, 08:37:33 am ---Off on a tangent now - is there any easy way to convert VHDL to Verilog other than manually?  Way back when I started this project, the choice of developing in Verilog or VHDL was a toss-of-a-coin for me as I had no experience (or knowledge) of either and I went with what the expert helping me out was familiar with. ;D  I find myself now looking at some VHDL and really wishing I could translate it to Verilog so I could understand it better and, personal opinion, I'm glad I learned Verilog and not VHDL - it looks unnecessarily wordy!

--- End quote ---
First make sure you need to.  You can make a verilog module which calls / instantiates your VHDL modules in the same way as if it were another verilog module.  Otherwise you are in for a ride which either may lead you back to just using the VHDL as is, or debugging a tone of peculiarities if you do not understand what the VHDL is exactly supposed to do.

Read full example here: https://www.eevblog.com/forum/fpga/vhdl-code-to-verilog-code/msg4123399/#msg4123399

  Until I finally did the authentic translation here all the way at the bottom.  We had to simulate side-by-side and verify the 2 codes were returning the same results with a list of matched random inputs going to both modules.

  Comparing the original VHDL to my final Verilog shows it can be done.

BrianHG:
In my above link, don't forget to download my final .zip showing you how to parallel simulate your VHDL vs Verilog to proof your design.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod