Lab 2B) Event-Driven Simulation of the DLX ALU
In this exercise we'll be modifying the original DLX design to follow
common guidelines and for successfull synthesis results. We'll use
the simulator to verify our work.
Prerequisites:
- Lab 1: "Event-Driven Simulation Set Up"
Important Concepts:
- Organizing VHDL Files
- Signals vs Variables
- Test Benchs
Outline
- Architecture Behavioral - Arithmetic ADD/SUB Operations
- Architecture Behavioral - Logic SHIFT Operations
- Architecture Behavioral - The Status Ports
ZERO_RESULT/NEGATIVE/OVERFLOW
Entity ALU
Prepare a file called alu.vhdl in your ~/vhdl_class/vhdlsrc directory
that describes an entity for the alu.
You may want to refer to the original alu design source
There are changes required to this design which will be introduced in
subsequent sections.
Coding Discussion
- Organizing VHDL Files
- The first significant change consists of combining entity and
architectures into a single file. While it's not - strictly speaking -
necessary, it's commonly accepted practice. The VHDL LRM does not
specify any particular arrangement however VHDL analyzers work on a
file at a time so however you arrange your VHDL into files each file
must be considered syntactically complete. Thoughout the following
exercises we'll instruct you to combine entity and architecture(s) in a
single file and name files according to this simple guideline:
- <entity_name>.vhdl
-
Instructions:
Continue working in the lab2 directory.
Architecture Behavioral - Implimenting Arithmetic ADD/SUB
Operations
We'll now undertake the implimentation of more complicated arithmetic
operations.
Coding Discussion
The ability to take an abstract HDL descruption containing a plus "+"
operator and construct a hardware adder is a pretty recent phenomenen
in the system design world. Every simulator can execute the code and
calculate the results but synthesis tools differ on their exact
policies.
- IEEE has a standard that describes packages numeric_bit and
numeric_std. A version of this for HIS/Booledozer is currently under
test.
- Synopsys has a proprietary standard called std_logic_arith.
The first point is that arithmetic operations are grouped into 2
classes with fundamentally different behavior: signed and unsigned.
Both are based on a vectored base type of 0 to some maximum width. Bit
0 being the MSB and the last bit the LSB.
- Signed
- Operations treat the MSB as an indication the sign ( +/- ) of
the number represented so the range available for arithmetic operations
is 2**(word length -1).
- Unsigned
- Operations utilize the full width of the word for arithmetic
operations and can not represent values < 0.
The designer should always be aware of what is appropriate for the
application and select the proper base types. Our DLX processor
provides both classes of instructions so we'll consider both. After
careful examination of the origonal DLX ALU we determine that it
impliments 32 bit arithmetic operations with an additional overflow
bit. We'll use these functions from the
IEEE_EXTD.std1164_vector_arithmetic package:
----------------------------------------------------------------
-- Signed addition with overflow detection
----------------------------------------------------------------
procedure sv_add (sv1, sv2 : in std_logic_vector;
sv_result : out std_logic_vector;
overflow : out std_logic);
----------------------------------------------------------------
-- Signed addition without overflow detection
----------------------------------------------------------------
procedure sv_add (sv1, sv2 : in std_logic_vector;
sv_result : out std_logic_vector);
----------------------------------------------------------------
-- Unsigned addition with overflow detection
----------------------------------------------------------------
procedure sv_addu (sv1, sv2 : in std_logic_vector;
sv_result : out std_logic_vector;
overflow : out std_logic);
Instructions
Now we're ready to add our instructions to the alu design. We want to
modify the vhdlsrc/alu.vhdl file to add a dependency on Library
ieee_extd.std1164_vector_arithmetic.all and expose the arithmetic
support discussed earlier. Next, we'll tackle the simplest form - the
unsigned add operation.
Unsigned Addition/Subtraction - Next we'll assign these
variables
from their respective ports. Finally we'll add a leg to the case
statement
for alu_addu and assign the temp_result.
signal stored_s1, stored_s2 :
dlx_word;
alu_op: process (stored_s1, stored_s2, func)
variable tmp_res : dlx_word;
variable tmp_ovl : std_logic;
begin
...
sv_addu(stored_s1, stored_s2, tmp_res, tmp_ovl);
Signed
Addition/Subtraction -
sv_add(stored_s1, stored_s2, tmp_res, tmp_ovl);
Logic SHIFT Operations
sv_sll(stored_s1, tmp_res, stored_s2(27 to 31));
Architecture Behavioral - Implimenting The Status Ports
ZERO_RESULT/NEGATIVE/OVERFLOW
The hardest part is over. These status bits are derived by comparing
and testing the value of temp_result
if tmp_res = X"0000_0000" then
zero <= '1' after tpd_out;
else
zero <= '0' after tpd_out;
end if;
negative <= tmp_res(0) after tpd_out;
overflow <= tmp_ovl after tpd_out;