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

0 Members and 2 Guests are viewing this topic.

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3000 on: November 28, 2021, 12:01:58 am »
Micron might have one in their e.MMC line.  But right now, their website is messed up as I cannot see or select any part numbers including their DDR3 stuff.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3001 on: November 28, 2021, 12:21:59 am »
You can google: 'MMC card verilog simulation test model'

Read the comments in this resulting thread : https://www.edaboard.com/threads/sd-card-verilog-behavioral-model.35335/

 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3002 on: November 28, 2021, 09:25:37 am »
You can google: 'MMC card verilog simulation test model'

Read the comments in this resulting thread : https://www.edaboard.com/threads/sd-card-verilog-behavioral-model.35335/

Yeah I found that thread last night; bearing in mind the comments are over 16 years old, I couldn't find anything of use on the Samsung website mentioned - that appears to be a dead end now.  Any information at denali.com is hidden behind a user login wall on the site -  I can't even do a search for relevant information before deciding whether I want to register an account, which I'm reluctant to do when the trail to this site is so cold. :horse:

Take a look at this more recent post https://www.edaboard.com/threads/sd-emmc-card-simulation-model.365970/ and it appears that denali is a dead-end too.
« Last Edit: November 28, 2021, 09:27:35 am by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3003 on: November 29, 2021, 03:05:50 pm »
Finally, it's here: BrianHG_DDR3 V1.5.
First, the new Z80 bus interface testbench...

Each new port on the DDR3 is a read and write port instead of the separate read ports, then separate write ports.

-PLUS- we now have a DDR3 shadow write TAP port:
// **************************************************************************************
// This Write Data TAP port passes a copy of all the writes going to the DDR3 memory.
// This will allow to 'shadow' selected write addresses to other peripherals
// which may be accessed by all the multiple write ports.
// This port is synchronous to the CMD_CLK.
// **************************************************************************************

This means, any peripherals writing to the DDR3 from any of the multi-ports are ordered and copied out to this port which can be tied to all the GPU control regs and palette rams.  So, blitting / accelerated mem copies from 1 ram location to a GPU control reg will have the same write access as the Z80 originally had.  Multiple prepared palettes, screen settings, or anything anywhere in ram or even on flash card can be GPU hardware written directly into the settings address without the Z80 having to do anything other than set the start & destination address with the number of bytes to be copied.
« Last Edit: November 29, 2021, 04:23:31 pm by BrianHG »
 
The following users thanked this post: nockieboy

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3004 on: November 29, 2021, 04:22:36 pm »
Here we go, GPU with my BrianHG_DDR3 controller beta v15.
 (  :scared: All together 11084 lines of code just for the new DDR3...  :scared: )
No more timing violations with 5 ports @ 400MHz, and, there shouldn't be any even with all 16 ports in use (I hope)...

I also noticed that you made changes to the Z80_bus_interface on the last 'GPU_DECA_DDR3_new.zip' compared to my TB posted above.  I hope I got everything right in trying to catch and transfer all the changes, but you still need to verify these 2 settings:

Code: [Select]
   .Z80_DELAY_WAIT_RI     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
   .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Memory cycle.

Check to see the lowest number which properly prevents the 'WAIT' from being asserted during a read cache hit condition.

Also check for the 'filled-box' graphical glitch which happens occasionally on the left most of a new line.

If everything works, you can try connecting your palette ram to the new 'Write Data TAP port'.  You will need to filter the address range for the palette and pass the appropriate write mask bits as the write data width is 128bits with 16 wmask bits.  You will also need to shift the write address.
« Last Edit: November 29, 2021, 04:53:50 pm by BrianHG »
 
The following users thanked this post: nockieboy

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3005 on: November 29, 2021, 04:31:00 pm »
Next I will update my DDR3 github, then if everything is ok with the GPU, I will look at re-doing my Display MEM and make a new VGA/HDMI output section where you can properly change color depth and resolutions plus add multiple layers.
« Last Edit: November 29, 2021, 04:59:11 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3006 on: November 29, 2021, 06:22:25 pm »
Here we go, GPU with my BrianHG_DDR3 controller beta v15.
 (  :scared: All together 11084 lines of code just for the new DDR3...  :scared: )
