Design custom NanoBoard peripheral boards – Pt2
Last month, we discussed how to get started on custom peripheral board designs by building a template from the PB30 reference design. This month, with an example prototype peripheral board in hand, we look at the process of registration using the 1-Wire bus EPROM which holds the board’s identity and allows Altium Designer® to automatically configure FPGA projects that use the new board.
Design custom NanoBoard® peripheral boards – Pt2
Part 2: Preparing Registration and Constraints
Last month, we discussed how to get started on custom peripheral board designs by building a template from the PB30 reference design. This month, with an example prototype peripheral board in hand, we look at the process of registration using the 1-Wire bus EPROM which holds the board’s identity and allows Altium to automatically configure FPGA projects that use the new board.
The device currently used on peripheral boards for registration is the Dallas/Maxim DS2502. Each DS2502 chip has a unique 64-bit factory programmed serial number, along with 1024 bits of user-programmable write-once memory. This “add-only” memory area is divided into 4 pages, and there is a page redirection area in the “status bytes” which is write-once programmable also. A block diagram of the EPROM is shown in figure 1 below.
Figure 1 - DS2502 block diagram (Source: http://www.maxim-ic.com/images/qv/2924.gif
The format of the data used by Altium for board registration is straight-forward. The first 16 bytes in the used page are the ASCII text name of the peripheral board. This name is used by Altium to find a matching constraint file for the board, along with a bitmap image for use in the View Configuration dialog in Devices View - more on those later. Following the 16-byte name field is a 4-byte batch ID field. Typically this is used to indicate the manufacturing batch when boards are in full production. It is therefore useful for determining precisely when and where the board was made. The next field (and last required field) is a 4-byte vendor code. Vendor codes are allocated by Altium, with the code ‘1’ reserved for Altium products. Your peripheral board should therefore be programmed with your own vendor code. To obtain a vendor code, contact your nearest sales and support office.
Contents of 1-Wire devices can be read using the example projects from the Altium installation. If you are using a NB2, use the example project found in .\Examples\Soft Designs\Communications\OneWire. For those with the NB3000, an updated version of this example can be downloaded from here (at the time of writing, this example is not yet part of the Altium installation, but will be added to Release 10). A screen shot from the NB3000 TFT panel is shown below, with the serial number, status byte and EPROM contents in HEX and ASCII. Notice that the board plugged in is my prototype for the PBGTR.01 guitar input board. The 1-Wire device on this board has been programmed, and I designed the PCB with a header that allows me to connect the DS2502 to the user 1-Wire bus or the host (NanoTalk Controller). To view the contents of the device, the jumper is set to the “User” position. For auto-configuration of FPGA constraints, it must be set back to the “NanoTalk” position.
Programming the 1-Wire EPROM
To program the 1-Wire bus EPROM, you need to use the OneWireViewer program, available for free download from the Maxim web site. This Java based software accesses the 1-Wire bus via a USB or serial port based 1-Wire bus programmer. These programmers are available from Dallas/Maxim for less than $30, and come with the various 1-Wire or iButton evaluation and development kits available. At the time of writing this article I used the USB based programmer with OneWireViewer running on Windows XP, with version 4.00 of the USB drivers installed. Below is an annotated screen shot of the OneWireViewer program - on the left pane you can see the EPROM (second device) and programmer (first device) on the 1-Wire bus. The memory pane allows viewing and programming of each byte within the memory, as well as the status bytes. My board is named ‘PBGTR.01’, and being an initial prototype it’s batch ID is ‘1’. Also, since it is an Altium design, the vendor code should also be ‘1’. The batch ID and vendor codes are straight-up hexadecimal integers, whereas the name field is ASCII. There is no null termination because it’s a fixed-width field. Also worth mentioning is that it is left justified, with space characters (0x20) trailing.
After programming the 1-Wire EPROM with the correct information, the board can be detected and identified on the NB2 or NB3000 to allow Altium to auto-configure FPGA projects for use with this board.
For more information relating to 1-Wire devices and associated software and programmers, visit the Maxim 1-Wire web site: http://www.maxim-ic.com/products/1-wire/.
Creating the constraint file and bitmap
For auto-configuration to work there must be a constraint file in the .\Library\FPGA folder of your Altium installation for the board. When the powers up, it scans the 1-Wire bus and registers any devices found on the peripheral board connector(s). Then Altium searches the .\Library\FPGA folder for a constraint file of the same name, as well as a bitmap (for creating the image of the configuration) - in this case those files are named PBGTR.01.Constraint and PBGTR.01.bmp, respectively.
The purpose of the constraint file is to map named IO signals on the peripheral board to the peripheral board header pins. The mapping of those header pins back to the FPGA pins is taken care of automatically when you configure your FPGA project by way of a Board Mapping constraint file - generated when you execute the autoconfiguration process from Devices View.
In my PBGTR.01 example, I have a couple of 4-digit multiplexed 7-segment LED displays, as well as two CTS rotary encoders with SPST pushbuttons. The analogue audio inputs on my board are routed to the dedicated analogue audio inputs to the NB3000’s codec, and also the mixer inputs to the power amplifier. The only signals needing to be added to the constraint file are those for the 7-segment displays and rotary encoders. The entire constraint file contents are shown below:
The format of the constraint file is simple, but important. After the file header, we define the name of the board, and the associated image name - along with the offset for displaying the image in the configuration view. To keep things simple these names should match the ASCII name of the board in the 1-Wire EPROM.
Next, we define the peripheral board connector, named HDR1 in this instance. From there on the IO signals are defined by name and assigned to their associated header pins with the “ConnectTo=HDR1-xx” constraint field, where xx is the pin number on the header connecting to the named signal. In this example the rotary encoder pins are low and therefore I have added the “FPGA_PULLUP=True” constraints to add the necessary weak pull-up from the FPGA pins.
Creating the bitmap image of the board is a simple matter of taking a photo of the board with a digital camera. The result looks best when the camera is at least three or four feet from the board viewed front-on, and zoomed in for the best clarity. This way lense warping is minimized. The image needs to be re-sized and cropped to have a width of 328 pixels. And, since the bitmap file format does not support transparency, Altium treats solid magenta as a chroma-key for transparent areas within the image. The correctly sized, cropped image is shown here:
Once the bitmap and constraint file have been added to the .\Library\FPGA folder of your Altium installation, plug in the new peripheral board on the NB3000 (or NB2), power it up, and in Devices View right-click the icon and choose View Configuration. If the 1-Wire registration, constraint file, and bitmap have been correctly generated, you should see your board within the configuration view (including the serial number, batch ID and vendor code):
Congratulations! The tricky part is done. Now you can use your custom peripheral board, and have it auto-configured for an existing or new FPGA project. This step adds the new constraint file to a project, so all you need to do is place IO ports on your top level schematic to access your peripherals by name.
But why stop there? Let's get fancy and make a matching port plug-in - which provides IO that look good on your schematics and reduce effort in re-using your peripheral board for new designs?
Creating the port plug-in to go with your board
Port plug-ins are essentially the same as standard components, with the addition of a parameter that identifies them as a substitute for top level schematic ports.
Create a new schematic, and within that, a component for each peripheral. Make the component designator blank and lock it - since you can only use one instance of each port component in any given design, designators are not needed and should be blank, hidden, and locked. Add a parameter to each part named “PortComponent” with the value “True”. This parameter should also be hidden as it would otherwise clutter the schematics.
Then add the necessary pins for the IO connections. This is the important part, where most errors are likely to occur. Since each pin must map to a constraint by name, the pin name and designator must match the name of the associated IO signal in the constraint file. The pin designator should also be hidden since it would also clutter the schematic.
Also, note that the pin direction must be set from the perspective of the peripheral outside the FPGA, not the schematic. In the image shown above (my LED display port plug-in which is partially completed) the pins are inputs to the display, so the pin direction is set to INPUT. Likewise, port components that generate signals which are brought into the FPGA are OUTPUTs. If in doubt, use the direction arrow of the pin as a guide: if it’s pointing the wrong way, then it means the direction is set incorrectly. And of course, FPGA pins can also be bi-directional. In setting the pin properties, the only valid pin types are Input, I/O, and Output.
The nice grey port shape in the image above is a simple polygon shape from the place menu in the schematic editor. These are purely optional - as are the embedded bitmap images (like the display illustration in my component).
Below is a schematic design at the top level of an FPGA project I used for testing my custom peripheral board. You can see I have used port plug-ins for the display and rotary encoders.