From Hamsterworks Wiki!
Please make sure that you have completed the earlier modules of FPGA course.
Having problems with your code? Do I need to change something? Want a reference solution to the project? Email me at "email@example.com", after removing the "nospam-" bit. I'll try to get back to you in a day or so.
Aims of module
- Implement binary addition through explicit logic
- Implement binary addition using IEEE.STD_LOGIC_UNSIGNED.ALL
- Test binary subtraction
You don't have to, but as a learning exercise it is valuable to implement simple binary addition.
To do so we have to make use of our first 'local variable' - a signal that is used only with the Switches_LEDs entity.
We will need four of these local signals. To do this, we add the definition of the signal between the "architecture" and "begin" lines:
... architecture Behavioral of Switches_LEDs is signal x : STD_LOGIC_VECTOR(3 downto 0); signal y : STD_LOGIC_VECTOR(3 downto 0); signal carry : STD_LOGIC_VECTOR(3 downto 0); signal result : STD_LOGIC_VECTOR(4 downto 0); begin ...
The sizes used may look a little odd, but we are going to add two four-bit numbers on the switches, which gives a five bit result (as 15+15 = 30). Let's wire the LED's up to the "result" signal, and set the unused LEDs to '0'.
LEDs <= "000" & result;
And we will also assign the values of X and Y to be the first and second group of four switches
x <= switches(3 downto 0); y <= switches(7 downto 4);
Here is the code for adding the first bit:
result(0) <= x(0) XOR y(0); carry(0) <= x(0) AND y(0);
Not too hard. This a half adder - it's called this as it doesn't have a 'carry in' only a 'carry out'.
Now here's the second bit, which is a 'full-adder' - it is a lot more complex as it has to deal with an x bit, a y bit and the carry bit from adding bit zero:
result(1) <= x(1) XOR y(1) XOR carry(0); carry(1) <= (x(1) AND y(1)) OR (carry(0) AND X(1)) OR (carry(0) AND Y(1));
It is a lot easier to understand the carry expression if you think of it as "are any two bits set?".
So here's the code up till now:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Switches_LEDs is Port ( switches : in STD_LOGIC_VECTOR(7 downto 0); LEDs : out STD_LOGIC_VECTOR(7 downto 0) ); end Switches_LEDs; architecture Behavioral of Switches_LEDs is signal x : STD_LOGIC_VECTOR(3 downto 0); signal y : STD_LOGIC_VECTOR(3 downto 0); signal carry : STD_LOGIC_VECTOR(3 downto 0); signal result : STD_LOGIC_VECTOR(4 downto 0); begin LEDs <= "000" & result; x <= switches(3 downto 0); y <= switches(7 downto 4); result(0) <= x(0) XOR y(0); carry(0) <= x(0) AND y(0); result(1) <= x(1) XOR y(1) XOR carry(0); carry(1) <= (x(1) AND y(1)) OR (carry(0) AND X(1)) OR (carry(0) AND Y(1)); end Behavioral;
Project 5.1 - Adding four bits
- Based on the code so far, extend this to add all four bite (note - result(4) will be the value of carry(3)). Test the design for a few values.
- How many combinations to you have to test to fully verify that your design works properly?
- Change the ordering of the statements in the code. Does it matter which order they are written in? Why would this be?
And now a better way to add (and subtract) numbers
Though interesting, this is a hard way to add numbers. VHDL includes standard libraries that make things a lot easier for you - STD_LOGIC_UNSIGNED allows you to treat your STD_LOGIC_VECTORS as if they are unsigned binary numbers.
To allow this, you need to add the following line to your code:
You can then just code the addition as:
result(4 downto 0) <= x + y;
Not requiring the ten lines or so of code.
The result of adding vectors will be only as long as the longest vector being added. I most cases this is one short that what is required to express the full range of results (and a warning like "Width mismatch. <result> has a width of 5 bits but assigned expression is 4-bit wide."). To ensure that I do get the full result I usually force at least one vector to be the length of the desired result:
result(4 downto 0) <= ('0' & x) + y;
Project 5.2 - Adding four bit numbers
- Change your code to use unsigned addition. Test if it works.
- Try it both with and without adding an extra bit to the length of the 'x' signal. Does it work as expected?
- Implement binary subtraction using AND, OR, XOR and NOT operators
- Implement addition using only NOR or only NAND gates
- Design a project to add "00000001" to the value on the switches and display it on the LEDs. If you use the full adder code you will be able to simplify the logic down to a familiar pattern...
Ready to carry on?
Click here to carry on to the next module. This is where things start to get interesting...