No more timing violations with 5 ports @ 400MHz, and, there shouldn't be any even with all 16 ports in use (I hope)...

I also noticed that you made changes to the Z80_bus_interface on the last 'GPU_DECA_DDR3_new.zip' compared to my TB posted above.  I hope I got everything right in trying to catch and transfer all the changes, but you still need to verify these 2 settings:

Code: [Select]
   .Z80_DELAY_WAIT_RI     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
   .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Memory cycle.

Check to see the lowest number which properly prevents the 'WAIT' from being asserted during a read cache hit condition.

Also check for the 'filled-box' graphical glitch which happens occasionally on the left most of a new line.

Not seeing any glitches at all in the filled boxes now - display output is very clean. :-+

If everything works, you can try connecting your palette ram to the new 'Write Data TAP port'.  You will need to filter the address range for the palette and pass the appropriate write mask bits as the write data width is 128bits with 16 wmask bits.  You will also need to shift the write address.

I've tidied up a couple of bits, added-in some missing connections from the Z80_Bridge and added the SD modules that I'm working on currently.  I've attached the project here so that we've both got the latest version and we don't have to keep amending/altering individual files with new updates.

As far as the palette RAM comment goes - erm.. The palettes sits in the FPGA's block RAM, doesn't it?  I'm going to have to go refresh my memory on how the palette works within the GPU and learn about this Write Data TAP port.
 
The following users thanked this post: BrianHG

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3007 on: November 30, 2021, 10:06:37 am »
I've tidied up a couple of bits, added-in some missing connections from the Z80_Bridge and added the SD modules that I'm working on currently.  I've attached the project here so that we've both got the latest version and we don't have to keep amending/altering individual files with new updates.

As far as the palette RAM comment goes - erm.. The palettes sits in the FPGA's block RAM, doesn't it?  I'm going to have to go refresh my memory on how the palette works within the GPU and learn about this Write Data TAP port.
What's with all the warnings?

Code: [Select]
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_WAIT" to top-level pin "pre_syn.bp.Z80_BRIDGE_Z80_WAIT". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[7]" to top-level pin "GPIO1_D[11]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[6]" to top-level pin "GPIO1_D[12]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[5]" to top-level pin "GPIO1_D[13]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[4]" to top-level pin "GPIO1_D[14]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[3]" to top-level pin "GPIO1_D[15]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[2]" to top-level pin "GPIO1_D[16]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[1]" to top-level pin "GPIO1_D[17]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[0]" to top-level pin "GPIO1_D[18]". Did not propagate pin attribute to the other top-level pins listed below

