Darn that Z80_bridge has turned into a mess, however, there are valid reasons why.
Do you have a simulation setup? If so, post it here...
Yes, it has become a bit messy since I have added stuff for testing and trying to get IO RD/WR from the Z80 working. I guess I should housekeep the code more often.
Test setup for the Z80_bridge attached. This is what I used in the other thread when I was testing the IO cycle.
What do you mean by 'denounce'? Not sure on the terminology here.
What do you mean by 'denounce'? Not sure on the terminology here.DE-Bounce. Bloody auto-correct.

Ok, I converted the GPU ram port from 8bit into a dynamic 16bit version.... I also had to modify the compiler settings to ensure the compiler would meet the timing for the GPU ram as the old settings were receiving a few address & write_enable bits a little late. Though, it was there in your existing version, it probably didn't cause any problem as the silicon usually performs better than the compiler's report which takes into consideration the worst possible conditions based on the set operating specs.
Let me know if the attached project works. If so, you will need to switch to that project from now on.

Also, why do you have your palette system memory set shy of 32k and your palette memory set right after?

Quartus still wasted the Cyclone's ram with the missing bytes in the main system memory with 32k and then wrote the separate palette memory in that shared address space. Also, why is the main system memory an odd number of bytes? You should have used 32768 for main ram and 32768 for the offset of the palette memory. But, you could have gone even a bit larger on the main system memory. See here:
(Attachment Link)
With the attached project and my settings, you now have 41kb, just enough memory for a 320x240 16 color screen plus a 256 character 8x8 pixel font. Or, 640x240 4 color, or 640x480 2 color screen. Even 160x240 @ 256 colors, 160x120 @ 65536 colors.
It should compile and function.
What where you able to discern from that?
I've attached the project with the actual Z80 vectors in the waveform editor. The Z80 clock is set to 8 Mhz and the gpu clk is set to 125MHz. The bus transaction timing you see is real from the Z80 datasheet, or as close as I can get it based on the poor datasheets I have access to.
Is there anything new you can gather from my layout?
Do you have any new insights when zooming into the simulation?
You need to shore up the Z80_bridge and add a few test signal tap signals to see whats going on inside your bridge.
Also, now it may be time to look at taking into account the Z80 CLK so that you wait for the next edge before reading the bus status too quickly before all the data and address lines are ready.
Note that we are missing the 'Z80_nWAIT' signal. The Z80 seems to assert it during a port read or port write.
It also seems if you were to read or write a memory address that the access is 1 clock faster as those transfers do not force that 1 clock cycle wait state.
(Note that for the Z80 data input, I made the data = $D0 when the Z80 outputs the correct data and make that same signal $D1 for the complete amount of time the Z80 expects to receive read valid data.)
Are you thinking the D1s are faults? The datasheet shows an overlap for valid data at the end of the MREQ / IOREQ cycle, but the timing charts quote 0 ns for that time for a 10 MHz Z80 CPU, so in reality there is no need for the data to be held past the end of the MREQ/IOREQ cycles.
It does seem that z80_DATA_DIR and z80_BDIR_EN are HIGH for a long time before the Z80 actually needs to read the data off the bus.
The way you read the data sheet, for the data in and data out, the small time slot where the Z80 has the 'D1' means that you need to present valid data to the Z80 beginning anytime before that time slot begins, and then hold data on the bus until after the 'D1' time slot ends.
Now, do we send data to the Z80, figuring it takes an additional 5-10ns for the data to get there from the assertion of the OE & data out signals, will the data reach the Z80 in time to ensure a good read?
Now, do we hold that data we are sending out to the Z80 long enough until the end of the Z80 'D1' time slot that we guarantee the Z80 will receive a correct byte?
Also, about the wait state, if you look at the port read and write, there is an extra Z80 clock cycle, wait state which you may need to wait before beginning a transaction just to be safe.
You have the function in your Z80 module, but not a basic setup where you can manipulate a response. You need to clean that up.
In the other direction, a Z80 write, you should be taking the data from the Z80 data bus after the valid 'D0' time has begun and before it ends. Now there is an additional caveat here too. Yo need to consider all the delays created by you bus' potential load on the data lines as well as the address lines.
Looking at you existing Z80 bridge, you can see you don't hold the data output until the period 'D1' ends. Electrical capacitance on the data bus or a fast Z80 may be whats keeping your read data clean. See here:
(Attachment Link)
Ok, I completely redone your Z80 bridge and present to you the new Z80_bridge_v2.sv. It operated based on the bus commands which are each filtered through programmable bidirectional 'hysteresis' timers.

I did almost everything except for the port inputs and outputs. I did leave an example port read and write in the code with a dummy test counter for the keyboard read, use this to test the keyboard port access as each read should increment the returned value by 1, and an example port write to the speaker. If reading the keyboard reveals a perfect 8 bit counter every read, but your keyboard interface still glitches with this Z80 bridge, then the error lies in you keyboard decoder source code.
The code is much simpler than what you had. I wasn't sure about the port address width so I made it 16 bits. If it needs changing, I'm sure you can fix this yourself.
This is borne out with practical experience - I get zero memory read errors in practice, so holding the data past the end of a RD cycle seems unnecessary, unless I'm missing something?
This is borne out with practical experience - I get zero memory read errors in practice, so holding the data past the end of a RD cycle seems unnecessary, unless I'm missing something?With that data sheet, no you are not. You can use a filter value of 1 or 0 if you like.

