Unit 4
Design using VHDL
Figure 1. Logic gates
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity logic_gate is
Port ( A,B : in std_logic;
y_and,y_or,y_nand,y_nor,y_not,y_xor,y_xnor : out std_logic);
end logic_gate;
architecture all_gates of logic_gate is
begin
y_and <= a and b;
y_or <= a or b;
y_nand <= a nand b;
y_nor <= a nor b;
y_not <= not a ;
y_xor <= a xor b;
y_xnor <= a xnor b;
end all_gates;
Key takeaways:
VHDL program to build all NAND, NOR, XOR, and XNOR gates using AND-OR-NOT gates
Half Adder
Library ieee;
use ieee.std_logic_1164.all;
entity half_adder is
port(a,b:in bit; sum,carry:out bit);
end half_adder;
architecture data of half_adder is
begin
sum<= a xor b;
carry <= a and b;
end data;
Figure2. Half adder waveforms
Library ieee;
use ieee.std_logic_1164.all;
Half subtractor
Library ieee;
use ieee.std_logic_1164.all;
entity half_sub is
port(a,c:in bit; d,b:out bit);
end half_sub;
architecture data of half_sub is
begin
d<= a xor c;
b<= (a and (not c));
end data;
Figure 3. Half subtractor
Full Subtractor
Library ieee;
use ieee.std_logic_1164.all;
entity full_sub is
port(a,b,c:in bit; sub,borrow:out bit);
end full_sub;
architecture data of full_sub is
begin
sub<= a xor b xor c;
borrow <= ((b xor c) and (not a)) or (b and c);
end data;
Figure 4. Full subtractor
Key takeaways:
In combinational behavior can be specified as concurrent signal assignments
Figure 5. General purpose processor
Key takeaways
A microprocessor is a computer processor which incorporates the functions of a computer's central processing unit (processor) on a single integrated chip.
Consider the example of an adder that can add 4-values. Assume, we want to add, a, b, c, d. If the output is s, the code can be written as,
s <= ( ( a + b ) + c ) + d ;
However, this results in a large circuit because the circuit will have 3 adders as shown in the figure,
Figure6. Adders
Use one adder and use it sequentially to add up all the four values. This is when we will need FSM/a control path. Lets take a look how the circuit might look like,
Figure7. Control path circuit
To define the data path it works on 2-bit input sel and 1-bit inputs load and clear from the control path.
-- datapath
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_arith.all ;
use work.averager_types.all ;
entity datapath is
port (
a, b, c, d : in num ;
sum : out num ;
sel : in std_logic_vector (1 downto 0) ;
load, clear, clk : in std_logic
) ;
end datapath ;
architecture rtl of datapath is
signal mux_out, sum_reg, next_sum_reg :num ;
constant sum_zero :num :=
conv_unsigned(0,next_sum_reg’length) ;
begin
-- mux to select input to add
with sel select mux_out<=
a when "00",
b when "01",
c when "10",
d when others ;
-- mux to select register input
next_sum_reg<=
sum_reg + mux_out when load = ’1’ else
sum_zero when clear = ’1’ else
sum_reg ;
-- register sum
process(clk)
begin
if clk’event and clk = ’1’ then
sum_reg<= next_sum_reg ;
end if ;
end process ;
-- entity output is register output
sum <= sum_reg ;
end rtl ;
The next state is the controller which controls the datapath.
-- controller
library ieee ;
use ieee.std_logic_1164.all ;
use work.averager_types.all ;
entity controller is
port (
update : in std_logic ;
sel : out std_logic_vector (1 downto 0) ;
load, clear : out std_logic ;
clk : in std_logic
) ;
end controller ;
architecture rtl of controller is
signal s, holdns, ns : states ;
signal tmp :std_logic_vector (3 downto 0) ;
begin
-- select next state
with s select ns <=
add_a when clr,
add_b when add_a,
add_c when add_b,
add_d when add_c,
hold when add_d,
holdns when others ; -- hold
-- next state if in hold state
holdns<=
clr when update = ’1’ else
hold ;
-- state register
process(clk)
begin
if clk’event and clk = ’1’ then
s <= ns ;
end if ;
end process ;
-- controller outputs
with s select sel<=
"00" when add_a,
"01" when add_b,
"10" when add_c,
"11" when others ;
load <= ’0’ when s = clr or s = hold else ’1’ ;
clear <= ’1’ when s = clr else ’0’ ;
end rtl ;
ALU’s comprise the combinational logic that implements logic operations such as AND, OR, NOT gate and arithmetic operations, such as Adder, Subtractor.
Functionally, the operation of typical ALU is represented as shown in diagram below,
Figure 8. Functional Description of 4-bit Arithmetic Logic Unit
Controlled by the three function select inputs (sel 2 to 0), ALU can perform all the 8 possible logic operations
VHDL Code for 4-bit ALU
library IEEE; | |
use IEEE.STD_LOGIC_1164.ALL; | |
use IEEE.NUMERIC_STD.ALL; | |
| |
entity alu is | |
Port ( inp_a : in signed(3 downto 0); | |
inp_b : in signed(3 downto 0); | |
sel : in STD_LOGIC_VECTOR (2 downto 0); | |
out_alu : out signed(3 downto 0)); | |
end alu; | |
| |
architecture Behavioral of alu is | |
Begin | |
process(inp_a, inp_b, sel) | |
Begin | |
case sel is | |
when "000" => | |
out_alu<= inp_a + inp_b; – addition | |
when "001" => | |
out_alu<= inp_a - inp_b; – subtraction | |
when "010" => | |
out_alu<= inp_a - 1; – sub 1 | |
when "011" => | |
out_alu<= inp_a + 1; – add 1 | |
when "100" => | |
out_alu<= inp_a and inp_b; – AND gate | |
when "101" => | |
out_alu<= inp_a or inp_b; – OR gate | |
when "110" => | |
out_alu<= not inp_a ; – NOT gate | |
when "111" => | |
out_alu<= inp_a xor inp_b; – XOR gate | |
when others => | |
NULL; | |
end case; | |
| |
end process; | |
| |
end Behavioral; |
Testbench VHDL Code for 4-Bit ALU
LIBRARY ieee; | |
USE ieee.std_logic_1164.ALL; | |
USE ieee.numeric_std.ALL; | |
| |
ENTITY Tb_alu IS | |
END Tb_alu; | |
| |
ARCHITECTURE behavior OF Tb_alu IS | |
| |
– Component Declaration for the Unit Under Test (UUT) | |
| |
COMPONENT alu | |
PORT( | |
inp_a : IN signed(3 downto 0); | |
inp_b : IN signed(3 downto 0); | |
sel : IN std_logic_vector(2 downto 0); | |
out_alu : OUT signed(3 downto 0) | |
); | |
END COMPONENT; | |
| |
| |
– Inputs | |
signal inp_a : signed(3 downto 0) := (others => '0'); |
signal inp_b : signed(3 downto 0) := (others => '0'); |
signal sel : std_logic_vector(2 downto 0) := (others => '0'); | |
| |
– Outputs | |
signal out_alu : signed(3 downto 0); | |
| |
BEGIN | |
| |
– Instantiate the Unit Under Test (UUT) | |
uut: alu PORT MAP ( | |
inp_a =>inp_a, | |
inp_b =>inp_b, | |
sel =>sel, | |
out_alu =>out_alu | |
); | |
| |
– Stimulus process | |
stim_proc: process | |
Begin | |
– hold reset state for 100 ns. | |
wait for 100 ns; | |
| |
– insert stimulus here | |
| |
inp_a<= "1001"; | |
inp_b<= "1111"; | |
| |
sel<= "000"; | |
wait for 100 ns; | |
sel<= "001"; | |
wait for 100 ns; | |
sel<= "010"; | |
wait for 100 ns; | |
sel<= "011"; | |
wait for 100 ns; | |
sel<= "100"; | |
wait for 100 ns; | |
sel<= "101"; | |
wait for 100 ns; | |
sel<= "110"; | |
wait for 100 ns; | |
sel<= "111"; | |
end process; | |
| |
END; | |
Simulation Result for 4-bit ALU
Figure 9. ALU
In a 4:2 encoder, the circuit takes 4 bits of data as input. It then codes the data to give an output of two bits.
By behavior, we mean, the response or output of a circuit under the application of a certain set of inputs.
Truth table of a 4:2 encoder
A | B | C | D | Y0 | Y1 |
|
|
|
|
|
|
|
0 | 0 | 0 | 1 | 0 | 0 |
|
|
|
|
|
|
|
0 | 0 | 1 | 0 | 0 | 1 |
|
|
|
|
|
|
|
0 | 1 | 0 | 0 | 1 | 0 |
|
|
|
|
|
|
|
1 | 0 | 0 | 0 | 1 | 1 |
|
|
|
|
|
|
|
The entity-architecture pair. The entity will have the port declaration statements of four input ports and two output ports. This is defined as STD_LOGIC_VECTOR datatype.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity ENCODER_SOURCE is
Port ( I : in STD_LOGIC_VECTOR (3 downto 0);
Y : out STD_LOGIC_VECTOR (1 downto 0));
end ENCODER_SOURCE;
The behavioral code always has a process statement. The sensitivity list variable here would be the input vector I. We begin the architecture first, define the process, and then begin the process. This order is imperative.
architecture Behavioral of ENCODER_SOURCE is
begin
process (I)
begin
The if sequential statement that we use in VHDL is not to be confused with the if or else-if statement that we are accustomed to in the C programming language. The syntax is a bit different here.
if I = "0001" then Y <= "00";
elsif I = "0010" then Y <= "01";
elsif I = "0100" then Y <= "10";
else Y <= "11";
Towards the end, you need to close the begin statements, as well as the if statement.
end if;
end process;
end Behavioral;
Binary decoder
Binary decoder has n-bit input lines and 2 power n output lines. It can be 2-to-4, 3-to-8 and 4-to-16 line configurations. Binary decoder can be easily constructed using basic logic gates. VHDL Code of 2 to 4 decoder can be easily implemented with structural and behavioral modelling.
Figure 10. 2 to 4 Decoder design using logic gates
Figure 11. Truth Table for 2 to 4 Decoder
Similar to Encoder Design, VHDL Code for 2 to 4 decoder can be done in different methods like using case statement, using if else statement, using logic gates etc.
VHDL Code for 2 to 4 decoder using case statement
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity decoder is
port(
a : in STD_LOGIC_VECTOR(1 downto 0);
b : out STD_LOGIC_VECTOR(3 downto 0)
);
end decoder;
architecture bhv of decoder is
begin
process(a)
Begin
case a is
when "00" => b <= "0001"; when "01" => b <= "0010"; when "10" => b <= "0100"; when "11" => b <= "1000";
end case;
end process;
end bhv;
VHDL Code for 2 to 4 decoder using if else statement
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity decoder1 is
port(
a : in STD_LOGIC_VECTOR(1 downto 0);
b : out STD_LOGIC_VECTOR(3 downto 0)
);
end decoder1;
architecture bhv of decoder1 is
Begin
process(a)
Begin
if (a="00") then
b <= "0001";
elsif (a="01") then
b <= "0010";
elsif (a="10") then
b <= "0100";
Else
b <= "1000";
end if;
end process;
end bhv;
VHDL Code for 2 to 4 decoder using logic gates
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity decoder2 is
port(
a : in STD_LOGIC_VECTOR(1 downto 0);
b : out STD_LOGIC_VECTOR(3 downto 0)
);
end decoder2;
architecture bhv of decoder2 is
Begin
b(0) <= not a(0) and not a(1);
b(1) <= not a(0) and a(1);
b(2) <= a(0) and not a(1);
b(3) <= a(0) and a(1);
end bhv;
TestBench VHDL Code for 2 to 4 decoder
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY tb_decoder IS
END tb_decoder;
ARCHITECTURE behavior OF tb_decoder IS
– Component Declaration for the Unit Under Test (UUT)
COMPONENT decoder
PORT(
a : IN std_logic_vector(1 downto 0);
b : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
– Inputs
signal a : std_logic_vector(1 downto 0) := (others => '0');
– Outputs
signal b : std_logic_vector(3 downto 0);
– appropriate port name
BEGIN
– Instantiate the Unit Under Test (UUT)
uut: decoder PORT MAP (
a => a,
b => b
);
– Stimulus process
stim_proc: process
Begin
– hold reset state for 100 ns.
wait for 100 ns;
a <= "00";
wait for 100 ns;
a <= "01";
wait for 100 ns;
a <= "10";
wait for 100 ns;
a <= "11";
wait;
end process;
END;
Figure 11. Test Bench waveform
Library ieee;
use ieee.std_logic_1164.all;
entity full_adder is port(a,b,c:in bit; sum,carry:out bit);
end full_adder;
architecture data of full_adder is
begin
sum<= a xor b xor c;
carry <= ((a and b) or (b and c) or (a and c));
end data;
Figure 12. Full Adder
Full Subtractor
Library ieee;
use ieee.std_logic_1164.all;
entity full_sub is
port(a,b,c:in bit; sub,borrow:out bit);
end full_sub;
architecture data of full_sub is
begin
sub<= a xor b xor c;
borrow <= ((b xor c) and (not a)) or (b and c);
end data;
Figure 13. Full Subtractor
Library ieee;
use ieee.std_logic_1164.all;
entity mux is
port(S1,S0,D0,D1,D2,D3:in bit; Y:out bit);
end mux;
architecture data of mux is
begin
Y<= (not S0 and not S1 and D0) or
(S0 and not S1 and D1) or
(not S0 and S1 and D2) or
(S0 and S1 and D3);
end data;
Waveforms
Figure14. Multiplexer
VHDL Code for a Demultiplexer
Library ieee;
use ieee.std_logic_1164.all;
entity demux is
port(S1,S0,D:in bit; Y0,Y1,Y2,Y3:out bit);
end demux;
architecture data of demux is
begin
Y0<= ((Not S0) and (Not S1) and D);
Y1<= ((Not S0) and S1 and D);
Y2<= (S0 and (Not S1) and D);
Y3<= (S0 and S1 and D);
end data;
Waveforms
Figure 15. Demultiplexer
library IEEE;
use IEEE.std_logic_1164.all;
entity TS_DRVR is
port ( IN_BITS : in BIT_VECTOR ( 15 downto 0 );
OE : in BIT := '1';
OUT_BITS : out STD_LOGIC_VECTOR (15 downto 0) );
end TS_DRVR;
architecture SIMPLE of TS_DRVR is
begin
process ( OE, IN_BITS ) -- if OE or input data
-- change, may change output
begin
if OE = '0' then -- if OE asserted, then
OUT_BITS <= To_StdLogicVector ( IN_BITS );
else -- otherwise
OUT_BITS <= "ZZZZZZZZZZZZZZZZ"; -- tri-state output
end if;
end process;
end SIMPLE;
Figure 16. 4 bit PIPO
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity pipo_behavior is
port(
clk : in STD_LOGIC;
reset : in STD_LOGIC;
din : in STD_LOGIC_VECTOR(3 downto 0);
dout : out STD_LOGIC_VECTOR(3 downto 0)
);
end pipo_behavior;
architecture pipo_behavior_arc of pipo_behavior is
begin
pipo : process (clk,din,reset) is
begin
if (reset='1') then
dout<= "0000";
elsif (rising_edge (clk)) then
dout<= din;
end if;
end process pipo;
end pipo_behavior_arc;
References:
Fundamentals of Modern VLSI Devices Book by Tak H. Ning and Yuan Taur
Introduction to VLSI systems Book by Carver Mead
VLSI physical design automation Textbook by Sadiq Sait
Cmos Digital Integrated Circuits Book by Sung-Mo Kang and Yusuf Leblebici