Close

Bus Access Timing Conflict - Does it Matter?

A project log for SPAM-1 - 8 Bit CPU

8 Bit CPU in 7400 with full Verilog simulator and toolchain

john-lonerganJohn Lonergan 04/12/2020 at 18:300 Comments

I've written before about timing constraints in the git hub project. https://github.com/portingle/spam-1/blob/master/docs/timing-considerations.md

I've recently been putting v2 of this processor's logic into Verilog to road test the design before committing to breadboard. Honestly, sometimes I think it would be less hassle to go straight to h/w flying by the seat of the pants, but then I'd have missed out on a bit of new learning with Verilog. 

I have four devices that take turns writing to the bus; the ROM, the RAM, the ALU, the UART.

If more than one device is inadvertently asserting on the bus simultaneously then there are risks of high current spikes and potentially damage to chips.

The ROM and ALU both connect to the bus via a 75HCT245 and the RAM and UART connect directly. In each case there is a control line to signal the logic low output enable of each device.

The logic behind the four control line is ...

assign  _decodedOp = 8 outputs of a 74138 decoder chip - decoding the op code
assign  _rom_out = _decodedOp[op_DEV_eq_ROM_sel];
assign  #11 _ram_out = _decodedOp[op_DEV_eq_RAM_sel] && _decodedOp[op_DEV_eq_RAMZP_sel];
assign  #11 _uart_out = _decodedOp[op_DEV_eq_UART_sel] && _decodedOp[op_RAMZP_eq_UART_sel];
assign  #11 _alu_out = _decodedOp[op_NONREG_eq_OPREGY_sel] && _decodedOp[op_REGX_eq_ALU_sel] && _decodedOp[op_RAMZP_eq_REG_sel];

You can see that the _rom_out line is a direct connection to one of the 8 output wires of the 74138, whereas the other three control lines include an AND gate.  

The timings shown, ie 11ns, are realistic for the 74HCT AND gates.

So .... today I put a constraint into my verilog model to check that we only have one of the bus control lines active at any instant and the check started failing.

The check looks like this.... 

wire [3:0] rrau = {_rom_out, _ram_out, _alu_out, _uart_out};
always @* begin   
    assert (rrau == 4'b1111 || rrau == 4'b1110 || rrau == 4'b1101 || rrau == 4'b1011 || rrau == 4'b0111)
    else begin        
        $error("Contention on data control lines Rom,Ram,Alu,Uart=%4b   !!!!!!!!!!!!!!!!!!!!!!!!\n", rrau);        
        $finish_and_return(1);    
    end
end

Going back to the control line logic we find that that 11ms delay is the likely culprit.

Since _rom_out transitions earlier than the other three control lines then each time the rom takes over the bus then momentarily two lines are simultaneously low. The ROM starts writing before the previous device has had time to relinquish control of the bus.

But, does it matter??

I think it's unlikely that damage will occur because the vanishly short 11ns window doesn't allow for much heating to occur in the gates involved in the push-pull.

It is probable that there will be some short current spikes on the power rail however a capacitor ought to fix that if it's an issue.

But, what other approaches could have been used to avoid or reduce the contention?

Well it's common to see home brew CPU's using a ROM for control logic. However, I don't think a ROM would have been 100% certain to avoid this kind of thing, due to uncertainty of the ROM output values during switching, but again if it's a very short contention then the same observations as above apply. 

Alternatively, I could put a redundant AND gate on the _rom_out line to even up  the timings.

Diode logic would also work in the case I have above, and that would have resulted in equivalent timings for all routes, if I also includes a diode on _rom_out.

All the above approaches go some way to mitigate the problem by reducing the time window of potential contention to smaller and smaller intervals.

Is there a better approach?

I could have organised the control logic so that there is an interval between the control wires returning to logic high before one of them alone returned to logic low. But, that's a lot of extra logic. Of perhaps some snazzy logic to make the negative transitions take longer than the positive transitions.

Clearly, glitching is a common issue, various 74xx series data sheets state "glitch free" logic in their description. 

I think a better approach would have been if I had been able to use open-collector outputs for the ROM/RAM/ALU/UART. Open collector outputs were designed to gloss over transient issues like this, however, firstly ,the RAM and UART don't use open collector outputs and secondly I can't find a reasonably priced open collector alternative to the 74HCT245. 

Conclusion 

I've decided to live with it. :(

Am I wrong?

How could I do better?

(see also the following which applies not just to FPGA designs https://zipcpu.com/blog/2017/08/21/rules-for-newbies.html)

Discussions