ASIC 120: Digital Systems and Standard-Cell ASIC Design
description
Transcript of ASIC 120: Digital Systems and Standard-Cell ASIC Design
ASIC 120: Digital Systems and Standard-Cell ASIC Design
Tutorial 3: Intermediate VHDL
November 9, 2005
Outline
• Summary of previous tutorial• Other signal values besides ‘0’ and ‘1’• More VHDL data types• Attributes, type definitions• Generics• Splitting a VHDL project across multiple design units and
files• if … generate, for … generate• VHDL 1987 vs. 1993 vs. 2000• Test benches
– time, procedures, variables, file access, etc.
Summary of Previous Tutorial
• HDL design flow
• Format of a VHDL file
• Combinational statements– assignments, conditionals, when … else
• Sequential statements– processes, if … then … else, case, loops
Wires in the Real World
• We think of digital logic as being either 0 or 1• Electricity on a real, physical wire is analog
– many different values
• Basic VHDL types do not take this into account– bit– bit_vector
• This is why we have the ieee.std_logic_1164 library– std_logic– std_logic_vector
std_logic_1164 Values
Value Description‘U’ Uninitialized‘X’ Unknown‘0’ Strong 0 (driving)‘1’ Strong 1 (driving)‘Z’ High impedance‘W’ Weak unknown‘L’ Weak 0 (reading)‘H’ Weak 1 (reading)‘-’ Don't care
std_logic_1164 Resolution Table
U X 0 1 Z W L H -
U U U U U U U U U U
X U X X X X X X X X
0 U X 0 X 0 0 0 0 X
1 U X X 1 1 1 1 1 X
Z U X 0 1 Z W L H X
W U X 0 1 W W W W X
L U X 0 1 L W L W X
H U X 0 1 H W W H X
- U X X X X X X X X
Things to Watch For
• Never have two output driving one wire
• Tri-state buffers– the usual way of connecting components to a
bus– compiler will often synthesize in a mux– explicitly use a mux instead
• Summary: only design with ‘0’ and ‘1’, but be prepared to accept any value
std_logic_1164 example
• Consider:
case Sel is when “00” => X <= B; when “10” => X <= A; when “1-” => X <= D; when others => X <= C; end case;
std_logic_1164 example
• While this statement is valid, it is bad form– unsynthesizable– designing with values other than ‘0’ and ‘1’, instead of just being
prepared to accept them
case Sel is when “00” => X <= B; when “10” => X <= A; when others => X <= C; end case;
More On Numeric Data Types
• We have already seen– bit, bit_vector– std_logic, std_logic_vector
• Now we look at– integer, real– std_logic_arith– numeric_std
Arithmetic Data Types
• bit, bit_vector, std_logic, std_logic_vector are useful for working with wires
• However, cannot perform arithmetic operations– not explicitly signed versus unsigned– integer vs. real representations
Arithmetic Data Types: integer
• integer is to signed as bit_vector is to std_logic_vector
• Not well standardized across VHDL tools
• More on the real data type later
Arithmetic Data Types: std_logic_arith
• Obfuscated
• Use numeric_std instead
Arithmetic Data Types: numeric_std
• Example:
library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;signal data : unsigned(7 downto 0);…data <= 137;data <= data + 1;
Arithmetic Data Types: numeric_std
• numeric_std allows the usual arithmetic operators to be used
• Conversion to/from std_logic_vector– unsigned(…)– signed(…)– std_logic_vector(…)
• Make sure your intermediate signals are large enough– 4-bit number + 4-bit number could equal 5-bit number
Attributes
• Consider:
process(clk)begin
if (clk’event and clk = ‘1’) thenif (resetn = ‘0’)
q <= ‘0’;else
q <= d;end if;
end if;end process;
Attributes
• event is an attribute of the clk signal– the apostrophe (‘) delimits the attribute
• An attribute is a characteristic of a VHDL object– extra data attached to signal, pin, etc.
• Can be user-defined:
Attributes
• User-defined attributes are generally used to tap into specific compiler’s functionality
• Pre-defined attributes include:– event, last_event, last_value– range, length, ascending– left, right, high, low– many more
Attributes Exampleentity eight_regs is
port( clk : in std_ulogic;data_in, load : in std_ulogic_vector(7 downto 0);data_out : out std_ulogic_vector(7 downto 0)
);end eight_regs;
architecture behavioural of eight_regs isbegin
signal data_q : std_ulogic_vector(data_in’range);process(clk)begin
if (clk’event and clk = ‘1’) thenfor i in data_in’range loop
if (data_in’left = ‘0’) then -- resetdata_q(i) <= ‘0’;
elsif (load(i) = ‘1’) then -- load datadata_q(i) <= data_in(i);
end if;end loop;
end if;end process;data_out <= data_q;
end behavioural;
Modular VHDL
• Using the previous example, what if I want 16 registers?– modify the existing code– copy and paste– components
Components
• Components provide a way to take an entity/architecture pair and reuse it– use it multiple times– map signals to component inputs and outputs
Component Example• Using the eight_regs entity/architecture defined earlier:…architecture behavioural of sixteen_regs is
component eight_regsport( clk : in std_ulogic;
data_in, load : in std_ulogic_vector(7 downto 0);data_out : out std_ulogic_vector(7 downto 0)
);end component;
begin-- positionaleight_regs1 : eight_regs port map ( clock, data_in(15 downto 8),
load(15 downto 8), data_out(15 downto 8));-- namedeight_regs2 : eight_regs port map ( clk => clock, data_in => data_in(7 downto 0),
load => load(7 downto 0), data_out => data_out(7 downto 0));
end behavioural;
Generics
• Recall the attributes example– instead of creating two components, what if we
doubled the size of data_in, data_out and load?
• Generics allow us to be flexible with sizes of things– compile time decisions– passed from higher level into an entity
• Syntax:
generic(name : type [:= default_value])
Attributes Exampleentity eight_regs is
port( clk : in std_ulogic;data_in, load : in std_ulogic_vector(7 downto 0);data_out : out std_ulogic_vector(7 downto 0)
);end eight_regs;
architecture behavioural of eight_regs isbegin
signal data_q : std_ulogic_vector(data_in’range);process(clk)begin
if (clk’event and clk = ‘1’) thenfor i in data_in’range loop
if (data_in’left = ‘0’) then -- resetdata_q(i) <= ‘0’;
elsif (load(i) = ‘1’) then -- load datadata_q(i) <= data_in(i);
end if;end loop;
end if;end process;data_out <= data_q;
end behavioural;
Generics Exampleentity eight_regs is
generic (bus_width : integer := 8);port( clk : in std_ulogic;
data_in, load : in std_ulogic_vector(bus_width-1 downto 0);data_out : out std_ulogic_vector(bus_width-1 downto 0)
);end eight_regs;
architecture behavioural of eight_regs isbegin
signal data_q : std_ulogic_vector(data_in’range);process(clk)begin
if (clk’event and clk = ‘1’) thenfor i in data_in’range loop
if (data_in’left = ‘0’) then -- resetdata_q(i) <= ‘0’;
elsif (load(i) = ‘1’) then -- load datadata_q(i) <= data_in(i);
end if;end loop;
end if;end process;data_out <= data_q;
end behavioural;
Generics Example: Up One Level
• Using the eight_regs entity/architecture defined earlier:…architecture behavioural of sixteen_regs is
component eight_regsgeneric(bus_width : integer);port( clk : in std_ulogic;
data_in, load : in std_ulogic_vector(bus_width-1 downto 0);data_out : out std_ulogic_vector(bus_width-1 downto 0)
);end component;
begineight_regs : eight_regs
generic map (bus_width => 16);port map (clock, data_in, load, data_out);
end behavioural;
Generics
• Note that the data type of the bus_width generic is integer, not signed or unsigned– in this case it’s okay
More On Data Types
• User defined data types
• Enumerations
• Arrays
User Defined Data Types
• It is possible to define your own data types in VHDL
• Useful for– reusing type declarations– keeping variable types constant across or variable
declarations components
• Much more can be said on this– VHDL has many data types that we will continue to
introduce throughout these tutorials
Enumerations• Relate human-meaningful text to underlying binary values
– useful for state machines• Example (includes definition of user-defined data type t_states):
architecture test1 of test is…type t_states is (STATE_BEGIN,
STATE_RUN, STATE_TURN, STATE_END);
signal curr_state : t_statesbegin
processbegin
wait until rising_edge(clk);if (curr_state = STATE_BEGIN) then
curr_state <= STATE_RUN)elsif …end if;
end process;end test1;
Arrays
• Collections of other data types– std_logic_vector is just an array of std_logic
• Multidimensional arrays possible– useful for modelling memory– sometimes design tools can automatically
infer memory from them, sometimes not
Arrays
• Consider:
type t_arr_single is array (31 downto 0) of std_logic;type t_arr_mult is array (31 downto 0, 31 downto 0) of
std_logic;
signal arr1 : t_arr_single;signal arr2 : t_arr_mult;
• Also possible:
signal arr3 : array (31 downto 0) of std_logic;
Ways to Replicate Hardware
• How can we replicate VHDL functionality• We have seen
– Manually (copy and paste)– Components and Generics– Loops
• Now we explore– if…generate– for…generate
Generate Statements
• Used to replicate concurrent constructs– Only valid outside of processes– Most useful for creating multiple component
instantiations
if…, for… generate Examplelibrary ieee;use ieee_std_logic_1164.all;
entity variable_shift_reg isgeneric( width : integer := 4;
depth : integer := 3;one_or_two : integer := 1
);port ( clk, reset : in std_logic;
data_in : in std_logic_vector(width-1 downto 0);data_out : out std_logic_vector(width-1 downto 0)
);end variable_shift_reg;
if…, for… generate Examplearchitecture structural of variable_shift_reg is
component single_register_Aport(clk, reset : in std_logic;
data_in : in std_logic;data_out : out std_logic
);end component;
component single_register_Bport(clk, reset, reset2 : in std_logic;
data_in : in std_logic;data_out : out std_logic
);end component;
begin…
if…, for… generate Examplearchitecture structural of variable_shift_reg is
[ component declarations on previous slide]signal data_temp : array(0 to depth) of std_logic_vector(width-1 downto 0);
beginwidth_gen : for i in width-1 downto 0 generate
-- connect inputsdata_temp(0)(i) <= data_in(i);
-- generate “middle” shift registers (generic “one_or_two” selects between _A and _B)depth_gen : for j in 0 to depth-1 generate
A_gen : if (one_or_two = 1) then generatesr_gen : single_register_A port map (clk =>clk, reset => reset,
data_in => data_temp(j)(i),data_out => data_temp(j+1)(i));
end generate A_gen;B_gen : if (one_or_two = 2) then generate
sr_gen : single_register_B port map (clk =>clk, reset => reset, reset2 => reset,data_in => data_temp(j)(i),data_out => data_temp(j+1)(i));
end generate B_gen;end generate depth_gen;
-- connect outputsdata_out(i) <= data_temp(depth)(i);
end generate width_gen;end structural;
if…, for… generate Example
• This example demonstrated how to construct a variable-width, variable-depth shift register– i.e., a width-bit shift register with depth-stages
• You must name an if… or for… generate statement– so the compiler has a base name to give to
each instance of a section
VHDL Versions: 1987, 1993, 2000
• There are three different revisions of VHDL– Modern development tools understand all three
versions– Important to at least know they exist
• Often development tools implement VHDL specification differently as well
• We’re going to postpone further discussion on this for now, because we have more important things to look at
Test Benches
• Testing synthesized HDL code in hardware happens in the final stages of development– time consuming, expensive, difficult
• Test benches allows us to simulate a design– send test inputs– check the outputs– virtually connect different components together to see
how they interact
Test Benches
• Consider a VHDL entity/architecture pair– inputs and outputs will eventually be
connected to physical pins on an FPGA or ASIC
• An entity/architecture pair without inputs or outputs is a test bench– signals are generated internally– think of it like a bread board sitting on your
desk
Simple Test Bench Examplelibrary ieee;use ieee.std_logic_1164.all;
entity test_and_gate is-- no inputs or outputs
end test_and gate;
architecture stimulate of test_and_gate is
component and_gateport(A, B : in std_logic; X : out std_logic);
end component;
constant CLK_PERIOD : time := 20 ns;signal A, B, X : std_logic;
begin
…
end stimulate;
Simple Test Bench Example
• Note that we have introduced CLK_PERIOD as a “constant”– its data type is time– time has a unit, in this case, ns or
nanoseconds
Simple Test Bench Example…begin
-- uut is “unit under test”uut : and_gate port map(A => A, B => B, X => X);
processbegin
A <= 0; B <= 0;wait for CLK_PERIOD;assert (X = ‘0’) report “0,0 result incorrect!” severity ERROR;
A <= 0; B <= 1;wait for CLK_PERIOD;assert (X = ‘0’) report “0,1 result incorrect!” severity ERROR;
A <= 1; B <= 0;wait for CLK_PERIOD;assert (X = ‘0’) report “1,0 result incorrect!” severity ERROR;
A <= 1; B <= 1;wait for CLK_PERIOD;assert (X = ‘1’) report “1,1 result incorrect!” severity ERROR;
wait;end process;
end stimulate;
Simple Test Bench Example
• Instead of “wait until rising_edge(clk)” we are using “wait for CLK_PERIOD”– execution of that process pauses for given
amount of time
• Final “wait” statement will pause forever• “wait for …” is unsynthesizable
– impossible to specify a specific amount of time in hardware
– however, this is very useful for test benches
Clocking Test Benches• Often, the clock will be run independently of the input stimulus• Consider:
processbegin
clk <= ‘0’;wait for CLK_PERIOD;clk <= ‘1’;wait for CLK_PERIOD;
end process;
…
processbegin
wait until rising_edge(clk);[apply input stimulus to unit under test]wait until rising_edge(clk);[check output of unit under test for correctness]
end process;
Clocking Test Benches
• In this way, we can co-ordinate input stimulus across multiple units under test
More on Test Benches
• Another useful test bench tool in VHDL is file input and output– obviously not synthesizable
Functions and Procedures
• Functions and procedures in VHDL are useful for defining a block of functionality that can be re-used– similar to functions in C– not the same thing as processes
• Due to time constraints, we won’t cover them in any further detail
Variables
• Variables can be used to store intermediate values within a process– can also be used in functions and procedures
• They are NOT the same thing as signals– use them wisely
• Due to time constraints, we won’t cover them in any further detail
What I’ve Skipped
• Blocks, Libraries/Packages– other modularity features– we’ve had a taste of libraries and packages:
library ieee; …• Configurations
– way to select among multiple architectures• Constants
– like generics, but within one file• File access
– useful for test benches, not synthesizable• Functions, procedures, variables
Preview of Next Tutorial
• Digital Systems Concepts– The FPGA: LEs, buffers and routing, other
resources– Bus interfaces– Register files– Other FPGA resources: clocks, memories,
memory interfaces, multipliers, etc.– Soft- and hard-processors in FPGAs
Summary
• Summary of previous tutorial• Other signal values besides ‘0’ and ‘1’• More VHDL data types• Attributes, type definitions• Generics• Splitting a VHDL project across multiple design units and
files• if … generate, for … generate• VHDL 1987 vs. 1993 vs. 2000• Test benches
– time, procedures, variables, file access, etc.
UW ASIC Design Team
• www.asic.uwaterloo.ca• reference material
– Accolade VHDL reference (excellent!):http://www.acc-eda.com/vhdlref/
• many of today’s examples came from here
– Bryce Leung’s tutorials (UW ASIC website)– Mike Goldsmith’s tutorials (UW ASIC website)– your course notes
• my contact info:Jeff Wentworth, [email protected]