Info (286031): Timing-Driven Synthesis is running on partition "Top"
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_CMD" driven by bidirectional pin "SD_CMD" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_0_" driven by bidirectional pin "SD_DAT[0]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_1_" driven by bidirectional pin "SD_DAT[1]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_2_" driven by bidirectional pin "SD_DAT[2]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_3_" driven by bidirectional pin "SD_DAT[3]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_21_" driven by bidirectional pin "GPIO0_D[14]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_20_" driven by bidirectional pin "GPIO0_D[15]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_19_" driven by bidirectional pin "GPIO0_D[16]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_18_" driven by bidirectional pin "GPIO0_D[17]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_17_" driven by bidirectional pin "GPIO0_D[18]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_16_" driven by bidirectional pin "GPIO0_D[19]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_15_" driven by bidirectional pin "GPIO0_D[20]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_14_" driven by bidirectional pin "GPIO0_D[21]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_13_" driven by bidirectional pin "GPIO0_D[26]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_12_" driven by bidirectional pin "GPIO0_D[27]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_11_" driven by bidirectional pin "GPIO0_D[28]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_10_" driven by bidirectional pin "GPIO0_D[29]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_9_" driven by bidirectional pin "GPIO0_D[30]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_8_" driven by bidirectional pin "GPIO0_D[31]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_7_" driven by bidirectional pin "GPIO0_D[34]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_6_" driven by bidirectional pin "GPIO0_D[35]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_5_" driven by bidirectional pin "GPIO0_D[36]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_4_" driven by bidirectional pin "GPIO0_D[37]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_3_" driven by bidirectional pin "GPIO0_D[38]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_2_" driven by bidirectional pin "GPIO0_D[39]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_1_" driven by bidirectional pin "GPIO0_D[40]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_0_" driven by bidirectional pin "GPIO0_D[41]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_WAIT_INn" driven by bidirectional pin "GPIO1_D[0]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_CLK" driven by bidirectional pin "GPIO1_D[3]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_RDn" driven by bidirectional pin "GPIO1_D[4]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_WRn" driven by bidirectional pin "GPIO1_D[5]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_MREQn" driven by bidirectional pin "GPIO1_D[6]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_IORQn" driven by bidirectional pin "GPIO1_D[7]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_M1n" driven by bidirectional pin "GPIO1_D[8]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_7_" driven by bidirectional pin "GPIO1_D[11]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_6_" driven by bidirectional pin "GPIO1_D[12]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_5_" driven by bidirectional pin "GPIO1_D[13]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_4_" driven by bidirectional pin "GPIO1_D[14]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_3_" driven by bidirectional pin "GPIO1_D[15]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_2_" driven by bidirectional pin "GPIO1_D[16]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_1_" driven by bidirectional pin "GPIO1_D[17]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_0_" driven by bidirectional pin "GPIO1_D[18]" cannot be tri-stated
Critical Warning (18061): Ignored Power-Up Level option on the following registers
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[1] will power up to Low
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[2] will power up to High
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[7] will power up to High
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[1] will power up to Low
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[2] will power up to High
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[7] will power up to High


What did you do?
The GPU I sent you doesn't have all of these...
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3008 on: November 30, 2021, 10:56:57 am »
I added in the extra pins for Z80_INTACKn, Z80_INT_INn, Z80_WAIT_INn to the Z80_Bus_Interface.sv (they're mostly unused, except Z80_WAIT_INn which can be used by SignalTap to see when the WAIT line goes low).  These are additional lines available to the GPU with the latest uCOM/DECA interface card version and are all inputs that can be ignored.

The SD card modules can be removed/ignored - there's going to be warnings generated by them as they're in the middle of development and may be incomplete or just plain wrong.

I have no idea why all the '...cannot be tri-stated' warnings are there.  I've not done anything with the other Z80 bus lines - at least afaik.  There's always the possibility I've made a typo or silly mistake somewhere, but it builds and works. :-//

EDIT:  I also grouped all the CMD_xxxx assigns together.  I've compiled the design with the additional signals above commented-out, in case they were causing the error, but no change.  It's the SD card modules - I've removed them and it compiles fine, with very limited warnings.
« Last Edit: November 30, 2021, 11:14:39 am by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3009 on: November 30, 2021, 11:13:52 am »
You might need to go back a version, then, add the new stuff 1 by 1 looking to see when the error arises.


Anyways, to help you see what the 'TAP_xxx' port does, take a look at my attached BrianHG_DDR3_v15 block diagram:



Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

I guess 1 parameter A will contain the total number of 'reset' presets you wish to enter and the second parameter will be an array with '{{address hex,data value hex},{address hex,data value hex},{address hex,data value hex},...}.

It may be useful to have the defaults at 16bit instead of 8 bit for convenience since all our presets will be 16bit or 32bit quantities.

Your gonna need a fancy write into the array since the source data is 128bit, but you want an 8bit output.
 
The following users thanked this post: nockieboy

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3010 on: November 30, 2021, 11:19:48 am »
You might need to go back a version, then, add the new stuff 1 by 1 looking to see when the error arises.

It's the SD module - comment out lines 770-837 in GPU_DECA_DDR3_top.sv and all the warnings go away.  I'm going to take a break from the SD side for a while, I think. ::)

