Closed ogamespec closed 5 months ago
It seems that the result of the ALU calculation is not saved on the ebus/fbus between cycles:
The picture above is not actually inverters, but a transparent DLatch for ebus/fbus buses
Unfortunately, didn't investigate this today as much as I expected, but the problem appears to be in the DataMux
, it is not putting Res
into DL
.
Below, x[37]
is s3_oe_alu_to_pbus
, which control Res_to_DL
in the DataMux
. I believe that should put the result of Res
in DL
, which then goes to Z_in
, to reg Z
, and then to zbus
to PCL
. Similar thing should happen with W
to PCH
, but didn't check.
But I didn't investigate this thoroughly, could be wrong.
Yep, it's a tough nut to crack. I can't figure out the best way to approach it yet. Everything seems to be correct, but the signals aren't coming out.
Look a little more into it today. Appears to be a issue in how WR_hack
is currently implemented.
From investigation.md
:
Jump relative is not jumping to the correct address. The jump relative should use the ALU to compute the target address, and them set the value of PC to its result. What appears to be happening is a bug in the DataMux
, where it is not putting the value of Res
into DL
(internal databus).
The DataMux
has currently the following logic (assuming CLK
is high, and Test1
is low):
assign Ext_bus = (WR_hack && ~Test1 && clk) ? int_to_ext_q : 1'bz;
assign Int_bus = (~WR_hack && ~Test1 && clk) ? ext_to_int_q :
( Res_to_DL ? res_q : ( DataOut ? dv_q : 1'bz ) );
WR |
Res_to_DL |
DataOut |
Operation |
---|---|---|---|
1 | 1 | x | D <- DL; DL <- Res |
1 | 0 | 0 | D <- DL |
1 | 0 | 1 | D <- DL; DL <- DV |
0 | x | x | DL <- D |
I think the first line is invalid, DL
is being written and read at the same time, while I expect that another entity must be already driving DL
. In no other case the content of Res
is put into DL
.
During the execution of the instruction JR d16
, WR
is low and Res_to_DL
is high.
Investigate the DataMux
logic more in depth, and I think I got it to work. One way is to replicate the exact logic of the circuit, and then make all internal connections have a smaller driving strength than the external bus to solve any conflict, and an even smaller signal pulling the buses up, to simulate the pre-charging:
assign Ext_bus = (clk || Test1) ? 1'bz : 1;
assign(pull0, pull1) Ext_bus = clk && ~(int_to_ext_q || Test1) ? 0 : 1'bz;
assign Int_bus = clk ? 1'bz : 1;
assign(pull0, pull1) Int_bus = clk && ~(Test1 || ext_to_int_q) ? 0 : 1'bz;
assign(pull0, pull1) Int_bus = (Res_to_DL && ~Res) ? 0 : 1'bz;
// DataBridge logic
assign(pull0, pull1) Int_bus = (~dv_q) ? (DataOut ? 0 : 1'bz) : 1'bz;
// Drive DL and D buses up with weak strength to simulate the precharge.
assign (weak0, weak1) Ext_bus = 1;
assign (weak0, weak1) Int_bus = 1;
One problem with that approach is that it does not work in Verilator (although I'm not sure if it is currently working in the first place), apart from making the logic hard to read.
Another approach is to introduce the same hack you did before with the WR_hack
, but also with a RD_hack
signal too:
assign Ext_bus = ~clk ? 1
: RD_hack && ~WR_hack ? 1'bz
: ~RD_hack && WR_hack ? int_to_ext_q
: 1;
assign Int_bus = ~clk ? 1
: RD_hack && ~WR_hack ? ext_to_int_q
: ~RD_hack && WR_hack && DataOut ? dv_q
: ~RD_hack && WR_hack ? 1'bz
: Res_to_DL ? res_q
: 1;
This one also works, but it introduces some undefined values into Z_in
when Int_bus
temporarily goes z
, but does not affect the simulation (but didn't try it in longer simulations). But this could be fixed by simulating the precharge, as in the previous approach (which would also break the Verilator simulation).
@ogamespec What do you think is the better approach? I can make a PR with either of them.
With the fix above I was able to simulate the entirety of quickboot.bin
🎉! I believe the next step is to run blargg's cpu_instrs test rom.
Bellow are my notes in investigation.md
:
Hi! I can't tell you how cool it is :) I think the RD hack is the better option. Even though it's a hack, it's at least more or less close to the synthesized version. The DataMux circuit itself is very tricky, so it's unlikely to be without some workarounds.
Fixed by @Rodrigodd
Conditional jump (JR) is not working.
Test rom:
Waves: