Lab #4: Bus Design
Fall 1998
In this lab you will try to implement a bus to communicate data between the Gizmo board PIT ports and the FPGA. The PIT side will be the master, meaning that all bus transactions will be initiated from the PIT. The protocol will be implemented in software on the gizmo board, and in hardware in the FPGA using VHDL. This will give you an opportunity to contrast how finite state machines can be implemented using software and hardware described with VHDL.
This circuit will be used in future designs as an interface to other circuits that you will build. You will want to make it work!
The bus protocol will be asynchronous, meaning that there will be handshaking signals instead of a clock. All transactions are initiated from the PIT side. You should read Section 4.5 in the text, particularly the part about asynchronous buses. In your system the skew will be very small, and is likely not even a problem. However, you can easily account for skew on the bus by ordering the the way you change the data and control registers on the PIT side.
To start a read, the PIT carries out the following actions:
The FPGA will handshake with the PIT using the ACK line. When ACK goes high, it means that the FPGA has latched the address into its address register. You can also implement a timeout feature to detect illegal addresses. If ACK does not get set high after a certain amount of time, then you can assume that there is nothing at that address, and abort the transaction.
The next transaction on the bus is to read the high byte of the data.
A similar transaction is carried out for the lower data byte, except that LBE is used. With these signals, it is also possible to do single byte transfers. Note that if neither byte enable signal is on when RDY is high, then an address is being transferred. You can use this to indicate that a new bus transaction is being started.
The FPGA circuit should be implemented with VHDL. It is easiest to implement the logic as a finite state machine, because a controller is really an FSM. Do not try to use the asynchronous logic style used in the text. It is better to use a synchronous FSM design. These days with the possibility of really high-speed clocks, you can generally get fast enough response time this way. In the case where you really have to respond quickly to some input, then you would think about doing that part asynchronously. There are examples in the VHDL Reference Guide on how to do FSMs.
You should also have a separate input for a Reset signal to make sure that your circuit starts in a reasonable state. The worst case is that the FPGA starts up driving the AD lines and you do not realize that from the PIT side. You could end up having the two devices driving the wires at the same time.
As a means of providing some standardization and inter-operability between designs, you should use the following connections:
Signal | PIT 0 | FGPA |
AD0 | Port A 0 | XCBUS18 |
AD1 | Port A 1 | XCBUS68 |
AD2 | Port A 2 | XCBUS6 |
AD3 | Port A 3 | XCBUS7 |
AD4 | Port A 4 | XCBUS8 |
AD5 | Port A 5 | XCBUS9 |
AD6 | Port A 6 | XCBUS27 |
AD7 | Port A 7 | XCBUS28 |
RDY | Port B 0 | XCBUS24 |
R/W | Port B 1 | XCBUS25 |
HBE | Port B 2 | XCBUS26 |
LBE | Port B 3 | XCBUS23 |
ACK | Port B 4 | XCBUS19 |
Reset | Port B 5 | XCBUS20 |
You can disable the 8031 by setting XCBUS36 high (RST). This can be done in your VHDL by assigning a `1' to that pin.
You should have three 16-bit registers that are byte-addressable using an addressing model like the 68000. This means that all words are at even addresses, and an odd address refers to the lower byte of a word.
Note that for a port that is bidirectional, you should declare it as inout in your entity declaration. Whenever you are finished outputting data on the AD lines, you should make sure that you drive a high impedance (AD "ZZZZZZZZ") on those lines to stop the output operation, and stop driving the lines so that they can be used by another device.
There are various levels of simulation when doing designs in VHDL. The first level is strictly behavioural simulation. In this case you are simply simulating the VHDL source code and debugging it much like you would debug a C program. Then, depending on the technology that you are synthesising to, there can be various levels of netlists that you can get after synthesis. For example, after synthesis to a gate-level netlist, you may use behavioural simulation of the gates to see whether it still has the desired function. This netlist could be further annotated with timing information for more accurate timing simulation.
Attached is a short tutorial on the use of the Synopsys VSS simulator, which can be used for your functional simulations. You can look the online manuals to learn the fancier stuff. The tool is available on the ugsparcs.
I recommend a few modifications to the tutorial sheets:
setenv SYNOPSYS /CMC/tools/synopsys if ( -e $SYNOPSYS/source_vrg.csh ) then source $SYNOPSYS/source_vrg.csh endif
If you end up with much more than 3-4 pages of VHDL then you are making this more complicated than necessary.
For the Gizmo, you should write C routines to handle the control of the PIT. Write two procedures, one for read and one for write. By modifying the I/O parts of your program, you should be able to debug the logic of the program on the ugsparcs.
The two procedures are described below:
int FPGAread(unsigned char Address, char *HighByte, char *Lowbyte, int Byte) Address: 8-bit address HighByte: pointer for returning the high byte of data LowByte: pointer for returning the low byte of data Byte: set to 1 for a byte read, 0 for a word read Return value: 0 for success, 1 for error int FPGAwrite(unsigned char Address, char HighByte, char Lowbyte, int Byte) Address: 8-bit address HighByte: high byte of data to be written LowByte: low byte of data to be written Byte: set to 1 for a byte write, 0 for a word write Return value: 0 for success, 1 for error
Using those procedures, write a simple monitor that allows you to examine and deposit data into the registers in the FPGA.
To minimize the possibility of problems, you should try to test the two parts individually. On the Gizmo side, you can have your program stop for input at each stage. This will allow you to probe lines and set values on input lines and test your program that way. You can do the same thing with the FPGA. When you are convinced both sides are working, then you can connect them together.
You will need to wire up a Xilinx board according to the specifications given. Do it neatly as we will keep these boards and use them again.
Demonstrate a working system.