Anyways, to help you see what the 'TAP_xxx' port does, take a look at my attached BrianHG_DDR3_v15 block diagram:

Thanks for this.  I'll go away and focus on this for a while instead! ;D

Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

You mean like the GPU_HW_Control_Regs?

I guess 1 parameter A will contain the total number of 'reset' presets you wish to enter and the second parameter will be an array with '{{address hex,data value hex},{address hex,data value hex},{address hex,data value hex},...}.

It may be useful to have the defaults at 16bit instead of 8 bit for convenience since all our presets will be 16bit or 32bit quantities.

Your gonna need a fancy write into the array since the source data is 128bit, but you want an 8bit output.

Righto, leave it with me. :-+
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3011 on: November 30, 2021, 11:27:25 am »
Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

You mean like the GPU_HW_Control_Regs?

You got it exactly  :-+

Once we have the new 'GPU_HW_REGS[7..0][0..16383]', with a reset powerup settings, we can feed selected bytes into anything, like my display_rmem controls.  Then you could change resolution, move screen buffer addresses and scroll offset from the Z80 as the first test.

Also, you can connect your palette port_b's write enable directly to the TAP_xxx with an address range selector anded with the write enable & byte enable for the 4 byte wide data so that the Z80 can write and read a new color palette.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3012 on: November 30, 2021, 08:09:43 pm »
Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

I guess 1 parameter A will contain the total number of 'reset' presets you wish to enter and the second parameter will be an array with '{{address hex,data value hex},{address hex,data value hex},{address hex,data value hex},...}.

It may be useful to have the defaults at 16bit instead of 8 bit for convenience since all our presets will be 16bit or 32bit quantities.

Something like this?

Code: [Select]
parameter HW_REGS_SIZE = 14    ; // 2^14 = 16384 bytes
parameter int RST_PARAM_SIZE = 8     ;
parameter int BASE_WRITE_ADDRESS = 20'h0 ;

parameter RESET_VALUES[RST_PARAM_SIZE] = '{
{8'h01, 8'h10}, {8'h03, 8'h10}, {8'h04, 8'h02}, {8'h05, 8'h8F},
{8'h06, 8'h01}, {8'h07, 8'hEF}, {8'h09, 8'h8C}, {8'h0B, 8'h86},
};

