1 / 54

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

nia
Download Presentation

ASIC 120: Digital Systems and Standard-Cell ASIC Design

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ASIC 120: Digital Systems and Standard-Cell ASIC Design Tutorial 3: Intermediate VHDL November 9, 2005

  2. 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.

  3. 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

  4. 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

  5. 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

  6. std_logic_1164 Resolution Table

  7. 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

  8. std_logic_1164 example • Consider: caseSelis when“00”  => X <= B; when“10”  => X <= A; when“1-”  => X <= D; whenothers  => X <= C; endcase;

  9. 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 caseSelis when“00”  => X <= B; when“10”  => X <= A; whenothers  => X <= C; endcase;

  10. 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

  11. 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

  12. 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

  13. Arithmetic Data Types: std_logic_arith • Obfuscated • Use numeric_std instead

  14. 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;

  15. 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

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

  17. 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:

  18. 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

  19. 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 data_q(i) <= data_in(i); end if; end loop; end if; end process; data_out <= data_q; end behavioural;

  20. Modular VHDL • Using the previous example, what if I want 16 registers? • modify the existing code • copy and paste • components

  21. 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

  22. 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_regs1 : eight_regs port map ( clock, data_in(15 downto 8), load(15 downto 8), data_out(15 downto 8)); -- named eight_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;

  23. 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])

  24. 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 data_q(i) <= data_in(i); end if; end loop; end if; end process; data_out <= data_q; end behavioural;

  25. 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 data_q(i) <= data_in(i); end if; end loop; end if; end process; data_out <= data_q; end behavioural;

  26. 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;

  27. Generics • Note that the data type of the bus_width generic is integer, not signed or unsigned • in this case it’s okay

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

  29. 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

  30. 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_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 test1;

  31. 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

  32. 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;

  33. 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

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

  35. 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;

  36. 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, reset2 : in std_logic; data_in : in std_logic; data_out : out std_logic ); end component; begin …

  37. 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); -- 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 => 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 outputs data_out(i) <= data_temp(depth)(i); end generate width_gen; end structural;

  38. 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

  39. 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

  40. 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

  41. 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

  42. 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;

  43. 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

  44. 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;

  45. 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

  46. 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;

  47. Clocking Test Benches • In this way, we can co-ordinate input stimulus across multiple units under test

  48. More on Test Benches • Another useful test bench tool in VHDL is file input and output • obviously not synthesizable

  49. 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

  50. 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

More Related