--- Notes and Demos for LSU EE 4702-1 Spring 2001

--- VHDL in 120 min;

 --- VHDL Standards

 -- This set describes VHDL 93, newer standard.


---  VHDL Basics

 --- Identifiers

 --  Use characters a-z A-Z 0-9 _
 --  Case insensitive.  (foo, FOO, Foo, FoO, are all the same.)

--- Expressions

-- Operators, from weakest to strongest binding.

-- Logical:    and, or, xor, nand, nor, xnor
-- Relational: =, <, >, <=, >=, /=, 
-- Shift:      sll (shift left logical), sra, ... rol (rotate left), ror
-- Adding:     +, -, & (array concatenation)
-- Multiply:   *, /, mod (modulus), rem (remainder)
-- Misc:       ** (exponentiation), abs, not (logical not)
 
-- Parenthesis must be used to group different logical operators:

x:= ( a and b ) or ( c and d ); -- Parenthesis needed regardless of grouping.
x:=  a and b or c and d ; -- Syntax error.

--- Types

 --- Scalar Types:  integer, real, physical, enumeration

 -- integer: At least 32 bits. (Implementation dependent.)
 -- Subtypes include natural (non-negative numbers) and positive (+ numbers).

 -- physical: An integer coupled with a unit.
 --
 -- Set of permissible units defined with type.
 --
 -- Subtype includes time.
 -- Units for time: fs, ps, ns, us, ms, sec, min, hr
 -- Example of use:
 t := 3 ms + 1 ms + t1;
 a <= x and y after 5 ns;

 -- enumerated: A set of values defined for type.
 --
 -- Examples of enumerated types:

 -- This is built in to the language.
 -- type bit is ('0','1')  -- Values of bit type are '0' or '1'.
 
 -- std_logic: -- Used for logic, included in the std_logic_1164 package.
 TYPE std_logic IS ( 'U',  -- Uninitialized
                      'X',  -- Forcing  Unknown
                      '0',  -- Forcing  0
                      '1',  -- Forcing  1
                      'Z',  -- High Impedance   
                      'W',  -- Weak     Unknown
                      'L',  -- Weak     0       
                      'H',  -- Weak     1       
                      '-'   -- Don't care
                      );
 
  signal my_sig: std_logic;
  -- [snip]
  my_sig <= '1';  -- Can't say: my_sig <= 1;
  
  -- A set of states that might be defined for a particular part:
 type state_t is (st_0N, st_0P, st_0C, st_1N, st_1P);
 -- Example:
  variable state: state_t;
  -- [snip]
  if state = st_0C
  then do_stuff;
  else do_other_stuff; end if;
  

  -- Each items between parenthesis called /enumeration literals/,
  -- and must be character constants (single-quoted characters)
  -- or valid identifiers.
  

 --- Composite Types: Arrays and Records

 -- Arrays

 -- Number of dimensions is unlimited.
 -- Elements can be any type (I think).

 -- Two Steps to Declaring an Array Object
 -- 1) Declare an array type (if one is not already defined).
 -- 2) Declare the variable.

 -- Declaring an array type:

 -- Declaring a 10-element array type.  
 type A_Table is array ( 0 to 9 ) of integer;
 -- Declaring an arbitrary size array type.  
 type Int_Array is array ( range <> ) of integer;
 -- The following declaration is part of the stdlogic_1164 library.
 TYPE std_ulogic_vector IS ARRAY ( NATURAL RANGE <> ) OF std_ulogic;

 -- Declaring an array object.
  
 variable table_a: A_Table;
 signal  table_b: A_Table;
 constant  table_c: A_Table;
 variable table_d: Int_Array ( 0 to 999 );
 signal count: std_ulogic_vector ( 31 downto 0 );

 

--- Object Types

-- Commonly used declarable objects:  variable, signal, constant.

-- Objects hold values, differ in how value changed and can be used.  

-- signal:   Values assigned at specified times. 
-- variable: Values assigned only in procedural code.
-- constant: Value assigned once, at simulation start.

-- Signals

-- Assigned using: <=  
-- Roughly akin to Verilog wires, but can be assigned in procedural code.
-- Can be used to interconnect entities.
-- Assignments occur at specified time, by default at the end of
-- current time step.  
  
 signal sig1: std_logic_vector (7 downto 0);
 signal sig2, sig3, sig4: std_logic:= '0';

 sig2 <= sig3 and sig4;
 -- This gets older value of sig2, not the one assigned above.  
 sig3 <= sig2;  
 sig2 <= sig3 and sig4 after 3 ms;
 sig3 <= sig3 and sig4 after 7 ns;
 clk <= '0', '1' after 1 ns, '0' after 2 ns;
 clk2 <= '0';
 clk2 <= '1' after 1 ns;
 clk2 <= '0' after 2 ns;

 -- Variables

 -- Assigned using: :=
 -- Can only be assigned in procedural code (other than initialization).
 -- Assignments occur immediately.
 -- Ordinary type can only be declared in a process and used in that process.
 -- Shared type declared in an architecture, result of
 -- simultaneous assignments not defined.

 var1 := ( sig3 and sig4 and sig5 ) or another_signal;

 variable var2: integer;
 variable var3: real;

 var2:= 5;
 var4:= var2;  -- This gets the 5.  
 var2:= 16#ff#;
 var3:= 16#ff.1fa#;
 

--- Entities and Architectures

 -- Entity defines ports and generics (parameters) of part.
  
 entity bfa is
    generic( d: integer );
    port( a, b, cin: in std_logic;
           sum, cout: out std_logic);
 end bfa;

 -- Architecture defines behavior and structure of part.
 -- An entity can have multiple architectures.
 
 architecture a1 of bfa is
  -- Signal, component, procedure, and function declarations go here.

   
 begin
    -- Part instantiations (sort of) which include port mapping go here.
    -- Concurrent assignments statements go here.
    sum <= a xor b xor cin;
    cout <= ( a and b ) or ( b and cin ) or ( a and cin );
     -- Processes go here.

 end a1;

 --- More examples of entity and architecture.

entity counter is

  -- Declare Generics (Like Verilog parameters)

  generic( d: integer:= 1 );

  -- Declare Ports
  
  port( c: in std_logic_vector ( 7 downto 0 );
        clk: out std_logic );

  
end entity;

architecture a1 of counter is

  -- Declare Signals and Components 
 signal foo: std_logic := '0';
 constant c1: integer := 14;

  -- Component connections, signals, and behavioral code below.
begin

  -- Executed once.
  foo <= '1' after 2 ms, '0' after 4 ms;

  -- Executed whenever a or b changes.
  bar <= a and b after 3 ms;

  -- Executed whenver x or y changes.
  process(x,y)
  begin

    foo <= bar;
    
  end;

  -- Infinite loop
  process
  begin

    wait for 3 ns;

    wait on x;

    wait until foo = bar;

    wait until rising_edge(y);
    
  end
    
end architecture a1;