I've used 8-bit values, but will convert to 16-bit if I'm on the right path and you can answer this question; are we setting these 16-bit values in big-endian or little-endian format?  I could just use e.g. {16'h01, 16'h10} as a value if endianness matches up, I guess?
« Last Edit: November 30, 2021, 10:18:50 pm by nockieboy »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3013 on: November 30, 2021, 10:49:26 pm »
Ok, so far, so good.
Now for the reset values, the issue here is that the FPGA doesn't have 16kb of registers (that would be a 160k reg/gate fpga).  What we are doing is selectively using reg at our convenience from that 16kb, not every one.  This also means we do not and need not assign 16kb of reset values.  The fewer resets we assign, the better.  So, for the default/reset RESET_VALUES, we want the '1:RST_PARAM_SIZE' for the number of entries, and inside the reset values, we want to define the 14'hxxxx address and the 8'hxx data so that in your verilog if(reset), you perform a for loop from 1 to RST_PARAM_SIZE, and read in that loop read the 14'hxxxx address and assign the HW_REGS[14'hxxxx] <= 8'hxx.

This will allow you to selective indvidualy define reset values as specific points...

reset values will most likely look like:
parameter bit [23:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......

Where the contents will be 24'haaaadd, ....
[aaaa] being a 16 bit address and [dd] being 8 bit data.

Then in the for loop, you can select 14 of the upper 16 bits for the address pointer and use the lower 8 bits for the reset data.  Or you can go straight to [31:0] and assign 16 bit data presets which will be easier since the majority of our presets will be 16bits long.


Inside the for loop, you should apply 8bits at a time and make an option to swap endian just in case.

Also, remember that in the main write data loop, the TAP_ data is 128bit with byte enables for the 16 bytes in the 128bit.  Make a parameter on-top to select the bus TAP width of 128 bits and and the TAP address does go down to the 'byte', but the lower address bits are always equal to 0'.  And when you store the data coming in, remember you wand an endian parameter option there too.

« Last Edit: November 30, 2021, 10:53:47 pm by BrianHG »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3014 on: November 30, 2021, 11:02:38 pm »
I have yet to use it packed bits like this, but this should also be possible:

parameter bit [13:0][7:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......
or
parameter bit [13:0][15:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......

Just stick with the previous one unless you prove it's usefullness.

Also, for the HW_REGS module, make it a stand alone module and test in modelsim by initiating it inside:
Z80_Interface_TB_v15 / Z80_Bus_Interface_to_DDR3_tb.sv . (around line 580...)

Update the 'setup_z80_to_DDR3.do' and 'run_z80_to_DDR3.do' to include the new HW_REGS.sv source.
In the 'setup_z80_to_DDR3.do', add the HW_REGS to the waveform display.

Modify the 'Z80_cmd_stimulus.txt' to test that write memory works and that read memory has no effect.
Also remember that you can test the reset in the 'Z80_cmd_stimulus.txt' as well.

Don't forget to use my parameter names for the TAP widths.
And make the HW_REG size in memory adjustable as for testing, maybe 256/1024 bytes total will be enough.
« Last Edit: December 01, 2021, 12:32:38 am by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3015 on: December 01, 2021, 11:37:08 am »
Ok, so far, so good.
Now for the reset values, the issue here is that the FPGA doesn't have 16kb of registers (that would be a 160k reg/gate fpga).  What we are doing is selectively using reg at our convenience from that 16kb, not every one.  This also means we do not and need not assign 16kb of reset values.  The fewer resets we assign, the better.  So, for the default/reset RESET_VALUES, we want the '1:RST_PARAM_SIZE' for the number of entries, and inside the reset values, we want to define the 14'hxxxx address and the 8'hxx data so that in your verilog if(reset), you perform a for loop from 1 to RST_PARAM_SIZE, and read in that loop read the 14'hxxxx address and assign the HW_REGS[14'hxxxx] <= 8'hxx.

This will allow you to selective indvidualy define reset values as specific points...

reset values will most likely look like:
parameter bit [23:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......

Where the contents will be 24'haaaadd, ....
[aaaa] being a 16 bit address and [dd] being 8 bit data.

Then in the for loop, you can select 14 of the upper 16 bits for the address pointer and use the lower 8 bits for the reset data.  Or you can go straight to [31:0] and assign 16 bit data presets which will be easier since the majority of our presets will be 16bits long.


Inside the for loop, you should apply 8bits at a time and make an option to swap endian just in case.

Okay, this is where I am with the HW_REGS module right now:

Code: [Select]
module HW_REGS (

        input                               RESET,
        input                               CLK,
        input                               WE,
        input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
        input         [PORT_CACHE_BITS-1:0] DATA_IN,
        input       [PORT_CACHE_BITS/8-1:0] WMASK,
        output  reg                 [  7:0] HW_REGS[0:(2**HW_REGS_SIZE-1)],
        output  reg                 [  7:0] DATA_OUT

);

parameter int           PORT_ADDR_SIZE                  = 19       ; // This parameter is passed by the top module
parameter int           PORT_CACHE_BITS                 = 128      ; // This parameter is passed by the top module
parameter               ENDIANNESS                      = "LITTLE" ; // Specify endianness of the reset values
parameter               HW_REGS_SIZE                    = 14       ; // 2^14 = 16384 bytes
parameter int           RST_PARAM_SIZE                  = 2        ; // Number of default values
parameter int           BASE_WRITE_ADDRESS              = 20'h0    ; // Where the HW_REGS are held in RAM
parameter bit   [31:0]  RESET_VALUES[1:RST_PARAM_SIZE]  = '{
    {16'h00, 16'h10}, {16'h02, 16'h10}
};

wire enable   = ( ADDR_IN[PORT_ADDR_SIZE-1:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[PORT_ADDR_SIZE-1:HW_REGS_SIZE] ) ;   // upper x-bits of ADDR_IN should equal BASE_WRITE_ADDRESS for a successful read or write
wire valid_wr = WE && enable ;

integer i;
always @( posedge CLK ) begin
   
    if ( RESET ) begin
        // reset registers to initial values
        for (i = 0; i < RST_PARAM_SIZE; i = i + 1) begin
            if (ENDIANNESS == "LITTLE") begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][ 7:0] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][15:8] ;
            end else begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][15:8] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][ 7:0] ;
            end
        end
    end
    else
    begin
        if (valid_wr) begin
            // apply written value to addressed register
            //HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] <= DATA_IN ;
        end
    end
   
    if (enable) begin
        //data_out <= HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] ;
    end else begin
        data_out <= 0 ;
    end
   
end

endmodule

The commented-out lines in (valid_wr) and (enable) are relics from the old GPU_HW_REGS module, which I'll be replacing with something more advanced to extract the data required from the 128-bit DATA_IN bus later.

Also, remember that in the main write data loop, the TAP_ data is 128bit with byte enables for the 16 bytes in the 128bit.  Make a parameter on-top to select the bus TAP width of 128 bits and and the TAP address does go down to the 'byte', but the lower address bits are always equal to 0'.  And when you store the data coming in, remember you wand an endian parameter option there too.

I need to look at the content of TAP_WMASK and each high bit will correspond to a valid byte in DATA_IN.  Are valid bytes always the lowest sequential ones, or will there ever be non-written bytes between the write bytes?  Will these valid bytes always follow the {16'address,16'data} format I'm using for the RESET_VALUES?


EDIT:  Thinking about my last questions, I guess the bytes will always be sequential as the DDR3_Controller will stack them up in the FIFO - and the format will follow whatever format the bytes have been written to RAM in, so that's down to the host software.
« Last Edit: December 01, 2021, 11:42:14 am by nockieboy »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3016 on: December 01, 2021, 11:55:26 am »
This is what I've just thrown together based on my understanding of TAP_WDATA and TAP_WMASK:

Code: [Select]
    begin
        if (valid_wr) begin
            // apply written value to addressed register
            //HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] <= DATA_IN ;
            for(i = 0; i < PORT_CACHE_BITS/8; i = i + 1) begin
                if (WMASK[i:i]) begin
                    if (ENDIANNESS == "LITTLE") begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+7:i*32]    ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+15:i*32+8] ;
                    end else begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+15:i*32+8] ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+7:i*32]    ;
                    end
                end
            end
        end
    end

