Bussed signals - How to do DTACK & DATAgreenspun.com : LUSENET : ece342 : One Thread
Labs using the 68K bus will require you to attach certain outputs, such as /DTACK and DATA to the bus. Since these are bussed outputs, they can be driven by other devices, so you have to make sure that you have some way of 'turning them off', i.e. making sure that they do not drive the bus at inappropriate times. There are two general ways of doing this: tri-state buffers and open-collector drivers.
Open-collector logic is a special kind of circuit that allows multiple outputs to drive conflicting logic levels at the same time. It avoids having a short-circuit condition by using only one half of a totem-pole transistor configuration. There is a pull-up resistor that keeps the line high by default. If one or more drives switch low, then the line goes low. The pull-up avoids a short-circuit.
To use open-collector in the lab, what you would do is have your Altera device generate a standard OUTPUT signal, and then put the signal through a discrete chip that has regular TTL inputs and open-collector outputs. This output could then be connected to the bus (J6) without any further consideration. This increases the wiring complexity, though, since it needs extra chips.
A better solution is to use tri-state buffers. Such a driver has a control signal called an 'output enable', which when high drives the input onto the output, and when low turns off the buffer so it acts as a high impedance. In VHDL, you need to use a TRI primitive, which is available in the Altera library. So, for example with DTACK, you might do it as follows:
LIBRARY altera; USE altera.maxplus2.all;
This makes the necessary library available. Within the ARCHITECTURE block you can now instantiate a TRI buffer. If you look at the Help page, you will see that this kind of buffer has 2 inputs 'a_in'/'oe' and 1 output 'a_out'. You could hook it up as follows (assuming that DTACK_n is declared as an OUTPUT in the PORT declaration):
t_buf: TRI PORT MAP( a_in => DTACK_sm_n, a_out => DTACK_n, oe => oe_sm);
DTACK_sm_n and oe_sm are signals generated in your state machine. The first is just DTACK asserted in the correct states. The second is active high and will turn on the output once you have decoded that a bus access is for your device. ** Make sure that you only drive the output enable when your device is active. **
This is fine for single-bit signals. For a bus like DATA, if you do it inside the Altera chip you will need to declare it as INOUT, and you will want an array of 16 tri-state buffers. You cannot use TRI for this, since it is does not accept parameters. The best way is to use an LPM module (described in class today), called 'lpm_bustri'. To do this you first need the LPM libraries:
LIBRARY lpm; USE lpm.lpm_components.all;
Then you could instantiate it like this (assume DATA is (15 DOWNTO 0) and declared as INOUT, and your internal regsiter is declared as 'my_reg'):
data_buf : lpm_bustri GENERIC MAP(LPM_WIDTH => 16) -- Set width to 16 PORT MAP(data => my_reg, -- And hook up the wires tridata => DATA, enabledt =>do_read);
Here 'do_read' is some internal signal from your state machine that indicates that a read is in progress.
This should be enough to get you going, and of course you can use the Help pages to fill in any blanks. (Or post questions in this forum.)
And for those of you who are asking, "Why are they just telling us this stuff now?", the answer is that nobody asked. We assumed that people would do the prep over the weekend and then ask if they had any questions. Since this didn't happen, I assume everyone already figured this out.
-- Robin Grindley (email@example.com), January 25, 1999