Page | 1 Chip Design with FPGA Design Tools Intern: Antoine Vazquez Supervisor: Janusz Zalewski Florida Gulf Coast University Fort Myers, FL 33928 V1.9, August 28 th .
Page | 1
Chip Design with FPGA Design Tools
Intern: Antoine Vazquez
Supervisor: Janusz Zalewski
Florida Gulf Coast University
Fort Myers, FL 33928
V1.9, August 28th.
Page | 2
1. Introduction
FPGA is abbreviation of Field Programmable Gate Array. It is a semiconductor device
containing Configurable Logic Block, Interconnect Resource, and Input/Output Block that
can be configured by the customer and designer after manufacturing.
The Configurable Logic Block can be programmed to duplicate the functionality of basic
logic gates (such as AND, OR, XOR, NOT) or more complex combinatorial functions such as
decoders or simple math functions. In most FPGAs, these Configurable Logic Blocks also
include memory elements, which may be simple flip-flops or more complete blocks of
memories. FPGA has several advantages, such as a shorter time to market and ability to re-
program in the field to fix bugs, and lower non-recurring engineering costs. Applications of
FPGAs include digital signal processing, aerospace, defense systems, etc...
FPGAs are programmed using hardware description languages to specify how the chip will
work. The most used language to program FPGAs is Very High Speed Integrated
Circuits (VHSIC) Hardware Description Language, abbreviated to VHDL. The boards we
have at our disposal are Altera (Cyclone 2) [1], Xilinx (Spartan-3E) [2] and National
Instrument (CRIO) [3]. To program this board, we use three tools, depending on which
board we want to work with:
• Altera Quartus II
• Xilinx ISE 10.1
• National Instruments Labview 8.5
In the following sections, the use of all three tools is explained for a Serial Data Receiver [4]
see section 1.1.2.
Page | 3
1.1 Quartus II design example
Quartus II is a software tool developed by Altera to manage projects, for which EDA
(Electronic Design Automation) operations are made. The use of the software can be
decomposed into three steps:
• Design entry – two modes of seizure are available, Schematic (GDF or BDF files) or
Textual (TDF and VHD files).
• Simulation – the synthesized circuit is tested to verify its functional correctness;
this simulation does not take into account any propagation delays.
• Synthesis – the verified design is synthesized into a circuit that consists of logic
elements provided in the FPGA chip
1.1.1 Design entry First, you have to create a new project by selecting File -> new project Wizard. After that
press next to continue. In the next window, enter your project name and location. Press
next two times. Now you can specify the type of device in which the designed circuit will be
implemented. Select as shown in figure 1.
Figure 1 - Type of device you want to use
Page | 4
It is important to specify the family and name of your device correctly. You can find the
family of the board written on the FPGA’s board; here it is “Cyclone II”. As well, the Name is
written on the FPGA, “EP2C35F672C6”. The name on the board may be ended with an “N”
which does not matter. If the selected device is not the one for synthesis, your program
will not be synthesized.
Figure 2 - Altera Cyclone II EP2C35F672C6
After selecting the family and name, click on next and then finish. Your project is now
created. The next step is creating a new file to develop your VHDL program by selecting
“File -> New…”. A new window appears. Choose VHDL File.
Page | 5
Figure 3 - Create a new VHDL File
You are now able to edit your VHDL code. One has to enter the library you are going to use
and describe your entity. Entity describes an external “block” view. You should know what
you are going to do before creating it. Inside this block will be the circuit that you want to
create in VHDL. So, define what your circuit does and how it will communicate with the
board and devices.
The entity should be described as followings:
1. Circuit’s name
2. IN/OUT ports :
Name, for example din, fclk, rst.
Direction (IN, OUT, IN/OUT...)
Type (BIT, BIT_VECTOR, INTEGER, STD_LOGIC, etc)
For a serial data receiver, we need a serial input, a clock to synchronize the circuit and a
reset to restart. On the output side, the serial input is converted to a set of parallel signals.
Additionally, more output signals should be used to indicate errors.
Page | 6
In the following figure, we define first the schematic representation and then write it in
VHDL code.
Figure 4 –Schematic representation and VHDL code corresponding
Then, you can describe the architecture. The architecture is the internal description of the
circuit. It is always associated with an entity. The same entity can have many structures.
The mechanism of configuration allows indicating the architecture connected with an
entity.
In the body of the architecture (between begin and end), there are two types of
instructions of VHDL that can be written in any order:
Type 1. Process with the keyword process.
Type 2. Instruction of affectation.
Library ieee; Use ieee.std_logic_1164.all; Entity test IS PORT ( din, fclk, rst : IN BIT; data: OUT BIT_VECTOR (6 DOWNTO 0); err, data_valid : OUT BIT ); END test;
test
din
fclk
rst Data_valid
Err
Data 7bit
Page | 7
Figure 5 – VHDL code of the architecture of the Serial Data Receiver
To be sure the code is complete, double-click on “compile design” on the Task window. Figure 6 shows an example at a successful compilation.
ARCHITECTURE rt1 OF test IS BEGIN PROCESS (rst, fclk) VARIABLE count: INTEGER RANGE 0 TO 10; VARIABLE reg: BIT_VECTOR (10 DOWNTO 0); VARIABLE temp: BIT; BEGIN IF (rst='0') THEN count:=0; reg:= (reg'RANGE => '0'); temp := '0'; err <= '0'; data_valid <= '0'; ELSIF (fclk' EVENT AND fclk = '0') THEN IF(reg(0)='0' AND din='1') THEN reg(0) :='1'; ELSIF (reg(0)='1') THEN count := count + 1; IF (count<10) THEN reg(count) := din; ELSIF (count=10) THEN temp :=(reg(1) XOR reg(2) XOR reg(3) XOR reg(4) XOR reg(5) XOR reg(6) XOR reg(7) XOR reg(8) XOR reg(9)); err <= temp; count := 0; temp:= '0'; reg(0) :=din; IF (temp ='0') THEN data <= reg(7 downto 1); data_valid <= '1'; END IF; END IF; END IF; END IF; END PROCESS; END rt1;
Page | 8
Figure 6 - Compile design
1.1.2 Simulation
Before implementing the designed circuit in the FPGA chip on the physical board, it is
prudent to simulate it to ascertain its correctness. The Cyclone II board has hardwired
connections between the FPGA pins and the other components on the board. So, after
compiling, we need to assign pins for simulation. Then, the simulation can be made. During
the compilation, the Quartus II Compiler was free to choose any pins on the selected FPGA
to serve as inputs and outputs.
This part is very important because you are going to choose how your circuit will
communicate with the extern world. You have to understand what your circuit is going to
do before assigning pins!
If you want to display your result, you can use the LCD screen, the 7-segments billsticker,
or the green and red leds. You can also use USB connection, IDE, JTAG, VGA, Ethernet or
every component that the board has. Input can be connected to those components except
displays. It is possible to connect a temperature captor, a webcam or a microphone. There
are also switches and push buttons, which will be used for the serial data receiver.
Page | 9
So each input and output must be assigned to a component of the board, and thus
connected to one of the FPGA pins. Look at the Appendix to see the mapping between pins
and components.
To assign pins, select Assignments > Assignment Editor to reach the window in Figure 7.
Under Category select Pin. Then double-click on the entry <<new>>. Assign the pin as
shown in Figure 7.
Figure 7 - Pin assignment
After the pins are assigned, you should create a simulation file (Vector Waveform File), by
selecting File -> New then choose Vector Waveform File then press OK. See figure 8.
Page | 10
Figure 8 - New Vector Waveform File
You can now include the input and output nodes of the circuit to be simulated, by clicking
Edit > Insert > Insert Node or Bus open the window in Figure 9.
Figure 9 - The Insert Node or Bus dialogue
In figure 9, click on Node Finder. In the Node Finder window, we are interested in input and output pins, so set the filter to “Pins: all”. Then Select all the node found. Click OK when you have finish.
Page | 11
Figure 10 - Selecting nodes to insert into the Waveform Editor.
To perform the functional simulation, select Assignments -> Settings to open the Settings
window. On the left side of this window click on Simulator Settings, choose Functional as
the simulation mode, and click OK. The Quartus II simulator takes the inputs and generates
the outputs defined in the “.vwf” file. Press Ok to finish.
Page | 12
Figure 11 - Functional Simulator settings
Before running the functional simulation it is necessary to create the required netlist which
map pins to signals. This is done by selecting Processing -> Generate Functional Simulation
Netlist. Additionally, use fclk as the clock. (din is read only when fclk falls.) You can now
make your simulation!
In the following, the input sequence is din = 1011100101 that is interpreted as follows:
Start=1 ---------- Data=0111001(binary) ---------- Parity=0 ---------- Stop=1.
To display it on binary, hexadecimal or decimal, make a right click on the name and then
choose Properties, followed by choosing unsigned decimal. Now simulation is ready! A
simulation run is started by selecting Processing -> Start Simulation, or by using the icon.
Page | 13
At the end of the simulation, Quartus II software indicates its successful completion and
displays a Simulation Report illustrated in Figure 12.
Figure 12 – Simulation results of serial data receivers
After reception, data = 78 (decimal) = 0111001 (binary). Data_valid is high and err is low
which means the data reception has been successful.
1.1.3 Synthesis
Now that the simulation has been done successfully, you can start to synthesize your circuit
on the “Altera Cyclone II” board to actually see the output. To do this, click on the
programmer icon , or select tools -> programmer. Figure 13 appear. If the device is not
detected, make sure that the board is turned on.
Page | 14
Figure 13 - Programmer window
When you are ready, click on the start icon. The FPGA will be flashed with your program.
Afterwards, you can use SW[0] to modify din. When din is on the good position (high or
low), press Key[3] every time you want to input your din position as Key[3] is your clock.
Key[0] is reset
For example, to input “1011100101”, you can switch SW[0] to generate either ‘1’ or ‘0’
sequentially. In order to be synchronized by the clock (Key[3]), press Key[3] every time
SW[3] is switched, high or low. After the data are received leds between ledR0 to ledR6 will
show you the results, LEDG0 (data_valid) is ‘on’ and LED17 (error) is off.
Try another sequence: “1111100101” and you will see that parity is false on that case. You
will see LED17 (err) turn ON. You can also try “1111100111” and see that parity is true.
You can observe your data display by leds, as shown in the box in Figure 14. The sequence
“0111001” is well shows. Moreover, Green led at the right corresponds to data_valid, so you
have well received the data.
Page | 15
“Data[0 to6]” “Din” switch “Fclk” button “Reset” button “Data_valid”
Figure 14 - Results on Altera board
Page | 16
1.2 Xilinx ISE design example Similar to Altera Quartus II, Xillinx ISE can help design circuits in VHDL, simulate the code, and flash the VHDL code to a board.
1.2.1 Design entry
The first thing is to create a new project in Xillinx by selecting File-> New project. You need to give a name of your project , select the project location, and press next. Choose the options like show in figure 15 as an example.
Figure 15 - New project
Then you can choose the board you are going to use. Check on the board (wrote on the FPGA) the family and the device. Here we use a “Spartan-3E XC3S100E”. Now the project is ready to be created. Press for Next for three times and then Finish.
Page | 17
Figure *** - Project properties
To create a VHDL file for your project, click on “create new source”:
Figure *** - New HDL Module file
A window will show up, asking for the type of the source code. Please select VHDL Module File, enter the File’s name and the directory and press Next.
Page | 18
Figure *** - VHDL Module File
Then you should describe your port entity. Define the direction (in or out), the port’s name and if it is a bus or just a bit. Then press next and finish.
Figure *** - Port entity’s definition
The first part of your VHDL code (the entity) will be automatically created based on the information which you entered previously.
Page | 19
Figure *** - VHDL code
The architecture has to be completed by you. You must write your VHDL code between “BEGIN Behavioral” and “END Behavioral” to describe the inside of your circuit.
Page | 20
Figure *** – VHDL code of the architecture of the Serial Data Receiver
On the process windows, double click on “check syntax”
Figure *** – Check syntax
architecture Behavioral of test is begin PROCESS (rst, fclk) VARIABLE count: INTEGER RANGE 0 TO 10; VARIABLE reg: STD_LOGIC_VECTOR (10 DOWNTO 0); VARIABLE temp: STD_LOGIC; BEGIN IF (rst='1') THEN count:=0; reg:= "00000000000"; temp := '1'; err <= '0'; data <= "0000000"; ELSIF (fclk' EVENT AND fclk = '1') THEN IF(reg(0)='0' AND din='1') THEN reg(0) :='1'; ELSIF (reg(0)='1') THEN count := count + 1; IF (count<10) THEN reg(count) := din; ELSIF (count=10) THEN temp :=((reg(1) XOR reg(2) XOR reg(3) XOR reg(4) XOR reg(5) XOR reg(6) XOR reg(7) XOR reg(8)) OR NOT reg(9)); err <= temp; count := 0; reg(0) :=din; IF (temp ='0') THEN data <= reg(7 downto 1); END IF; END IF; END IF; END IF; END PROCESS; end Behavioral;
Page | 21
1.2.2 Simulation
Once the design is created and the VHDL code developed, you can simulate the behavior of the circuit.
• Change the source folder for “Behavior Simulation” • Double click on “Create New Source” • Choose “TestBenchWaveform” • Enter a name for your file
Figure *** – Test bench new file
Page | 22
You have to define clock options. For this example, you can use a single clock, “fclk” in Falling Edge. You can choose the period, the length or an offset. Select options like show in Figure ***.[d1]
Figure *** – Timing option for simulation
Press finish when settings are complete. Then the following window will appear. It is your
simulation window. “fclk“ is defined as a clock, so define your rst and din input sequence
like for the preview example.
Page | 23
The input sequence for din is 1011100101, which mean, for this protocol:
• Start = 1
• Din = 0111001 (binary)
• Parity = 0
• Stop = 1.
Rst has to be low for resetting the board. For using your program, set rst high.
Figure *** – Selection of the entries
When you are ready, double click on “Simulate Behavioral Model” to start the simulation and to obtain your results in a new window with the setting you have set before. You can choose the format of the results, binary, decimal, etc.
Page | 24
Figure *** – Simulation results of serial data receivers
Data = 78
We can see that data, data_valid and err output do not change until every din bits have been
sent. Then, after the complete reception, data = 78 (decimal) = 0111001 (binary). It
indicates that the data reception has been done successfully.
Page | 25
1.2.3 Synthesis
You are going to see a new approach to assign pins that on section 1.1.3. It is possible to
assign manually the pins to the components. For that, you need to create a new file, an ‘ucf’
file. Select implementation on the source window and click on your “test.vhd” file.
On the project directory, create a new file by right clicking -> new -> test document.
Rename the file to “test.ucf”. You will create your assignment manually! Open this file,
every assignment file begins by:
#PACE: Start of Constraints generated by PACE
#PACE: Start of PACE I/O Pin Assignments
Then you choose the pins that you want use. For our example, you need three switch inputs
for din, fclk and reset. You also can use the led for the data output and the errors signal. On
the Xilinx Spartan-3E board, pins are written close to the component like display on figure
***.
Page | 26
Figure *** - Switches and leds on Xilinx Spartan-3E
For example, to use “SW0”, assign the input (rst) to the pin “L13” and for the “Led 7”, assign
to “F9”.
NET "fclk" LOC = "H18" ; NET "fclk" CLOCK_DEDICATED_ROUTE = FALSE;
NET "data<0>" LOC = "E9" ; NET "data<1>" LOC = "D11" ; NET "data<2>" LOC = "C11" ; NET "data<3>" LOC = "F11" ; NET "data<4>" LOC = "E11" ; NET "data<5>" LOC = "E12" ; NET "data<6>" LOC = "F12" ;
NET "din" LOC = "N17" ; NET "rst" LOC = "L13" ; NET "err" LOC = "F9" ;
For finish write:
#PACE: Start of PACE Area Constraints
#PACE: Start of PACE Prohibit Constraints
#PACE: End of Constraints generated by PACE
Save and close the “test.ucf” file. On Xilinx-ISE click on add existing source on the process
windows. Select test.ucf like shows on figure ***. Click OK on window ***.
Page | 27
Figure *** - Add Existing Sources
Figure *** - Add Existing Files…
Then you can see your assignments on the FPGA by double clicking on Floorplan
Area/IO/Logic - Post Synthesis found in the User Constraints process group.
The Xilinx Pinout and Area Constraints Editor opens.
Figure *** - Package Pins for Spartan-3E
Page | 28
You can observe the Location used in blue. The others Pins are all the pins of the FPGA 320,
the Xilinx’s FPGA. On the left, there are the correspondences between the Input/output of
your program and the location where they are connected. Close the window when you
have finished your observations.
Double click the “Implementation Design” on the Processes. You show a warning because
you are using a switch as a clock, the constraints file must be edited to explicitly allow it.
This is why the line “NET "fclk" CLOCK_DEDICATED_ROUTE = FALSE;” is present on the
test.ucf file. Without this line the warning is an error[5]. Now double click the “Generate
Programming File” and then “Configure Target Device”.
Figure *** - Project Navigator
Figure *** - iMPACT dialog box
Page | 29
Select “Configure devices using Boundary-Scan (JTAG)” and “Automatically connect to a
cable and identify Boundary-Scan chain”. Click Finish. Open the test.bit file on figure ***,
and Bypass the other files. Click Ok on the new window.
Figure *** - Assign New Configuration File
You are now able to flash you program on the Xilinx xc3s500e FPGA.
Figure *** - Boundary Scan
Click right on the Green icon (xc3s500e) on select “Program”. The board has been flashed!
You can see a Yellow Led on which means that the Program succeeded.
On the Board, use “SW3” for “din”, “SW2” for “fclk” and “SW0” for “reset”. Data is displayed
on led from “LD0” to “LD6” and the error signal is displayed on the Led “LD7”.
Page | 30
For example, to input “1011100101”, you can switch SW0 to generate either ‘1’ or ‘0’
sequentially. In order to be synchronized by the clock (SW2), switch SW2 to High then low
every time you want valid din. After the data are received leds between LD0 to LD6 will
show you the results and LD7 (error) is off.
Try another sequence: “1111100101” and you will see that parity is false on that case. You
will see LED17 (err) turn ON. You can also try “1111100111” and see that parity is true.
Figure *** - Results on the Xilinx board.
Between Led 6 and Led 0, you can read the sequence “0111001”, that is the sequence you
enter by Din!
Page | 31
1.3 Labview 8.5 design example
LabVIEW is short for “Laboratory Virtual Instrumentation Engineering Workbench”. It is a
platform and development environment for a visual programming language developed by
National Instruments. It is possible to program the FPGA of the NI cRIO-9074. For the
CompactRIO, the embedded FPGA is a high-performance, reconfigurable chip which can be
programed with LabVIEW and LabVIEW FPGA module graphical development tools.
1.3.1 Design entry
When you open Labview, the “Getting Started” window appears. You can open a new VI
(Virtual Instruments’ file), project or open an existing project.
Figure *** - Getting Started window
Page | 32
To create a new FPGA project, click on “More…” in the window called “New”.
Figure *** - New file or project
Select Labview FPGA Project to use the cRIO-9074. This will create a new project using the FPGA for running. Click on Ok, a new window appears. Choose “CompactRIO Reconfigurable Embedded System” and press next. Labview can discover an existing system automatically as the cRIO-9074. So, select “Discover existing system” as on Figure *** and click Next.
Figure *** - Create New CompactRIO FPGA Project
Page | 33
The cRIO is detected, select it and click Next.
Figure *** - Selection of the system
Figure *** - Systems available
When you can see this window, press Finish. You project is created and configured. Close the FPGA Wizard. The Project explorer appears. Save it and give it a name.
Page | 34
Figure *** - Project Explorer
Page | 35
Right click on cRIO (address of this device, here 69.88.163.23) and select New -> VI. Your
file appears on your cRIO project. Save it and give it a name too. Two windows appears, one
is called “Front Panel on Data-Receive” and a second is called “Block Diagram on Data-
Receive”:
- The Block diagram is the program, it is the source code for the Front panel.
Figure *** - Block Diagram
- The Front Panel simulate the panel of a physical instrument like an oscilloscope for
example. It is the interface between the user and the machine. Here is the bottoms,
graphs and indicates.
Figure *** - Front Panel
Page | 36
On the Block Diagram, add the “HDL Interface Node” by right click. If you do not find it, go
to the help menu -> Search the Labview Help, make a research of “HDL interface node” and
click on “find on the Functions palette”. Then add it to your Block Diagram file.
Figure *** - Help Menu
Figure *** - Hdl Nnterface Node on the Block Diagram
Double click on the item, the properties window appears. Insert parameters, that means
your input and output like shows in Figure ***.
Page | 37
Figure *** HDL Interface Node, Parameters tab
On the “Code” tab, after “architecture implementation of test is”, enter the VHDL code.
Figure *** - HDL Interface Node, code tab
Page | 38
Figure *** - VHDL Code
You can check if your code is correct by clicking on “Check Syntax”. Then click on OK. You
can now see all the connection on the HDL Interface Node.
PROCESS (rst, fclk) VARIABLE count: INTEGER RANGE 0 TO 10;
VARIABLE reg: STD_LOGIC_VECTOR (10 DOWNTO 0); VARIABLE temp: STD_LOGIC;
BEGIN IF (rst(0)='0') THEN
count:=0; reg:= (reg'RANGE => '0'); temp := '0'; err(0) <= '0'; data_valid(0) <= '0'; data0(0) <= '0'; data1(0) <= '0'; data2(0) <= '0'; data3(0) <= '0'; data4(0) <= '0'; data5(0) <= '0'; data6(0) <= '0'; ELSIF (fclk(0)' EVENT AND fclk(0) = '1') THEN IF(reg(0)='0' AND din(0)='1') THEN
reg(0) :='1'; ELSIF (reg(0)='1') THEN count := count + 1; IF (count<10) THEN reg(count) := din(0); ELSIF (count=10) THEN temp :=((reg(1) XOR reg(2) XOR reg(3) XOR reg(4)
XOR reg(5) XOR reg(6) XOR reg(7) XOR reg(8)) OR NOT reg(9)); err(0) <= temp; count := 0; temp:= '0'; reg(0) :=din(0); IF (temp ='0') THEN data0(0) <= reg(1); data1(0) <= reg(2); data2(0) <= reg(3); data3(0) <= reg(4); data4(0) <= reg(5); data5(0) <= reg(6); data6(0) <= reg(7); data_valid(0) <= '1'; END IF; END IF; END IF;
END IF; enable_out <= enable_in;
END PROCESS;
Page | 39
Figure *** - HDL interface Node
You need to wire the connection. Before that, create the interaction of your program on the
Front Panel window. Right click on the Front Panel, and select Modern -> Boolean -> LED.
Display nine Led, seven for the data and one for data_valid and err. Choose your input
bottoms by select Modern -> Boolean -> Switch. Create three switches.
Figure *** - Front Panel’s interface
When you add an item on the Front Panel, it is add on the Block Diagram too. Wire the
input and output to their associate items.
Page | 40
Figure *** - Front Panel
1.3.2 Synthesis
Before to run the program, make sure the VI file is in the section FPGA Target (RIO0, cRIO-
9074) like shows on Figure ***.
Figure *** - Project Explorer with test.vi file
Page | 41
Click on the “Run Continuously” icon on the Front Panel or the Block Diagram and press
OK. Wait a couple of minutes, Labview is compiling your program on the cRIO FPGA.
Figure *** - FPGA Compile Server
Figure *** - Successful Compile Report
Click Ok on the Successful Compile Report. You can use your program on the “Front Panel”
renamed “FPGA Target”. As for Altera and Xilinx, use fclk for the clock when you choose din.
For example, to input “1011100101”, you can switch din to generate either ‘1’ or ‘0’
sequentially. In order to be synchronized by the clock, switch “fclk” to High then low every
time you want valid din. After the data are received leds Data-0 to Data-6 will show you the
results while err is “Off” and data_valid is “On”. You can observe your data display by leds,
as shown in the box in Figure ***. The sequence “0111001” is well shows. Moreover, Green
led at the right corresponds to data_valid, so you have well received the data.
Page | 42
Figure *** - Results for din = “1011100101”
Try another sequence: “1111100101” and you will see that parity is false on that case. You
will see LED17 (err) turn ON. You can also try “1111100111” and see that parity is true.
Figure *** - Results for din = “1111100101”
Page | 43
2. Designing a bus interface in FPGA
<TBD>
References
[1] Altera Corp, Literature: Cyclone II Devices, San Jose, California.
http://www.altera.com/products/devices/cyclone2/literature/cy2-literature.jsp
[2] Xilinx Inc, Spartan-3E Starter Kit, San Jose, California.
http://www.xilinx.com/products/devkits/HW-SPAR3E-SK-US-G.htm
[3] National Instruments Corporation., CompactRIO Integrated Systems, Austin, Texas.
http://www.ni.com/pdf/products/us/2008-10370-161-101-D.pdf
[4] V. A. Pedroni, Circuit Design with FPGA, HIT Press, Cambridge, Mass, 2004.