Is this along the right lines for writing to the HW_REGS?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3017 on: December 01, 2021, 11:57:02 am »
The mask is like a write enable for every 16 bytes in the case of the data bus being 128 bit.  If the data bus was 256 bit, then there would be 32 bytes.

Note that Modelsim prefers the parameters placed before the IO ports, otherwise the parameter width settings will not be ready yet for the width settings in the IO ports.  Take a look at any of my latest .sv code...

You can get rid of the if (enable) data out section, after writing a value, if the Z80 does a read, it will get the contents from the DDR3.

Your reset looks OK.
For your valid_wr, you will need to make a 2 layer loop, the outer one which incs (PORT_CACHE_BITS/8) as the inner will inc 1 at a time from 0 to (PORT_CACHE_BITS/8-1), using a second write enable for the WMASK[innerloopcounter] while adding the 2 loop counters together to generate the write address.  Don't forget to select the correct part of WDATA by using WDATA[innerloopcounter*8+:8]

No endian option for the valid_wr section.  If you did want to, it would be weird as the source data is 128 bits, not 32 or 16.

And, dont forget to simulate it...
« Last Edit: December 01, 2021, 11:59:28 am by BrianHG »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3018 on: December 01, 2021, 12:04:49 pm »
This is what I've just thrown together based on my understanding of TAP_WDATA and TAP_WMASK:

