Register-Transfer Level Design
Register-Transfer Level (RTL) is a design abstraction which models a synchronous digital
circuit in terms of the flow of digital signals (data) between hardware registers, and the logical operations
performed on those signals.
Register-transfer-level abstraction is used in hardware description languages (HDLs) like Verilog
and VHDL to create high-level representations of a circuit, from which lower-level representations and
ultimately actual wiring can be derived. Design at the RTL level is typical practice in modern digital
design
RTL Description
A synchronous circuit consists of two kinds of elements: registers and combinational logic.
Registers (usually implemented as D flip-flops) synchronize the circuit's operation to the edges of the
clock signal, and are the only elements in the circuit that have memory properties. Combinational logic
performs all the logical functions in the circuit and it typically consists of logic gates.
For example, a very simple synchronous circuit is shown in the figure. The inverter is connected
from the output, Q, of a register to the register's input, D, to create a circuit that changes its state on each
rising edge of the clock, clk. In this circuit, the combinational logic consists of the inverter.
When designing digital integrated circuits with a hardware description language, the designs are
usually engineered at a higher level of abstraction than transistor level (logic families) or logic gate level.
In HDLs the designer declares the registers (which roughly correspond to variables in computer
programming languages), and describes the combination logic by using constructs that are familiar from
programming languages such as if-then-else and arithmetic operations. This level is called register-
transfer level. The term refers to the fact that RTL focuses on describing the flow of signals between
registers.
As an example, the circuit mentioned above can be described in VHDL as follows:
D <= not Q;
process (clk)
begin
if rising_edge (clk) then
Q <= D;
end if;
end process;
Using an EDA tool for synthesis, this description can usually be directly translated to an equivalent
hardware implementation file for an ASIC or an FPGA. The synthesis tool also performs logic
optimization.
At the register-transfer level, some types of circuits can be recognized. If there is a cyclic path of
logic from a register's output to its input (or from a set of registers outputs to its inputs), the circuit is
called a state machine or can be said to be sequential logic. If there are logic paths from a register to
another without a cycle, it is called a pipeline.
RTL in the circuit design cycle
RTL is used in the logic design phase of the integrated circuit design cycle.
An RTL description is usually converted to a gate-level description of the circuit by a logic
synthesis tool. The synthesis results are then used by placement and routing tools to create a physical
layout.
Logic simulation tools may use a design's RTL description to verify its correctness.
RTL Synthesis Flow
Logic Design and Verification
Design starts with a specification
Text description or system specification language
Example: C, SystemC, SystemVerilog
RTL Description
Automated conversion from system specification to RTL possible
Example: Cadence C-to-Silicon Compiler
Most often designer manually converts to Verilog or VHDL
Verification
Generate test-benches and run simulations to verify functionality
Assertion based verification
Automated test-bench generation
Static Timing Analysis
Checks temporal requirements of the design
Uses intrinsic gate delay information and estimated routing loads to exhaustively evaluate all timing paths
Requires timing information for any macro-blocks e.g. memories
Will evaluate set-up and hold-time violations
Special cases need to be flagged using timing constraints (more later)
Reports “slack time”
Re-synthesize the circuit or re-design to improve delay
Test Insertion and Power Analysis
Insert various DFT features to perform device testing using Automated Test Equipment
(ATE) and system level tests
Scan enabled flip-flops and scan chains
Automatic Test Pattern Generation (ATPG) tools generate test vectors to perform logic and parametric
testing
Built-in Self Test
Logic: Based on LFSR (random-patterns) and MISR (signature) (LBIST)
Memory: Implements various memory testing algorithms (MBIST)
Boundary-Scan/JTAG
Enables board/system level testing
More on DFT and test insertion later
Power Analysis
Power analysis tools predict power consumption of the circuit
Either test vectors or probabilistic activity factors used for estimation
VHDL Programs
===========================Half Adder==================================
Behavioral style model
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ha is
port (a, b: in bit; sum, carry: out bit);
end entity;
architecture ha1 of ha is
begin
process (a, b)
Data flow style model begin
library IEEE; if (a ='0' and b='0') then
use IEEE.STD_LOGIC_1164.ALL; sum <= '0'; carry<='0';
elsif ( a='0' and b='1') then
entity half_adder is sum<= '1'; carry<='0';
port (A, B : in std_logic; S, C : out elsif ( a='1' and b='0') then
std_logic); sum<= '1'; carry<='0';
end half_adder; elsif( a='1' and b='1') then
architecture myadd of half_adder is sum<= '0'; carry<='1';
begin end if;
S <= A xor B; end process;
C <= A and B; end architecture;
end myadd;
================vhdl code for halfadder using structural model============
library IEEE;
use IEEE.STD_LOGIC_1164.ALL; architecture structural of half-adder is
--andgate is defined as a sub-block of
entity half-adder is --the entity half-adder
port (A, B:in std_logic; S,C :out std_logic); --Component declaration
end half-adder;
entity andgate is component andgate
port (X, Y:in std_logic; Z:out std_logic); port(X, Y:in std_logic; Z:out std_logic);
end andgate; end component;
architecture behavioral of andgate is component xorgate
begin port(L, M:in std_logic; N:out std_logic);
Z <= X and Y; end component;
end behavioral;
entity xorgate is begin
port (L, M:in std_logic; N:out std_logic); --Component Instantiation
end xorgate; --Port mapping of the i/p and o/p ports
architecture behavioral of xorgate is A0: andgate port map (A, B, C);
beginN<=L xor M; X0: xorgate port map (A, B, S);
end behavioral; end structural;
===============Full Adder using two Half Adder==================
library IEEE; end full_adder;
use IEEE.STD_LOGIC_1164.ALL; architecture myfulladd of full_adder is
signal Sum1,Cout1,Cout2:std_logic;
entity half_adder is component half_adder
port (A, B : in std_logic; S, C : out std_logic); port (A, B:in std_logic; S, C:out
end half_adder; std_logic);
architecture myhalfadd of half_adder is end component;
begin begin
S <= A xor B; H1:half_adder port map (A,B
C <= A and B; ,Sum1,Cout1);
end myhalfadd; H2:half_adder port map (Sum1,
entity full_adder is Cin,S,Cout2);
port (A, B, Cin : in std_logic; S, Cout : out Cout <= Cout1 or Cout2;
std_logic); end myfulladd;
=========================Full Adder =====================
-- Behavioral model of Full Adder:
architecture Behavioral of Full_Adder is
-- Data Flow model of Full Adder: begin
process(A, B, Cin)
begin
library IEEE; if (A='0') and (B='0') and (Cin='0')
use IEEE.STD_LOGIC_1164.ALL; then Sum<='0'; Cout<='0';
elsif (A='0') and (B='0') and (Cin='1')
entity FA_DF is then Sum<='1'; Cout<='0';
port (A, B, Cin : in bit; Sum, Cout : out elsif (A='0') and (B='1') and (Cin='0')
bit); then Sum<='1'; Cout<='0';
end FA_DF; elsif (A='0') and (B='1') and (Cin='1')
then Sum<='0'; Cout<='1';
architecture FA_dataflow of FA_DF is elsif (A='1') and (B='0') and (Cin='0')
begin then Sum<='1'; Cout<='0';
elsif (A='1') and (B='0') and (Cin='1')
Sum <= A xor B xor Cin;
then Sum<='0'; Cout<='1';
Cout <= (A and B) or (B and Cin) or (A elsif (A='1') and (B='1') and (Cin='0')
and Cin); then Sum<='0'; Cout<='1';
end FA_dataflow; elsif (A='1') and (B='1') and (Cin='1')
then Sum<='1'; Cout<='1';
end if;
end process;
end Behavioral;
==================Four Bit Binary Adder====================
library ieee;
use ieee.std_logic_1164.all;
-- --Structural architecture
entity xorGate is architecture struct of adderSubtractor is
port( A, B : in std_logic;
F : out std_logic); component xorGate is --XOR
end xorGate; component
-- port( A, B : in std_logic;
architecture func of xorGate is F : out std_logic);
begin end component;
F <= A xor B;
end func; component Full_Adder is
port( X, Y, Cin : in std_logic;
-- Full Adder sum, Cout : out std_logic);
library ieee; end component;
use ieee.std_logic_1164.all;
-- signal C1, C2, C3, C4: std_logic
entity Full_Adder is signal xor0, xor1, xor2, xor3 : std_logic;
port( X, Y, Cin : in std_logic;
sum, Cout : out std_logic); begin
end Full_Adder; GX0: xorGate port map(mode, B0, xor0);
--Dataflow architecture. GX1: xorGate port map(mode, B1, xor1);
--See Full Adder on Teahlab.com for structural GX2: xorGate port map(mode, B2, xor2);
version GX3: xorGate port map(mode, B3, xor3);
architecture func of Full_Adder is
begin FA0: Full_Adder port map(A0, xor0, mode,
sum <= (X xor Y) xor Cin; S0, C1); -- S0
Cout <= (X and (Y or Cin)) or (Cin and Y);
end func; FA1: Full_Adder port map(A1, xor1, C1, S1,
C2); -- S1
-- Four Bit Adder
library ieee; FA2: Full_Adder port map(A2, xor2, C2, S2,
use ieee.std_logic_1164.all; C3); -- S2
entity adderSubtractor is
FA3: Full_Adder port map(A3, xor3, C3, S3,
port( mode : in std_logic;
C4); -- S3
A3, A2, A1, A0 : in std_logic;
B3, B2, B1, B0 : in std_logic; Vout: xorGate port map(C3, C4, V);
S3, S2, S1, S0 : out std_logic; Cout <= C4;
Cout, V : out std_logic); end struct;
end adderSubtractor;
================= 4 to 1 Multiplexer ====================
Data Flow Modeling Style Behavior Modeling Style
library IEEE;
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_1164.all;
entity multiplexer_4_1 is
entity multiplexer_4_1 is
port(
port(
I0 : in std_logic;
din : in std_logic_vector(3 downto 0);
I1 : in std_logic;
sel : in std_logic_vector(1 downto 0);
I2 : in std_logic;
dout : out std_logic
I3 : in std_logic;
);
S0 : in std_logic;
end multiplexer_4_1;
S1 : in std_logic;
Y : out std_logic
architecture multiplexer4_1_arc of
);
multiplexer_4_1 is
end multiplexer_4_1;
begin
architecture multiplexer_4_1_arc of
mux : process (din, sel) is
multiplexer_4_1 is
begin
if (sel="00") then
begin
dout <= din(3);
Y <= ((not S1) and (not S0) and I1) or
elsif (sel="01") then
((not S1) and S0 and I2) or
dout <= din(2);
(S1 and (not S0) and I3) or
elsif (sel="10") then
(S1 and S0 and I3);
dout <= din(1);
end multiplexer_4_1_arc; else
dout <= din(0);
end if;
end process mux;
end multiplexer4_1_arc;
2X1 MUX
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL; 4 Bit Magnitude Comparator
entity mul_2to1 is library IEEE;
port(I0,I1,S: in std_logic; Y: out std_logic); use IEEE.STD_LOGIC_1164.all;
end mul_2to1;
entity comparator_4bit is
architecture arch_mul of mul_2to1 is port(
begin a : in std_logic_vector(3 downto 0);
Y <= ((not S) and I0) or (S and I1);
b : in std_logic_vector(3 downto 0);
end arch_mul;
equal : out std_logic;
greater : out std_logic;
8X1 MUX lower : out std_logic
);
library IEEE; end comparator_4bit;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
architecture comparator_4bit_arc of
entity mux_8to1 is comparator_4bit is
port (s: in std_logic_vector (2 downto 0); begin
I: in std_logic_vector (7 downto 0); comparator : process (a,b) is
Y: out std_logic); begin
end mux_8to1; if (a=b) then
equal <= '1';
architecture arch_mux of mux_8to1 is
greater <= '0';
begin
process (s,I) lower <= '0';
begin elsif (a<b) then
case s is equal <= '0';
when "000" => Y <= I(0); greater <= '0';
when "001" => Y <= I(1); lower <= '1';
when "010" => Y <= I(2);
else
when "011" => Y <= I(3);
when "100" => Y <= I(4); equal <= '0';
when "101" => Y <= I(5); greater <= '1';
when "110" => Y <= I(6); lower <= '0';
when "111" => Y <= I(7); end if;
when others => Y <= '0'; end process comparator;
end case;
end process;
end comparator_4bit_arc;
end arch_mux;
D Flip Flop
library IEEE;
use IEEE.std_logic_1164.all;
entity d_ff_aras is
port (
d,clk,reset,set : in std_logic;
q : out std_logic); library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
end d_ff_aras;
entity jkflipflop1 is
Port ( J : in std_logic;
architecture d_ff_aras of d_ff_aras is
K : in std_logic;
begin CLK : in std_logic;
Q : inout std_logic;
process(clk,reset,set)
QN : inout std_logic);
begin end jkflipflop1;
if reset='1' then
architecture Behavioral of jkflipflop1 is
q <= '0'; begin
process(CLK,J,K)
elsif set='1' then
begin
q <= '1'; if (CLK='1' and CLK'event) then
if(J='0' and K='0') then
elsif clk'event and clk='1' then
Q <=Q;
q <= d; QN <=QN;
elsif(J='0' and K='1') then
end if;
Q <= '0';
end process; QN <= '1';
elsif(J='1' and K='0') then
end d_ff_aras;
Q <= '1';
QN <= '0';
elsif(J='1' and K='1') then
Q <= NOT Q;
QN <= NOT QN;
end if;
JK Flip Flop end if;
end process;
end behavioral;
MOD 6 Counter
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity mod6_counter is
port(
clk : in std_logic;
reset : in std_logic;
dout : out std_logic_vector(2 downto 0)
);
end mod6_counter;
entity bcd_counter is
architecture mod6_counter_arc of mod6_counter is port(
begin reset : in std_logic;
clk : in std_logic;
counter : process (clk,reset) is dout : out std_logic_vector(3 downto 0)
variable m : integer range 0 to 7 := 0; );
begin end bcd_counter;
if (reset='1') then
m := 0; architecture bcd_counter_arc of bcd_counter is
elsif (rising_edge (clk)) then begin
m := m + 1; count : process (reset, clk) is
end if; variable m : std_logic_vector (3 downto 0) :=
if (m=6) then "0000";
m := 0; begin
end if; if (reset='1') then
dout <= conv_std_logic_vector (m,3); m := "0000";
end process counter; elsif (rising_edge (clk)) then
m := m + 1;
end mod6_counter_arc; end if;
if (m="1010") then
BCD Counter m := "0000";
end if;
library IEEE; dout <= m;
use IEEE.STD_LOGIC_1164.all; end process count;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all; end bcd_counter_arc;
========================8 Bit Gray Counter========================
if (reset = '1') then
library ieee; count <= (others=>'0');
use ieee.std_logic_1164.all; elsif (rising_edge(clk)) then
use ieee.std_logic_unsigned.all; if (enable = '1') then
entity gray_counter is count <= count + 1;
port ( end if;
cout :out std_logic_vector (7 downto 0); end if;
enable :in std_logic; end process;
clk :in std_logic; cout <= (count(7) &
reset :in std_logic (count(7) xor count(6)) &
); (count(6) xor count(5)) &
end entity; (count(5) xor count(4)) &
(count(4) xor count(3)) &
architecture rtl of gray_counter is (count(3) xor count(2)) &
signal count :std_logic_vector (7 downto 0); (count(2) xor count(1)) &
begin (count(1) xor count(0)) );
process (clk, reset) begin end architecture;
==================8 Bit Counter with Parallel Load===============
data :in std_logic_vector (7 downto 0);
library ieee; load :in std_logic;
use ieee.std_logic_1164.all; enable :in std_logic;
use ieee.std_logic_unsigned.all; clk :in std_logic;
reset :in std_logic
entity up_counter_load is );
port ( end entity;
cout :out std_logic_vector (7 downto 0);
count <= data;
architecture rtl of up_counter_load is elsif (enable = '1') then
signal count :std_logic_vector (7 downto 0); count <= count + 1;
begin end if;
process (clk, reset) begin end if;
if (reset = '1') then end process;
count <= (others=>'0'); cout <= count;
elsif (rising_edge(clk)) then end architecture;
if (load = '1') then
=========================3 Bit Up / Down Counter=========================
library IEEE;
use IEEE.STD_LOGIC_1164.ALL; when "011"=> if (r='1') then next_state <=
"000";
entity cnt3ud is elsif (c='0') then next_state <= "011";
port(clk,c,r,ud : in bit; cnt : out bit_vector(2 elsif (ud='1') then next_state <= "100";
downto 0)); else next_state <= "010";
end cnt3ud; end if;
architecture one of cnt3ud is when "100"=> if (r='1') then next_state <=
signal state,next_state : bit_vector(2 downto "000";
0) := "000"; elsif (c='0') then next_state <= "100";
begin elsif (ud='1') then next_state <= "101";
process else next_state <= "011";
begin end if;
wait until clk='1' and clk'event;
state <= next_state; when "101"=> if (r='1') then next_state <=
end process; "000";
process (state,c,r,ud) elsif (c='0') then next_state <= "101";
begin elsif (ud='1') then next_state <= "110";
case state is else next_state <= "100";
when "000"=> if (r='1') then next_state <= end if;
"000";
elsif (c='0') then next_state <= "000"; when "110"=> if (r='1') then next_state <=
elsif (ud='1') then next_state <= "001"; "000";
else next_state <= "111"; elsif (c='0') then next_state <= "110";
end if; elsif (ud='1') then next_state <= "111";
when "001"=> if (r='1') then next_state <= else next_state <= "101";
"000"; end if;
elsif (c='0') then next_state <= "001";
elsif (ud='1') then next_state <= "010"; when "111"=> if (r='1') then next_state <=
else next_state <= "000"; "000";
end if; elsif (c='0') then next_state <= "111";
elsif (ud='1') then next_state <= "000";
when "010"=> if (r='1') then next_state <= else next_state <= "110";
"000"; end if;
elsif (c='0') then next_state <= "010"; end case;
elsif (ud='1') then next_state <= "011"; end process;
else next_state <= "001"; cnt <= state;
end if; end one;
Universal Shift Register entity USR is
Port ( D : in std_logic_vector (3 downto 0);
CLK, RST : in std_logic;
SIR, SIL : in std_logic; use ieee.std_logic_1164.all;
S :in std_logic_vector (1 downto 0);
entity pipo is
Q : out std_logic_vector (3 downto 0)); port(
clk : in std_logic;
end entity USR;
D: in std_logic_vector (3 downto 0);
architecture behavioral of USR is Q: out std_logic_vector(3 downto 0)
);
begin
end pipo;
process(CLK, RST) is
architecture arch of pipo is
variable REG : std_logic_vector(3 downto 0);
begin begin
if (RST = '0') then
process (clk)
reg := (others => '0'); begin
if (CLK'event and CLK='1') then
elsif rising_edge(clk) then
Q <= D;
case S is end if;
end process;
when "11" =>
REG := D; end arch;
when "01" =>
Serial In – Parallel Out Shift Registers
REG := SIR & REG (3 downto 1);
library ieee;
when "10" =>
use ieee.std_logic_1164.all;
REG := REG (2 downto 0) & SIL;
entity sipo is
when others =>
port(
null; clk, clear : in std_logic;
Input_Data: in std_logic;
end case;
Q: out std_logic_vector(3 downto 0) );
end if; end sipo;
Q <= REG;
architecture arch of sipo is
end process; begin
process (clk)
end architecture;
begin
if clear = '1' then
Q <= "0000";
elsif (CLK'event and CLK='1') then
Q(3 downto 1) <= Q(2 downto 0);
Q(0) <= Input_Data;
end if;
Parallel In – Parallel Out Shift Registers end process;
end arch;
library ieee;