As for the port reads, did you try using my dummy internal counter example read?
If that internal counter works, its the way you retrieve data from the PS2 keyboard vhdl module which is messing up.
Z80_rData <= PS2_CHAR;
PS2_CHAR <= 8'b0;Note that you can set the Z80 to operate off the Z80 clk input and for the ports, you can add a second filter parameter of 1 or 2 instead of 0 to delay the input/output data past that 'TW' added state.
This is why I made the module the way I did. You can separate clocks, either GPUclk or Z80clks for each command without modifying the basic input/output data and OE part.

Ooops, you posted the 'OLD' bridge.sv...

Also, to get around your long compile times, send me your current project and I will send it back (renamed) with compiler setting plus a few items removed to get it to compile in 45 seconds...
Okay, no worries.
port_dly[12:1] <= port_dly[11:0];port_dly[12:0] <= { port_dly[11:0], 1'b0 };
How did you do that IO read delay?
if ( ~z80_op_read_port && (z80_read_port_fc != 1'd0 ) ) z80_read_port_fc <= z80_read_port_fc - 1'd1;
else if ( z80_op_read_port && (z80_read_port_fc != Z80_CLK_FILTER[2:0] ) ) z80_read_port_fc <= z80_read_port_fc + 1'd1;
if ( ~z80_op_read_port && (z80_read_port_fc == 1'd0 ) ) z80_read_port <= 1'b0;
else if ( z80_op_read_port && (z80_read_port_fc == Z80_CLK_FILTER[2:0] ) ) z80_read_port <= 1'b1;
if ( ~z80_op_read_port && (z80_read_port_fc != 1'd0 ) ) z80_read_port_fc <= z80_read_port_fc - 1'd1;
else if ( z80_op_read_port && (z80_read_port_fc != Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port_fc <= z80_read_port_fc + 1'd1;
if ( ~z80_op_read_port && (z80_read_port_fc == 1'd0 ) ) z80_read_port <= 1'b0;
else if ( z80_op_read_port && (z80_read_port_fc == Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port <= 1'b1;
How did you do that IO read delay?

It makes no sense...
You were only supposed to edit these lines:Code: [Select]if ( ~z80_op_read_port && (z80_read_port_fc != 1'd0 ) ) z80_read_port_fc <= z80_read_port_fc - 1'd1;
else if ( z80_op_read_port && (z80_read_port_fc != Z80_CLK_FILTER[2:0] ) ) z80_read_port_fc <= z80_read_port_fc + 1'd1;
if ( ~z80_op_read_port && (z80_read_port_fc == 1'd0 ) ) z80_read_port <= 1'b0;
else if ( z80_op_read_port && (z80_read_port_fc == Z80_CLK_FILTER[2:0] ) ) z80_read_port <= 1'b1;
To something like:Code: [Select]if ( ~z80_op_read_port && (z80_read_port_fc != 1'd0 ) ) z80_read_port_fc <= z80_read_port_fc - 1'd1;
else if ( z80_op_read_port && (z80_read_port_fc != Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port_fc <= z80_read_port_fc + 1'd1;
if ( ~z80_op_read_port && (z80_read_port_fc == 1'd0 ) ) z80_read_port <= 1'b0;
else if ( z80_op_read_port && (z80_read_port_fc == Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port <= 1'b1;
Same for the write port.
I went through all that hassle so you could keep the read and write ports and ram all the same as I had it, not special circumventing work around code. If you wanted a special delay state for any of the bus transaction, just add or subtract a number in my command filter section.
if ( z80_read_opcode || z80_read_memory || z80_read_port ) begin // this section sets the output enable sends the correct data back to the Z80if ( ~Z80_RDn_r ) begin // this section sets the output enable sends the correct data back to the Z80

if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin // Z80 is reading PS/2 port
Z80_rData <= PS2_CHAR;
PS2_CHAR <= 8'b0;
endSomething weird is going on with the keyboard input.
If I do individual 'IN' commands, or a sequence of them, to the PS2_STAT port, I get a nice incrementing number.
.If I switch to polled keyboard input (so the 'OS' is constantly polling the PS2_DATA port for ASCII chars) - and I press a key on the keyboard - the screen fills with that key and the system locks up.
All I have changed in the Z80_bridge you sent was this:Code: [Select]if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin // Z80 is reading PS/2 port
Z80_rData <= PS2_CHAR;
PS2_CHAR <= 8'b0;
end
if (PS2_RDY) begin // valid data on PS2_DAT
PS2_CHAR <= PS2_DAT; // Latch the character into Ps2_char register
endreg [7:0] PS2_RDY_r;
.......
PS2_RDY_r[7:0] <= {PS2_RDY_r[6:0],PS2_RDY};
if (PS2_RDY_r[7:0] == 8'b00001111 ) begin // valid data on PS2_DAT
PS2_CHAR <= PS2_DAT; // Latch the character into Ps2_char register
end
if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin // Z80 is reading PS/2 port
Z80_rData <= PS2_CHAR;
if (PS2_RDY_r[7:0] != 8'b00001111 ) PS2_CHAR <= 8'b0;
end