Code: [Select]
    begin
        if (valid_wr) begin
            // apply written value to addressed register
            //HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] <= DATA_IN ;
            for(i = 0; i < PORT_CACHE_BITS/8; i = i + 1) begin
                if (WMASK[i:i]) begin
                    if (ENDIANNESS == "LITTLE") begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+7:i*32]    ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+15:i*32+8] ;
                    end else begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+15:i*32+8] ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+7:i*32]    ;
                    end
                end
            end
        end
    end

Is this along the right lines for writing to the HW_REGS?
Ok, close, bu no endianess here.
Also try this line instead:
Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
It seems smaller than your example.
« Last Edit: December 01, 2021, 12:07:10 pm by BrianHG »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3019 on: December 01, 2021, 12:15:17 pm »
Ok, close, bu no endianess here.
Also try this line instead:
Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Yes, if we're not worried about endianness it simplifies the logic a little - and I was confusing the format of RESET_VALUES with DATA_IN, overcomplicating the logic massively. |O

It seems smaller than your example.
I get that a lot. :-DD

Okay, will try simulating later this afternoon if there's nothing else I need to do with it?

Full code here:
Code: [Select]
module HW_REGS (

        input                               RESET,
        input                               CLK,
        input                               WE,
        input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
        input         [PORT_CACHE_BITS-1:0] DATA_IN,
        input       [PORT_CACHE_BITS/8-1:0] WMASK,
        output  reg                 [  7:0] HW_REGS[0:(2**HW_REGS_SIZE-1)],
        output  reg                 [  7:0] DATA_OUT

);

parameter int           PORT_ADDR_SIZE                  = 19       ; // This parameter is passed by the top module
parameter int           PORT_CACHE_BITS                 = 128      ; // This parameter is passed by the top module
parameter               ENDIANNESS                      = "LITTLE" ; // Specify endianness of the reset values
parameter               HW_REGS_SIZE                    = 14       ; // 2^14 = 16384 bytes
parameter int           RST_PARAM_SIZE                  = 2        ; // Number of default values
parameter int           BASE_WRITE_ADDRESS              = 20'h0    ; // Where the HW_REGS are held in RAM
parameter bit   [31:0]  RESET_VALUES[1:RST_PARAM_SIZE]  = '{
    {16'h00, 16'h10}, {16'h02, 16'h10}
};

wire enable   = ( ADDR_IN[PORT_ADDR_SIZE-1:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[PORT_ADDR_SIZE-1:HW_REGS_SIZE] ) ;   // upper x-bits of ADDR_IN should equal BASE_WRITE_ADDRESS for a successful read or write
wire valid_wr = WE && enable ;

integer i;
always @( posedge CLK ) begin
   
    if ( RESET ) begin
        // reset registers to initial values
        for (i = 0; i < RST_PARAM_SIZE; i = i + 1) begin
            if (ENDIANNESS == "LITTLE") begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][ 7:0] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][15:8] ;
            end else begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][15:8] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][ 7:0] ;
            end
        end
    end
    else
    begin
        for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && WMASK[i]) HW_REGS[(ADDR_IN | i)] <= DATA_IN[i*8+:8] ;
    end
   
end

endmodule
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3020 on: December 01, 2021, 12:20:29 pm »
You want the reverse endian, here you go:

Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i ^ ENDIAN]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Just make ENDIAN = 1 for 16 bit reverse endian, or make it 3 for 32 bit reverse endian.  Happy?  Only 7 more characters.

Dont forget to move the parameters to the top of the code for Modelsim compatibility and next put the code into my Z80_bus_interface_to_DDR3 and simulate.

 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3021 on: December 01, 2021, 02:36:27 pm »
