INTRODUCTION TO VHDL Slides by: Pedro Tomás Additional reading: - ADVANCED COMPUTER ARCHITECTURES ARQUITECTURAS AVANÇADAS DE COMPUTADORES (AAC)
Outline 2 Hardware Description Languages (HDL) VHDL Very High Speed Integrated Circuits (VHSIC) Hardware Description Language Typical VHDL structure General Tips and tricks Examples
What is VHDL 3 Hardware Description Language (HDL) Used to describe digital and mixed-signal systems such as Field-Programmable Gate Arrays (FPGAs) and Integrated Circuits (ICs) The advantage of such a language, regarding graphical editors, is that eases the creation process of complex digital circuits. However, one should have in mind that when programming In VHDL, you are actually designing digital circuits. Thus, a strong understanding of your code is more important than syntax and style.
VHDL Basics 4 In VHDL the description of a logic block is divided into two parts: Inputs and Outputs Entity defines the input and output ports (i.e., how the internal circuit interfaces with the outside world); A B C D Chip E Architecture: Defines the actual behavior/implementation/function of the component; A B Chip X E one entity can have more than one architectural definition. C D Y
Structure of a VHDL file 5 -- DECLARATION OF LIBRARIES library IEEE; use IEEE.std_logic_1164.all; -- IEEE Standard library use work.mylibrary.all; -- User defined library -- Definition of the component interface (input/output signals) entity <COMPONENTE_NAME> is port ( ); end <COMPONENTE_NAME>; -- Architecture definition (more than one type can co-exist) -- Just name the type whatever you want, e.g., behavior architecture <ARCHITECTURE_TYPE> of <COMPONENTE_NAME> is -- general declarations, such as signals (wires) and components -- used to define the architecture of this component Begin -- Description of the component architecture end <ARCHITECTURE_TYPE>;
VHDL Features 6 Case insensitive inputa, INPUTA and InputA refer to the same variable/signal/component Comments -- until end of line If you want to comment multiple lines, -- need to be put at the beginning of every single line Statements are terminated by ; Signal assignment: <= User defined names: letters, numbers, underscores ( _ ) start with a letter
Simple example 7 -- import std_logic from the IEEE library library IEEE; use IEEE.std_logic_1164.all; -- this is the entity entity ANDGATE is port ( A : in std_logic; B : in std_logic; S : out std_logic ); end ANDGATE; Library definitions, including signal type and some basic operation and functions Entity declaration, defines the interconnection to the outside world architecture Behavioral of ANDGATE is -- declare architecture specific types -- declare internal signals Begin -- describe architecture operation S <= A and B; end Behavioral; Specifies the ANDGATE operation
IEEE standard VHDL libraries 8 library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_textio.all; use IEEE.std_logic_arith.all; use IEEE.numeric_bit.all; use IEEE.numeric_std.all; use IEEE.std_logic_signed.all; use IEEE.std_logic_unsigned.all; use IEEE.math_real.all; use IEEE.math_complex.all; Provides enhanced signal types, e.g., std_ulogic, std_ulogic_vector, std_logic, std_logic_vector Provides interface to text files (usefull in simulations) Provides numerical computation (e.g., + (plus), - (minus), * (times)) on std_logic_vector, signed and unsigned types Provides computation on signed or unsigned arrays of type bit. Provides computation on signed or unsigned arrays of type std_logic. Provides signed computation on signals of type std_logic_vector. Provides unsigned computation on signals of type std_logic_vector. Provides numerical computation on type real. Provides numerical computation on type complex.
9 VHDL types: Standard type declarations type Bit is ('0', '1'); type Boolean is (false, true); type Integer is range --usually typical integer-- ; subtype Natural is Integer range 0 to Integer'high; subtype Positive is Integer range 1 to Integer'high; type Time is range --implementation defined-- ; units fs; -- femtosecond ps = 1000 fs; -- picosecond ns = 1000 ps; -- nanosecond us = 1000 ns; -- microsecond ms = 1000 us; -- millisecond sec = 1000 ms; -- second min = 60 sec ; -- minute hr = 60 min; -- hour end units;
VHDL types: IEEE type declarations 10 type std_logic is ( U, -- unitialized X, -- unknown 0, -- logic state 0 1, -- logic state 1 Z, -- high impedance W, -- weak signal (either 0 or 1) L, -- weak signal leaning 0 H, -- weak signal leaning 1 -, -- don t care ); type std_logic_vector is array (natural range <>) of std_logic;
11 VHDL types: Declaring new types Type declarations useful for state-machines: type mystate is (S1,S2,S3); Type declarations useful for counters: type count_int is range 0 to 35; Record type declarations: type InstructionType is record OPCODE : std_logic_vector(6 downto 0); DR : std_logic_vector(4 downto 0); AA : std_logic_vector(4 downto 0); BA : std_logic_vector(4 downto 0); end record;
VHDL signals: Declaring signals 12 signal X,Y,Z : std_logic; signal A : std_logic_vector(31 downto 0); -- A is a 32 bit bus signal B : std_logic_vector(15 downto 0); -- B is a 16 bit bus signal count_value : count_int; signal myinst : InstructionType;
13 VHDL architecture: Assignment and execution architecture behavior of my_circuit is -- signal declaration signal A, B, C : std_logic; signal vec1 : std_logic_vector(2 downto 0); signal vec2 : std_logic_vector(2 downto 0); begin A <= 0 ; -- assign logic value 0 B <= 1 ; -- assign logic value 1 C <= A; -- assign value of A to C Assignment can be moved around with no difference in the resulting operation Code is NOT sequential, but parallel vec1 <= 011 ; -- assign value of 3 vec2 <= A & B & C; -- assign the concatenation of A, B and C -- vec2 takes the values of 2. end behavior;
14 VHDL architecture: Assignment and execution -- 2-input AND gate S1 <= A and B; -- 3-input OR gate S2 <= A or B or C; -- XOR gate S3 <= A xor B; -- Combined gate S4 <= (A xor B) or (not (C and D)); -- Conditional assignment S5 <= 0 when A= 1 and B= 0 else 1 ; -- Conditional assignment ArrayValue <= 00 when State=S0 and ControlValue= 0000 else S1 xor S2 when State=S1 else S3 or S4 when State=S2 or State=S3 else S5 and S1;
VHDL architecture: Assignment and execution 15 -- n-bit registers (i.e., n parallel flip-flops) Dout <= Din when rising_edge(clk); -- n-bit register with enable (i.e., n parallel flip-flops) Dout <= Din when rising_edge(clk) and en= 1 ; -- n-bit register with enable and asynchronous reset Dout <= (n-1 downto 0=> 0 ) when reset= 1 else Din when rising_edge(clk) and en= 1 ; -- n-bit register with enable and asynchronous set Dout <= (others=> 1 ) when set= 1 else Din when rising_edge(clk) and en= 1 ; VHDL standard Description Alternative VHDL description CLK event and CLK= 1 Rising edge of signal CLK rising_edge(clk) CLK event and CLK= 0 Falling edge of signal CLK falling_edge(clk)
VHDL architecture: Processes 16 Advanced behaviour descriptions can be made by using the process construction <optional process name>: process(<sensitivity list>) <variable declarations> Begin <multiple assignments> <multiple assignments> <multiple assignments> Inside processes code execution is serialized end process;
VHDL architecture: Example of processes 17 Advanced behaviour descriptions can be made by using the process construction <optional process name>: process(<sensitivity list>) <variable declarations> begin <multiple assignments> end process; -- register with asynchronous reset process(clk,reset) begin if reset= 1 then Dout <= (others=> 0 ); elsif rising_edge(clk) then Dout <= Din; end if; end process; -- register with synchronous reset process(clk) begin if rising_edge(clk) then if reset= 1 then Dout <= (others=> 0 ); else Dout <= Din; end if; end if; end process;
VHDL architecture: Example of processes 18 Advanced behaviour descriptions can be made by using the process construction <optional process name>: process(<sensitivity list>) <variable declarations> begin <multiple assignments> end process; -- multiplier (return only the least significant bits) process(a,b) variable aux: std_logic_vector(2*n-1 downto 0); Begin aux := A*B; Dout <= aux(n-1 downto 0); end process; Variable assignment is made by using a different operator :=
VHDL architecture: Example of processes 19 Advanced behaviour descriptions can be made by using the process construction <optional process name>: process(<sensitivity list>) <variable declarations> begin <multiple assignments> end process; Processes are handy and very useful in special occasions, however You are not sure the compiler will understand exactly what you want In general, hardware is better described (area, performance, ) by avoiding the use of processes
20 First useful example Creating a register file
Creating a register file 21 Consider that one wants to design a processor Assume the first block to be designed is the register file 8-bit registers 4 register in total A Address A Data B Address B Data Write Address Write Enable Write Data AA A BA B Asynchronous read ports RF Register file DA WE DATA Synchronous write ports CLK Clock
22 Creating a register file: Declaring the interface -- import std_logic from the IEEE library library IEEE; use IEEE.std_logic_1164.all; -- this is the entity entity RegisterFile is port ( -- Output port A AA : in std_logic_vector(1 downto 0); A : out std_logic_vector(7 downto 0); -- Output port B BA : in std_logic_vector(1 downto 0); B : out std_logic_vector(7 downto 0); -- input port D DA : in std_logic_vector(1 downto 0); WE : in std_logic; Data : in std_logic_vector(7 downto 0) ); end RegisterFile; The last line does not need a ; architecture Behavioral of RegisterFile is
23 Creating a register file: Architecture Destination Address DA log 2 (d) Decoder 0 Address 1 2 Write Enable WE EN d-1 Data n D EN D EN D EN D EN R(d-1) R2 R1 R0 A Address A Data B Address B Data Write Address Write Enable Write Data Q Q Q Q AA MUX Operand A Address A AA A BA B Asynchronous read ports RF Register file DA WE DATA Synchronous write ports CLK Clock MUX Operand B Address B BA
24 Creating a register file: Declaring the internal signals Destination Address DA log 2 (d) Decoder 0 Address 1 2 Write Enable WE EN d-1 Data n D EN D EN D EN D EN R(d-1) R2 R1 R0 entity RegisterFile is port ( ); end RegisterFile; Q Reg3 Q Reg2 Q Reg1 Q Reg0 AA MUX Operand A Address A architecture Behavioral of RegisterFile is MUX B signal Reg0, Reg1, Reg2, Reg3 : std_logic_vector(7 downto 0); BA Operand B Address begin end Behavioral;
25 Creating a register file: Describing the architecture entity RegisterFile is port ( ); end RegisterFile; Destination Address DA Decoder Address architecture Behavioral of Write RegisterFile is Enable signal Reg0, Reg1, Reg2, Reg3 WE : std_logic_vector(7 EN d-1 downto 0); begin Data log 2 (d) n 0 1 2 A <= Reg0 when AA= 00 else Reg1 when AA= 01 else Reg2 when AA= 10 else Reg3 when AA= 11 ; B <= Reg0 when BA= 00 else Reg1 when BA= 01 else Reg2 when BA= 10 else Reg3 when BA= 11 ; end Behavioral; EN Q D R(d-1) Reg3 EN R2 Q D Reg2 EN R1 Q D Reg1 What happens when AA or BA is not one of those values? The synthesis tool will generate a latch EN R0 Q D Reg0 AA MUX MUX BA Operand A Address Operand B Address A B
26 Creating a register file: Describing the architecture entity RegisterFile is port ( ); end RegisterFile; Destination Address DA Decoder Address architecture Behavioral of Write RegisterFile is Enable signal Reg0, Reg1, Reg2, Reg3 WE : std_logic_vector(7 EN d-1 downto 0); begin Data log 2 (d) n 0 1 2 A <= Reg0 when AA= 00 else Reg1 when AA= 01 else Reg2 when AA= 10 else Reg3; B <= Reg0 when BA= 00 else Reg1 when BA= 01 else Reg2 when BA= 10 else Reg3; D EN R(d-1) Q Reg3 EN R2 Q D Reg2 EN R1 Q D Reg1 EN R0 Q D Reg0 AA MUX MUX BA Operand A Address Operand B Address A B end Behavioral; Avoids the use of a latch
27 Creating a register file: Describing the architecture architecture Behavioral of RegisterFile is signal Reg0, Reg1, Reg2, Reg3 : std_logic_vector(7 downto 0); begin A <= Reg0 when AA= 00 else Reg1 when AA= 01 else Reg2 when AA= 10 else Reg3; Destination Address DA log 2 (d) Decoder 0 Address 1 2 B <= Reg0 when BA= 00 else Reg1 when BA= 01 else Reg2 when BA= 10 else Reg3; Write Enable WE Data n EN d-1 D EN R(d-1) D EN R2 D EN R1 D EN R0 Reg0 <= Data when DA= 00 and rising_edge(clk); Reg1 <= Data when DA= 01 and rising_edge(clk); Reg2 <= Data when DA= 10 and rising_edge(clk); Reg3 <= Data when DA= 11 and rising_edge(clk); Q Q Q Q A MUX end Behavioral; MUX
28 Instantiating a VHDL Module: Declaring the interface -- import std_logic from the IEEE library library IEEE; use IEEE.std_logic_1164.all; -- this is the entity entity RegisterFile is port ( -- Output port A architecture Behavioral of OF_Stage is AA : in std_logic_vector(1 downto 0); A : out std_logic_vector(7 downto component 0); RegisterFile -- Output port B port ( BA : in std_logic_vector(1 downto 0); B : out std_logic_vector(7 downto 0); -- input port D DA : in std_logic_vector(1 downto 0); WE : in std_logic; Data : in std_logic_vector(7 downto 0) ); end RegisterFile; ); entity OF_Stage is port ( ); end OF_Stage; end component; architecture Behavioral of RegisterFile is AA : in std_logic_vector(1 downto 0); A : out std_logic_vector(7 downto 0); BA : in std_logic_vector(1 downto 0); B : out std_logic_vector(7 downto 0); DA : in std_logic_vector(1 downto 0); WE : in std_logic; Data : in std_logic_vector(7 downto 0) The last line does not need a ; Begin -- describe architecture operation end Behavioral;
29 Instantiating a VHDL Module: Using an instance -- import std_logic from the IEEE library library IEEE; use IEEE.std_logic_1164.all; -- this is the entity entity RegisterFile is port ( -- Output port A entity OF_Stage is port ( ); end OF_Stage; architecture Behavioral of OF_Stage is AA : in std_logic_vector(1 downto 0); A : out std_logic_vector(7 downto component 0); RegisterFile -- Output port B port (); BA : in std_logic_vector(1 downto end component; 0); B : out std_logic_vector(7 downto 0); -- input port D begin DA : in std_logic_vector(1 downto -- use 0); as many instances as you want WE : in std_logic; <required instance_name> : RegisterFile ( Data : in std_logic_vector(7 downto AA 0) => <signal declared in OF_Stage>, ); BA => <signal declared in OF_Stage>, A => <signal declared in OF_Stage>, end RegisterFile; B => open, -- leave signal unconnected architecture Behavioral of RegisterFile is DA => <signal declared need in a OF_Stage>, ; Once the component is declared, multiple instances can be instantiated The last line does not WE => <signal declared in OF_Stage>, Data => <signal declared in OF_Stage> ); end Behavioral;
30 Generics and for generates How do we scale the architecture considering: a) Number of registers b) Word size
VHDL example: Register file port map 31 A Address A Data B Address B Data Write Address Write Enable Write Data AA A BA B Asynchronous read ports RF Register file DA WE DATA Synchronous write ports CLK Clock entity RegisterFile is Generic ( REG_ADD_WIDTH : NATURAL := 5; REG_DATA_WIDTH : NATURAL := 32 ); Port ( CLK: in STD_LOGIC; AA : in STD_LOGIC_VECTOR (REG_ADD_WIDTH-1 downto 0); BA : in STD_LOGIC_VECTOR (REG_ADD_WIDTH-1 downto 0); DA : in STD_LOGIC_VECTOR (REG_ADD_WIDTH-1 downto 0); D : in STD_LOGIC_VECTOR (REG_DATA_WIDTH-1 downto 0); WE : in STD_LOGIC; A : out STD_LOGIC_VECTOR (REG_DATA_WIDTH-1 downto 0); B : out STD_LOGIC_VECTOR (REG_DATA_WIDTH-1 downto 0) ); end RegisterFile;
32 VHDL example: Register file architecture architecture Behavioral of RegisterFile is type RegisterTableType is array(2**reg_add_width-1 downto 0) of std_logic_vector(reg_data_width-1 downto 0); signal RegisterTable,RTaux : RegisterTableType; begin -- Asynchronous read process A <= RegisterTable(conv_integer(AA)); B <= RegisterTable(conv_integer(BA)); -- Register r[0] is always 0 RegisterTable(0) <= (others =>'0'); -- Synchronous write process to remaining registers (2**N 2^N) WriteUnit: for i in 1 to 2**REG_ADD_WIDTH-1 generate process(clk) begin if rising_edge(clk) then if WE='1' and conv_integer(da)=i then RegisterTable(i) <= D; end if; end if; end process; end generate; Requires: end Behavioral; use IEEE.STD_LOGIC_UNSIGNED.ALL;
33 Using VHDL Packages How do we scale the architecture considering: a) Number of registers b) Word size
VHDL Packages 34 -- Library declarations library IEEE; use IEEE.STD_LOGIC_1164.all; package <package_name> is -- Declare constants -- Declare types -- Declare functions and procedures end <package_name>; package body <package_name> is ---- Example 1 -- function <function_name> (signal <signal_name> : in <type_declaration> ) -- return <type_declaration> is -- variable <variable_name> : <type_declaration>; -- begin -- <variable_name> := <signal_name> xor <signal_name>; -- return <variable_name>; -- end <function_name>; end <package_name>;
VHDL Packages 35 -- Library declarations library IEEE; use IEEE.STD_LOGIC_1164.all; package processor_definitions is -- Declare constants constant word_width : integer := 32; constant reg_add_width : integer := 5; constant num_registers : integer := 32; -- Declare types type word is array (word_width-1 downto 0) of std_logic; type word_array is array (integer range <>) of word; type ID_EX_record is record A,B : word; AdderOperation : std_logic_vector(1 downto 0); end record; end processor_definitions; package body processor_definitions is end processor_definitions;
VHDL example: Register file port map 36 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use WORK.PROCESSOR_DEFINITIONS.ALL; entity RegisterFile is Port ( CLK: in STD_LOGIC; AA : in STD_LOGIC_VECTOR (REG_ADD_WIDTH-1 downto 0); BA : in STD_LOGIC_VECTOR (REG_ADD_WIDTH-1 downto 0); DA : in STD_LOGIC_VECTOR (REG_ADD_WIDTH-1 downto 0); D : in word; WE : in STD_LOGIC; A : out word; B : out word ); end RegisterFile;
VHDL example: Register file architecture 37 architecture Behavioral of RegisterFile is type RegisterTableType is word_array(2**reg_add_width-1 downto 0); signal RegisterTable,RTaux : RegisterTableType; begin -- Asynchronous read process A <= RegisterTable(conv_integer(AA)); B <= RegisterTable(conv_integer(BA)); -- Register r[0] is always 0 RegisterTable(0) <= (others =>'0'); -- Synchronous write process to remaining registers (2**N 2^N) WriteUnit: for i in 1 to 2**REG_ADD_WIDTH-1 generate process(clk) begin if rising_edge(clk) then if WE='1' and conv_integer(da)=i then RegisterTable(i) <= D; end if; end if; end process; end generate; end Behavioral;
38 Basic processor elements Logic unit Adder/subtractor Multiplier Simple Shift / Barrel Shifter Memories Instruction decoder
VHDL example: Logic unit 39 architecture Behavioral of RegisterFile is type RegisterTableType is word_array(2**reg_add_width-1 downto 0); signal RegisterTable,RTaux : RegisterTableType; begin -- Asynchronous read process A <= RegisterTable(conv_integer(AA)); B <= RegisterTable(conv_integer(BA)); -- Register r[0] is always 0 RegisterTable(0) <= (others =>'0'); -- Synchronous write process to remaining registers (2**N 2^N) WriteUnit: for i in 1 to 2**REG_ADD_WIDTH-1 generate process(clk) begin if rising_edge(clk) then if WE='1' and conv_integer(da)=i then RegisterTable(i) <= D; end if; end if; end process; end generate; end Behavioral;
VHDL architecture: Logic unit 40 OPER. SEL RESULT Operand A A S Result MOVB 00 S B AND 01 S A B Operand B B Logic Unit OR 10 S A B XOR 11 S A B Operation Select SEL Flags Flags (Z) S <= B when SEL= 00 else A and B when SEL= 01 else A or B when SEL= 10 else A xor B; -- all other undefined cases;
VHDL architecture: Arithmetic unit 41 OPER. SEL RESULT ADD 000 S A + 1 SUB 001 S A 1 INC DEC MULL MULH MULU MULUH 010 S A + B 011 S A B 100 S A * B (LSB, signed) 101 S A * B (MSB, signed) 110 S A * B (LSB, unsigned) 111 S A * B (MSB, unsigned) Operand A A S Result Operand B B Arithmetic Unit Operation Select SEL Flags Flags (Z,N,C,V)
VHDL architecture: Arithmetic unit 42 OPER. SEL RESULT ADDER (Option 1) ADD 000 S A + 1 SUB 001 S A 1 INC 010 S A + B Sum <= A + '1' when Sel(1 downto 0)="00" else A - '1' when Sel(1 downto 0)="01" else A + B when Sel(1 downto 0)="10" else DEC MULL MULH MULU MULUH 011 S A B 100 S A * B (LSB, signed) 101 S A * B (MSB, signed) 110 S A * B (LSB, unsigned) 111 S A * B (MSB, unsigned) A - B; Leads to the use of excessive functional units Operand A A S Result Operand B Operation Select B SEL Arithmetic Unit Flags Flags (Z,N,C,V) Requires: use IEEE.STD_LOGIC_SIGNED.ALL;
43 VHDL architecture: Arithmetic unit OPER. SEL RESULT ADDER (Option 2) ADD 000 S A + 1 SUB 001 S A 1 AddA <= A; INC DEC MULL MULH MULU MULUH 010 S A + B ugen: for i in 0 to word_width-1 generate 011 S A B AddB(i) <= (B(i) and Sel(1)) xor Sel(0); end generate; 100 S A * B (LSB, signed) 101 S A * B (MSB, signed) Cin <= Sel(1) xnor Sel(0); 110 S A * B (LSB, unsigned) Sum <= AddA + AddB + Cin; 111 S A * B (MSB, unsigned) Operand A A S Result Operand B Operation Select B SEL Arithmetic Unit Flags Flags (Z,N,C,V) Requires: use IEEE.STD_LOGIC_SIGNED.ALL;
44 VHDL architecture: Arithmetic unit OPER. SEL RESULT ADDER (Option 3) ADD 000 S A + 1 SUB 001 S A 1 INC 010 S A + B DEC 011 S A B AddA <= A; AddB <= (B and (word_width-1 downto 0=>Sel(1))) xor (word_width-1 downto 0=>Sel(0)); MULL MULH MULU MULUH 100 S A * B (LSB, signed) Cin <= Sel(1) xnor Sel(0); 101 S A * B (MSB, signed) Sum <= AddA + AddB + Cin; 110 S A * B (LSB, unsigned) 111 S A * B (MSB, unsigned) Operand A A S Result Operand B Operation Select B SEL Arithmetic Unit Flags Flags (Z,N,C,V) Requires: use IEEE.STD_LOGIC_SIGNED.ALL;
45 VHDL architecture: Arithmetic unit OPER. SEL RESULT ADD 000 S A + 1 SUB 001 S A 1 MULTIPLIER signal AuxA, AuxB : std_logic_vector(32 downto 0); signal Res : std_logic_vector(65 downto 0); INC 010 S A + B DEC MULL MULH MULU MULUH 011 S A B AuxA <= A(31) & A when Sel(1)='0' else '0' & A; 100 S A * B (LSB, signed) AuxB <= B(31) & B when Sel(1)='0' else '0' & B; 101 S A * B (MSB, signed) 110 S A * B (LSB, unsigned) Res <= AuxA * AuxB; 111 S A * B (MSB, unsigned) Prod <= Res(31 downto 0) when Sel(0)= 0 else Res(63 downto 32); Operand A A S Result Operand B Operation Select B SEL Arithmetic Unit Flags Flags (Z,N,C,V) Requires: use IEEE.STD_LOGIC_SIGNED.ALL;
VHDL architecture: Barrel Shifter 46 OPER. LSL LSR ASL ASR ROL ROR ROLC RORC SEL RESULT 000 S A << N 001 S A >> N 010 S A << N (arithmetic) 011 S A >> N (arithmetic) 100 S ROL(A,N) 101 S ROR(A,N) 110 S ROL(A,C,N) 111 S ROR(A,C,N)
VHDL architecture: Barrel Shifter 47 OPER. SEL RESULT LSL / ASL (1 times) LSL 000 S A << N 31 30 2 1 0 0 LSR 001 S A >> N ASL ASR ROL 010 S A << N (arithmetic) 011 S A >> N (arithmetic) 100 S ROL(A,N) C 31 30 2 1 0 Res <= A(width-2 downto 0) & 0; C <= A(width-1); ROR ROLC 101 S ROR(A,N) 110 S ROL(A,C,N) LSL / ASL (2 times) RORC 111 S ROR(A,C,N) 31 30 2 1 0 0 0 C 31 30 2 1 0 n <= conv_integer(sh); Res <= A(width-1-n downto 0) & (n-1 downto 0=> 0 ); C <= A(width-n);
VHDL architecture: Barrel Shifter 48 OPER. SEL RESULT LSR (1 times) LSL 000 S A << N 0 31 30 2 1 0 LSR 001 S A >> N ASL ASR ROL ROR ROLC RORC 010 S A << N (arithmetic) 011 S A >> N (arithmetic) 100 S ROL(A,N) 101 S ROR(A,N) 110 S ROL(A,C,N) 111 S ROR(A,C,N) 31 30 2 1 0 Res <= 0 & A(width-1 downto 1); C <= A(0); LSR (n times) Res <= (n-1 downto 0=> 0 ) & A(width-1 downto n); C C <= A(0);
VHDL architecture: Barrel Shifter 49 OPER. LSL LSR ASL ASR ROL ROR ROLC RORC SEL RESULT 000 S A << N 001 S A >> N 010 S A << N (arithmetic) 011 S A >> N (arithmetic) 100 S ROL(A,N) 101 S ROR(A,N) 110 S ROL(A,C,N) 111 S ROR(A,C,N) ASR (1 times) 31 30 2 1 0 31 30 2 1 0 C Res <= A(width-1) & A(width-1 downto 1); C <= A(0); ASR (n times) Res <= (n-1 downto 0=> A(width-1)) & A(width-1 downto n); C <= A(0);
VHDL architecture: Barrel Shifter 50 OPER. SEL RESULT ROL ROR ROLC RORC 100 S ROL(A,N) 101 S ROR(A,N) 110 S ROL(A,C,N) 111 S ROR(A,C,N) 31 30 2 1 0 31 30 2 1 0 31 30 2 1 0 C Res <= A(n-1 downto 0) & A(width-1 downto n) C <= A(n-1);
VHDL architecture: Barrel Shifter 51 OPER. SEL RESULT ROL ROR ROLC RORC 100 S ROL(A,N) 101 S ROR(A,N) 110 S ROL(A,C,N) 111 S ROR(A,C,N) Cr 31 30 2 1 0 31 30 2 1 0 C 31 30 2 1 0 Res <= A(width-1-n downto 0) & Cr & A(width-1 downto n) C <= A(width-n);
52 VHDL architecture: Multi-mode Barrel Shifter OPER. LSL LSR ASL ASR ROL ROR ROLC RORC SEL RESULT 000 S A << N 001 S A >> N 010 S A << N (arithmetic) 011 S A >> N (arithmetic) 100 S ROL(A,N) 101 S ROR(A,N) 110 S ROL(A,C,N) 111 S ROR(A,C,N) Aux <= A & (width-1 downto 0=> 0 ) A & A A & Cr & A(width-1 downto 1); when sel(2)= 0 else when sel(1)= 0 else Res <= Aux(2*width-1-n downto width-n); C <= A(2*width-n);
53 VHDL architecture: Dual Port Memory library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity DualPortMemory is Generic ( ADDR_SIZE : positive := 8 ); Port ( CLK_A : in STD_LOGIC; WE_A : in STD_LOGIC; Addr_A : in STD_LOGIC_VECTOR (ADDR_SIZE-1 downto 0); DI_A : in STD_LOGIC_VECTOR (31 downto 0); DO_A : out STD_LOGIC_VECTOR (31 downto 0); ); end DualPortMemory; CLK_B : in STD_LOGIC; WE_B : in STD_LOGIC; Addr_B : in STD_LOGIC_VECTOR (ADDR_SIZE-1 downto 0); DI_B : in STD_LOGIC_VECTOR (31 downto 0); DO_B : out STD_LOGIC_VECTOR (31 downto 0) architecture Behavioral of DualPortMemory is begin end Behavioral;
VHDL architecture: Dual Port Memory 54 entity DualPortMemory is end DualPortMemory; architecture Behavioral of DualPortMemory is -- declare a type of matrix of words the memory type MEM_TYPE is array (0 to (2**ADDR_SIZE)-1) of STD_LOGIC_VECTOR(31 downto 0); -- declare a constant with the memory initial value constant InitValue : MEM_TYPE := ( 0 => "00100000001000001111111111111111", -- Binary value for address 0 1 => "00100100010000011111111111111101", 3 => "00111100011000001111111111111100", 4 => "000011" & "00100" & "00011" & "00010" & "00000000000", 5 => "000001" & "00101" & "00100" & "00010" & "00000000000", -- value for address 5 17 => X"000001AB", -- Hexadecimal value for address 17 others => x"00000000"); -- value for all addresses not previously defined -- declare the signal correspondent to the RAM memory -- and define an initial value shared variable myram : MEM_TYPE := InitValue0; begin end Behavioral;
VHDL architecture: Dual Port Memory 55 architecture Behavioral of DualPortMemory is begin -- architecture for port A process (CLK_A) begin if rising_edge(clk_a) then if WE_A='1' then RAM(conv_integer(Addr_A)) := DI_A; end if; DO_A <= RAM(conv_integer(Addr_A)); end if; end process; -- architecture for port B process (CLK_B) begin if rising_edge (CLK_B) then if WE_B='1' then RAM(conv_integer(Addr_B)) := DI_B; end if; DO_B <= RAM(conv_integer(Addr_B)); end if; end process; To ensure that the synthesis tool infers a Block RAM, the memory reading ports must be synchronous end Behavioral;
56 Testbenches Creating a stimulus generator to validate the described architecture
Circuit validation 57 To fully validate the correct behavior of the circuit, it is necessary to test the circuit output value for all combinations of: Input signals Circuit internal state In practice this means describing a signal generator capable of reproducing all combinations of such values (i.e., of the truth table)
Description of a Testbench 58 Similar to all other VHDL modules, except that: It does not require the description of any input/output ports library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity my_testbench is end my_testbench; architecture Behavioral of my_testbench is Declare the VHDL module(s) to be tested and all required signals begin end Behavioral; Instantiate all VHDL module(s) to be tested and describe Generate the signals that allow you to test the VHDL module
Typical testbench signals 59 Clock signal with period of 50 ns process begin clk <= 0 ; wait for 25 ns; clk <= 1 ; wait for 25 ns; end process; Counter with period of 10 ns process begin code <= code + 1; wait for 10 ns; end process;
Typical testbench signals 60 Other cases process begin -- state the value signals wait for clk_period; -- state the value of the same or other signals wait for 1.5*clk_period; -- state the value of the same or other signals wait for clk_period/5; wait; -- forever end process;