emu-russia / dmgcpu Goto Github PK
View Code? Open in Web Editor NEWDMG CPU Reverse Engineering
Home Page: https://emu-russia.github.io/dmgcpu/
License: Creative Commons Zero v1.0 Universal
DMG CPU Reverse Engineering
Home Page: https://emu-russia.github.io/dmgcpu/
License: Creative Commons Zero v1.0 Universal
The HDL is now running an NOP stream, but the Addr bus value is not increasing, and hence neither is the PC.
We need to localize the problem and fix it.
We need to verify that CLK trees are correctly represented and their polarity is treated correctly in all project materials.
The SM83 has a number of DFFs that use negedge for the LoadEnable
signal. We need to check how it reacts at all and whether it needs to be taken into account at all.
We need to compare the approach and implementation of our HDL and @Gekkio's HDL when it is released in the future.
Hey, I noticed you tried to identify the CPU parts. Just wanted to give you my thoughts on that. Of course I could be wrong, but I strongly believe that the part in the upper left, that you suspect to be the sequencer, is actually the 4-bit ALU. It looks like it is made out of four similar vertical slices, one for each bit. The slices can't be perfectly identical because of the 0x66 and 0x99 comparators that may be in there for the DAA instruction. It also looks similar like the ALU in the Z80, but since it misses some functionality, like parity flag and stuff, it just looks similar, not identical. I suspect that they route simple register-to-memory LD instructions through the ALU as well, because the result at the top of the ALU is very close to the external data bus tri-state buffers. This would mean that the internal data bus(es) are organized a bit different compared to the Z80.
The sequencer logic could be in the top right, that you labeled "WTF?".
The bottom part are the register banks and most likely also a 16-bit incrementer/decrementer for PC and SP addresses, which can output it's result to the address lines to the right of the register bank. Contrary to some believe out there in the internet, I don't think that they have a 16-bit adder that can add anything else than +1 and -1 to an address. The required clock cycles needed by 16-bit ADD instructions are long enough so that those additions can be serialized through the regular 4-bit ALU. I've already implemented the CPU in that way and it works out well.
I'm very excited about your project and that we might finally have some schematics for the CPU soon. And I'd like to figure out if my assumptions described above are correct. I dreamed of this for soooo long. :)
Once the entire HDL is implemented, you need to shake it up, optimize it, document it in places and make sure it is moving at all.
I like the short d/w/x designation, but at the same time the Gekkio signal names are also useful. To find a use-compromise we will take a hybrid approach: outside (Top) all signals walk in packs of d/w/x; inplace instead of d[n], w[n], x[n] the corresponding macros from GekkioNames are used.
Run through the topology and compare the HDL implementation all the places where CLK7 (writeback_ext) is used.
This CLK is tied to the overlapped instruction execution mechanism, so it is absolutely critical to check the circuits and add DLatch to make sure they "extend" the results properly (they are essentially shift delay registers)
in Top.v you assign DL_Control2 = x[37]; but you still accidentally pass x[37] to DataLatch instead of DL_Control2
In the lazy mode to try all sorts of roms in the simulator and check that there is something moving.
After getting the HDL, you need to run each opcode in Icarus to make sense of the d/w/x outputs.
Need to update all .pdf's and pics from Xilinx PlanAhead with the actual HDL.
Although topologically these 2 pieces are in different places on the chip - it is more convenient to merge them into one to make it more convenient to multiplex the data bus.
Analyze DataLatch and make sure it works as it should.
Noticed that when integrating this CPU into the complete Game Boy system made by msinger. That work is displayed at msinger/dmg-sim#1.
From msinger research, CLK_ENA
should only go high after OSC_STABLE
, otherwise the OSC_STABLE
never goes up (this is better explained in the link above).
Extracting the logic of CLK_ENA
from Seq.v
, we can see it never interacts with OSC_STABLE
, and goes up immediately after RESET
:
RESET | SYNC_RESET | CLK_ENA |
---|---|---|
0 | 0 | ~(d[100] | IR[4] & d[101]) | SeqControl_1 |
0 | 1 | ~(d[100] | IR[4] & d[101]) |
1 | x | 0 |
When using other tools to synthesize the HDL, they error out because assign
happens to a wire which is not defined yet (that is, the wire
is declared after there is an assign
using it).
Rearranging the lines, so that the ordering becomes input
/output
/inout
, then wire
, then assign
, and then module instantiations, then the file successfully snythesizes.
in Decoder3.v I get an error for the autogenerated portion: x[19] is assigned twice with two different rules
../Top.v:242: warning: output port A is coerced to inout.
run.v:90: warning: output port A is coerced to inout.
There are reports that the cc check circuit (RET cc, JP cc, etc.) is not working correctly.
It is necessary to make a test rom for testing and visual inspection of signals.
At the same time to process the results and supplement the description on the wiki (it is assumed that the cc_check circuit is located in ALU random logic, associated with the signal ALU_Out1, which goes to the sequencer).
From #238. To fix it there, I removed the not operator from the assignment to Z_in
and W_in
, but I don't know how to confirm if this should be the actual fix, there are many other possible positions where the signal could be inverted or not (the registers could for example store the value of the registers inverted and then straight them when loading).
Below is my investigation of the flow of data from the databus to the registers, extracted from investigating.md
in the linked PR, with added screenshots.
H
and L
are stored in ReqH
/r3q
and ReqL
/r2q
, respectively, inverted.
H
can go to abus
, bbus
or dbus
, and L
can go to abus
, bbus
or
cbus
. They go to the bus through an inverter, so they have they original
value.
In this instruction, H
goes to dbus
and L
goes to cbus
. dbus
cbus
go
through an BusKeeper
, and them inverted again into the AdressBus
(or A
).
From the comments in IDU.v
, the code expects that the internal register
actually holds the straight value of the ISA registers, but they are inverted in
the current form. This was also seen in the JP
instruction, and I fix that
there by inverting the Zbus, but maybe we need to invert something more
fundamental, like the value read from the memory?
r3q
-> dbus
-> BusKeeper
-> AddressBus
(inverted)r2q
-> cbus
-> BusKeeper
-> AddressBus
(inverted)D
-> DataLatch
-> DL
-> Z_in
(inverted) -> zbus
-> bbus
bbq
-> DV
(inverted) -> Res
-> fbus
-> RegA
So RegA
/r1q
contains the inverted value of A
.
In screenshot, the execution of the instruction LD A, $BC
(3e bc
).
D
-> DataLatch
-> DL
-> W_in
(inverted) -> wbus
-> fbus
-> RegH
D
-> DataLatch
-> DL
-> Z_in
(inverted) -> zbus
-> ebus
-> RegL
So HL
are also stored inverted in the registers.
In screenshot, the execution of the instruction LD HL, $DE80
(21 80 de
).
D
-> DataLatch
-> DL
-> W_in
(inverted) -> wbus
-> sph_nd
(inverted) -> SPH
(inverted)D
-> DataLatch
-> DL
-> Z_in
(inverted) -> zbus
-> spl_nd
(inverted) -> SPL
(inverted)So SP
is also stored inverted in the registers.
In screenshot, the execution of the instruction LD SP, $AACC
(31 cc aa
).
D
-> DataLatch
-> DL
-> W_in
(inverted) -> wbus
-> pch_nd
(inverted) -> PCH
(inverted)D
-> DataLatch
-> DL
-> Z_in
(inverted) -> zbus
-> pcl_nd
(inverted) -> PCL
(inverted)So PC
is also stored inverted in the registers.
In screenshot, the execution of the instruction JP $0112
(c3 12 01
).
In #238 I noticed that during instructions that should write to memory, it doesn't output a value to the external bus, it was kept in high impedance. Below is the summary of my investigation, as contained in investigating.md
in the linked PR.
DataLatch
is the only one connected to the external data bus D
. Although it
is called a "latch" it does not hold any data, it just forwards data from other
data buses; that is Res
(the result of the ALU) and DL
(the internal
databus).
But datalatch.md
states that it can only output values to DL
, and load from
either D
or Res
. But this should not be the case, because we need to output
to the external bus, and DataLatch
is the only one connected to it.
Also, it specifies DL
bus as inout
, but never assign z
to it. In fact,
during the write (WR
high) DataBridge
also writes to DL
, making DL
go
to invalid state x
. Actually, a lot of things tries to write to DL
.
(Strangely, DataBridge
only writes 0
or z
bits to DL
. Maybe DL
has a
pull-up somewhere? Oh, maybe that is what BusPrecharge
does, not sure if
verilog will simulate that. Oh, this is handle by the use of BusKeeper
.)
The value of register A
is stored in ReqA
/r1q
, inverted. This value can be
put in the abus
or bbus
(and Aout
, but just affect ALU logic), but during
write neither of them are used, s2_op_alu8
(w[3]
) and
s3_oe_areg_to_rbus
(x[35]
) are both 0.
In screenshot, the execution of the instruction LD (HL), A
(77
).
Yeah, simple. Add a + b, make sure it works :)
Write a test run for Icarus to check it.
Let's NOT concentrate on the flag setting logic for now, it's complicated. Check CLA.
Additionally mark with
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.