You want the reverse endian, here you go:

Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i ^ ENDIAN]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Just make ENDIAN = 1 for 16 bit reverse endian, or make it 3 for 32 bit reverse endian.  Happy?  Only 7 more characters.

Dont forget to move the parameters to the top of the code for Modelsim compatibility and next put the code into my Z80_bus_interface_to_DDR3 and simulate.

What about reads from HW_REGS?  Is there any need for DATA_OUT?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3022 on: December 01, 2021, 07:44:38 pm »
You want the reverse endian, here you go:

Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i ^ ENDIAN]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Just make ENDIAN = 1 for 16 bit reverse endian, or make it 3 for 32 bit reverse endian.  Happy?  Only 7 more characters.

Dont forget to move the parameters to the top of the code for Modelsim compatibility and next put the code into my Z80_bus_interface_to_DDR3 and simulate.

What about reads from HW_REGS?  Is there any need for DATA_OUT?


You can get rid of the if (enable) data out section, after writing a value, if the Z80 does a read, it will get the contents from the DDR3.


Remember, with the 'TAP_xxxx' port, you are tapping writes to the DDR3 meaning the you see the written data, but the DDR3 also gets a copy of the same data at the same address.
« Last Edit: December 01, 2021, 07:46:36 pm by BrianHG »
 
The following users thanked this post: nockieboy

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #3023 on: December 01, 2021, 11:11:44 pm »
Remember, with the 'TAP_xxxx' port, you are tapping writes to the DDR3 meaning the you see the written data, but the DDR3 also gets a copy of the same data at the same address.

D'oh.  I'd forgotten that.  Okay, well I've got ModelSim 20.1 running, have tried to run the simulation and am getting this error:

Code: [Select]
** Error: (vsim-3033) Instantiation of 'HW_Regs' failed. The design unit was not found.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_to_DDR3_tb File: Z80_Bus_Interface_to_DDR3_tb.sv Line: 627
#         Searched libraries:
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/altera
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/220model
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/sgate
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/altera_mf
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/altera_lnsim
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/cycloneive
#             D:/FPGA/Projects/GPU/test/Z80_Interface_TB_v15/work
# Loading work.Z80_Bus_Interface
# Error loading design
# Error: Error loading design
#        Pausing macro execution
# MACRO ./setup_z80_to_DDR3.do PAUSED at line 20

I'll take a closer look tomorrow, but I've probably missed something really basic.  ::)
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #3024 on: December 02, 2021, 05:31:42 am »
Update the 'setup_z80_to_DDR3.do' and 'run_z80_to_DDR3.do' to include the new HW_REGS.sv source.
In the 'setup_z80_to_DDR3.do', add the HW_REGS to the waveform display.
In both of your xxxxxx.do files, you did not add the:
vlog -sv -work work {HW_Regs.sv}

Like this:
Code: [Select]
vlog -sv -work work {BrianHG_DDR3/altera_gpio_lite.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_GEN_tCK.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_PLL.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_FIFOs.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_CMD_SEQUENCER.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_IO_PORT_ALTERA.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_PHY_SEQ.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_COMMANDER_v15.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_CONTROLLER_v15_top.sv}
vlog -sv -work work {HW_Regs.sv}
vlog -sv -work work {Z80_Bus_Interface.sv}
vlog -sv -work work {Z80_Bus_Interface_to_DDR3_tb.sv}

Look at the third to last line...
Don't forget to add the line to both the setup and run...

You have other bugs too, but, you can figure them out
You will also want to add the 'HW_REGS' output to the waveform display in the 'setup_xxxx.do'.

Let's see how many bugs you can find and patch.

Also, if I were you, change the HW_REGS size in your sim to a total of 64 instead of 16k.  If you have the HW_REGS displayed on your waveform and it has 16k entries, every recompile will take a dumb amount of time just for clearing out the waveform display's contents, then replacing it as it's height will at least be 16384 rows tall.
« Last Edit: December 02, 2021, 08:21:28 am by BrianHG »
 
The following users thanked this post: nockieboy


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf