ijor / fx68k

FX68K 68000 cycle accurate SystemVerilog core
GNU General Public License v3.0
135 stars 31 forks source link

How to request the bus? #4

Closed jotego closed 3 years ago

jotego commented 4 years ago

I am trying to implement DMA in a system with fx68k (CAPCOM SYSTEM 1). I have read the MC68000 manual about the signals, and I have tried to replicate them as follows:

imagen

The CPU starts by signalling data available to the DMA controller (signal obj_dma_ok at the bottom). Then the DMA controller requests the bus: busreq. This gets translated into signal BRn going down, soon after BGn goes down too and BGACKn goes down and stays down during the whole DMA transaction.

I am not sure whether the fx68k core is expecting this signals to occur at specific times or right at the clock edges, or whether anytime is ok. Once I implement this scheme, some games continue working normally (like 1941) but others like Mercs or Street Fighter 2 just fail. Nemo shows a "1111 EXCEPTION" message on screen. Ghouls'n Ghosts fails the OBJ memory check.

I would like to understand better what are the assumptions made on the fx68k core about bus arbitrion and what signals are expected for the handshaking. Could you comment, please?

Thank you

a1exh commented 4 years ago

Without a clock I can't tell but are you asserting BGACKn and deasserting BRn in the same cycle?

jotego commented 4 years ago

Yes, the logic is like this:

always @(posedge clk, posedge rst)
    if( rst ) begin
        cpu_BRn    <= 1'b1;
        cpu_BGACKn <= 1'b1;
    end else begin
        casez( {cpu_BGACKn, cpu_BGn} )
            2'b11: // waiting for bus request
                if( |dev_br ) begin
                    cpu_BRn <= 1'b0;                    
                end
            2'b10: begin // bus granted
                cpu_BGACKn <= 1'b0;
                cpu_BRn    <= 1'b1;
            end
            2'b0?: // bus held by the device
                if( !(|dev_br) ) begin
                    cpu_BGACKn <= 1'b1; // frees the bus
                end
        endcase
    end

dev_br stands for device bus request. It is a bus signal made of all devices than request the bus. Note that this block does not use clock enable signals, but maybe it should use the same clock enablers as fx68k.

a1exh commented 4 years ago

In the 68000 manual, Figure 5-15. 3-Wire Bus Arbitration Timing Diagram, asserting BGACKn and deasserting BRn doesn't happen in the same cycle. And section 5.2.3 Acknowledgement of Mastership says "The bus request from the granted device should be negated after BGACK is asserted."

a1exh commented 4 years ago

This is probably not the issue as Figure 5-20 has BGACKn asserting and BRn deasserting in the same cycle. @ijor will know for sure.

jotego commented 4 years ago

I am waiting now for ASn to go high and that helps.

        casez( {cpu_BGACKn, cpu_BGn} )
            2'b11: // waiting for bus request
                if( |dev_br ) begin
                    cpu_BRn <= 1'b0;                    
                end
            2'b10: begin // bus granted
                if( cpu_ASn /*&& cpu_DTACKn*/ ) cpu_BGACKn <= 1'b0;
            end
            2'b0?: begin // bus held by the device
                cpu_BRn  <= 1'b1;
                if( !(|dev_br) ) begin
                    cpu_BGACKn <= 1'b1; // frees the bus
                end
            end
        endcase

Still, an old core stopped working after the change (Tiger Road)

ijor commented 4 years ago

Hi Jose,

FX68K behaves as a real 68000 with the exception noted below.

You don't necessarily have to assert the signals at a specific cycle, the core performs an internal synchronization anyway. But the core, by default, does expect the signals to be asserted at the right phase of the clock. Otherwise, you need to uncomment a couple of lines at the source to preserve cycle accuracy (see the rBR register). If you don't assert the signals at the right phase and you don't uncomment those lines, it still shouldn't be fatal. The worst that should happen is that the core might grant the bus one cycle earlier than a real 68K. But this scenario wasn't extensively tested. I recommend asserting the signals at the "enPhi1" cycle.

Yes, it is imperative to wait until AS is deasserted. Depending on the case it might be necessary to wait for DTACK to be asserted as well. It is also necessary to not deassert BGACK (or BR) until the external master completed the bus cycle.

If there is only one master, BGACK can be asserted and BR deasserted at the same cycle. But if so you probably can use a 2-wire arbitration scheme that is much simpler than the 3-wire one. Just hold BGACK high all the time.

Note that depending on the platform, just following the bus protocol might not be enough. The software or the chipset might expect a specific timing of the bus master. Some systems delay BR or BGACK for a few cycles. I realize in some cases it is not available, but ideally you should follow traces taken on real hardware.