ASIC 120 Digital Systems and StandardCell ASIC Design

  • Slides: 54
Download presentation
ASIC 120: Digital Systems and Standard-Cell ASIC Design Tutorial 3: Intermediate VHDL November 9,

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’

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

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

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_vector • This is why we have the ieee. std_logic_1164 library – std_logic_vector

std_logic_1164 Values Value ‘U’ ‘X’ ‘ 0’ ‘ 1’ ‘Z’ ‘W’ ‘L’ ‘H’ ‘-’

std_logic_1164 Values Value ‘U’ ‘X’ ‘ 0’ ‘ 1’ ‘Z’ ‘W’ ‘L’ ‘H’ ‘-’ Description Uninitialized Unknown Strong 0 (driving) Strong 1 (driving) High impedance Weak unknown Weak 0 (reading) Weak 1 (reading) Don't care

std_logic_1164 Resolution Table U X 0 1 Z W L H - U U

std_logic_1164 Resolution Table U X 0 1 Z W L H - U U U U U X U X X X X 0 U X 0 0 0 0 X 1 U X X 1 1 1 X Z U X 0 1 Z W L H X W U X 0 1 W W X L U X 0 1 L W X H U X 0 1 H W W H X U X X X X

Things to Watch For • Never have two output driving one wire • Tri-state

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;

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

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 –

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_vector are useful for working with wires •

Arithmetic Data Types • bit, bit_vector, 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

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: std_logic_arith • Obfuscated • Use numeric_std instead

Arithmetic Data Types: numeric_std • Example: library ieee; use ieee. std_logic_1164. all; use ieee.

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

Arithmetic Data Types: numeric_std • numeric_std allows the usual arithmetic operators to be used • Conversion to/from std_logic_vector – unsigned(…) – 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’) then if

Attributes • Consider: process(clk) begin if (clk’event and clk = ‘ 1’) then if (resetn = ‘ 0’) q <= ‘ 0’; else q <= d; end if; end process;

Attributes • event is an attribute of the clk signal – the apostrophe (‘)

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 •

Attributes • User-defined attributes are generally used to tap into specific compiler’s functionality • Pre-defined attributes include: – event, last_value – range, length, ascending – left, right, high, low – many more

Attributes Example entity eight_regs is port( clk : in std_ulogic; data_in, load : in

Attributes Example entity 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 is begin signal data_q : std_ulogic_vector(data_in’range); process(clk) begin if (clk’event and clk = ‘ 1’) then for i in data_in’range loop if (data_in’left = ‘ 0’) then -- reset data_q(i) <= ‘ 0’; elsif (load(i) = ‘ 1’) then -- load data_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? –

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

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

Component Example • Using the eight_regs entity/architecture defined earlier: … architecture behavioural of sixteen_regs is component eight_regs 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 component; begin -- positional eight_regs 1 : eight_regs port map ( downto 8), data_out(15 downto 8)); -- named eight_regs 2 : eight_regs port map ( clock, data_in(15 downto 8), load(15 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

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 Example entity eight_regs is port( clk : in std_ulogic; data_in, load : in

Attributes Example entity 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 is begin signal data_q : std_ulogic_vector(data_in’range); process(clk) begin if (clk’event and clk = ‘ 1’) then for i in data_in’range loop if (data_in’left = ‘ 0’) then -- reset data_q(i) <= ‘ 0’; elsif (load(i) = ‘ 1’) then -- load data_q(i) <= data_in(i); end if; end loop; end if; end process; data_out <= data_q; end behavioural;

Generics Example entity eight_regs is generic (bus_width : integer : = 8); port( clk

Generics Example entity 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 is begin signal data_q : std_ulogic_vector(data_in’range); process(clk) begin if (clk’event and clk = ‘ 1’) then for i in data_in’range loop if (data_in’left = ‘ 0’) then -- reset data_q(i) <= ‘ 0’; elsif (load(i) = ‘ 1’) then -- load data_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

Generics Example: Up One Level • Using the eight_regs entity/architecture defined earlier: … architecture behavioural of sixteen_regs is component eight_regs generic(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; begin eight_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

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

More On Data Types • User defined data types • Enumerations • Arrays

User Defined Data Types • It is possible to define your own data types

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

Enumerations • Relate human-meaningful text to underlying binary values – • useful for state machines Example (includes definition of user-defined data type t_states): architecture test 1 of test is … type t_states is (STATE_BEGIN, STATE_RUN, STATE_TURN, STATE_END); signal curr_state : t_states begin process begin wait until rising_edge(clk); if (curr_state = STATE_BEGIN) then curr_state <= STATE_RUN) elsif … end if; end process; end test 1;

Arrays • Collections of other data types – std_logic_vector is just an array of

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

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 arr 1 : t_arr_single; signal arr 2 : t_arr_mult; • Also possible: signal arr 3 : array (31 downto 0) of std_logic;

Ways to Replicate Hardware • How can we replicate VHDL functionality • We have

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

Generate Statements • Used to replicate concurrent constructs – Only valid outside of processes – Most useful for creating multiple component instantiations

if…, for… generate Example library ieee; use ieee_std_logic_1164. all; entity variable_shift_reg is generic( width

if…, for… generate Example library ieee; use ieee_std_logic_1164. all; entity variable_shift_reg is generic( 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 Example architecture structural of variable_shift_reg is component single_register_A port(clk, reset :

if…, for… generate Example architecture structural of variable_shift_reg is component single_register_A port(clk, reset : in std_logic; data_in : in std_logic; data_out : out std_logic ); end component; component single_register_B port(clk, reset 2 : in std_logic; data_in : in std_logic; data_out : out std_logic ); end component; begin …

if…, for… generate Example architecture structural of variable_shift_reg is [ component declarations on previous

if…, for… generate Example architecture 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); begin width_gen : for i in width-1 downto 0 generate -- connect inputs data_temp(0)(i) <= data_in(i); reset, -- 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 generate sr_gen : single_register_A port map ( clk =>clk, reset => data_temp(j)(i), 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 ( reset, reset 2 => reset, data_temp(j)(i), data_temp(j+1)(i)); end generate B_gen; end generate depth_gen; data_in => data_out => clk =>clk, reset => data_in => data_out =>

if…, for… generate Example • This example demonstrated how to construct a variable-width, variable-depth

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 –

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

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

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 Example library ieee; use ieee. std_logic_1164. all; entity test_and_gate is --

Simple Test Bench Example library 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_gate port(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”

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 :

Simple Test Bench Example … begin -- uut is “unit under test” uut : and_gate port map(A => A, B => B, X => X); process begin 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

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

Clocking Test Benches • • Often, the clock will be run independently of the input stimulus Consider: process begin clk <= ‘ 0’; wait for CLK_PERIOD; clk <= ‘ 1’; wait for CLK_PERIOD; end process; … process begin 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

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

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

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 –

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

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

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’

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

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, jswentwo@engmail. uwaterloo. ca