Topic 3: VHDL José Nelson Amaral Paul Berube Paras Mehta CMPUT329 - Fall 2003 Topic 3: VHDL José Nelson Amaral Paul Berube Paras Mehta
Reading Assigment Chapter 4: Sections 4.7.0 to 4.7.4
PCSource TargetWrite 1 2 M u x Target 32 4 32 26 PcWrite MemRead 1 2 M u x Target 32 4 Conc/ Shift left 2 32 26 PcWrite MemRead RegDst MemWrite ALUSelA IorD IRWrite MemtoReg RegWrite PC M u x 1 M u x 1 I[25-21] Read address Read register 1 Instruction [31-26] I[20-16] Read data 1 Read register 2 Zero Memory Write address M u x 1 ALUSelB ALU result Instruction [25-0] Write register Read data 2 MemData M u x 1 2 3 ALU Write data Instruction register Write data 4 ALU control ALUOp [15-11] 1 M u x Registers 32 I[15-0] Sign ext. Shift left 2 16
Motivating Example: Arithmetic Logic Unit Important part of datapath in CPU architecture Like all hardware, can be designed in VHDL Useful example because it can be easily decomposed operand1 alu_result ALU operand2 ALU operation opcode
Motivating Example: Arithmetic Logic Unit Set of operations: operand1 alu_result ALU Logic AND OR XOR NOT operand2 ALU operation opcode Arithmetic add subtract multiply negate
ALU Structure Arithmetic Module Logic arithmetic operation MUX logic 2 arith_result logic_result operand1 operand2 alu_result 1 opcode selection
ALU Structure ALU Arithmetic Module Logic MUX 2 1 selection arith_result logic_result operand1 operand2 alu_result 2 opcode 1 selection
VHSIC Hardware Description Language Very High Speed Integrated Circuit VHDL VHSIC Hardware Description Language Very High Speed Integrated Circuit Development sponsored by the IEEE and the US DoD in mid-1980s Based on ADA (somehow similar to Pascal)
VHDL Features Designs organized hierarchically Each design element has: A well-defined interface A precise behavioral specification using either: algorithmic description hardware structural description Models concurrency, timing, and clocking: Handles asynchronous and synchronous circuits Designs can be simulated
VHDL Hierarchical Program Structure architecture A entity A entity is a “wrapper” with “hooks” for an architecture A higher level architecture instantiates lower level entities. architecture B entity B architecture C entity C architecture D entity D architecture E entity E architecture F entity F
ALU Structural Picture alu_arch alu arithmetic_module logic_module mux_arch mux Multiplexor arithmetic_module_arch logic_module_arch Arithmetic Functionality Logic Functionality
VHDL Program File Structure text file (e.g., mydesign.vhd) entity declaration architecture definition
Entity Declaration Syntax: out inout buffer Modes: in Final signal has entity entity-name is port ( signal-name: mode signal-type; ... signal-name: mode signal-type); end entity-name; Syntax: Final signal has no semi-colon Built-in or user-defined
Example – ALU Syntax: ALU entity entity-name is port ( operand1 signal-name: mode signal-type; ... signal-name: mode signal-type); end entity-name; Syntax: operand1 alu_result ALU operand2 opcode entity alu is port( operand1: in std_logic_vector(7 downto 0); operand2: in std_logic_vector(7 downto 0); opcode: in std_logic_vector(2 downto 0); alu_result: out std_logic_vector(7 downto 0)); end alu;
ALU Structure How do we describe this structure? 2 MUX Arithmetic Module Logic arith_result logic_result operand1 operand2 First we need to describe these components! alu_result 1 opcode
Structural VHDL – Component Declaration A component must be declared before it can be used declaration before architecture 'begin' statement component component-name port( signal-name: signal-type; . . . ); end component; Syntax:
Arithmetic Module Logic Module MUX operation operandA result inputA operandB output Logic Module operation result inputB operandA selection operandB component arithmetic_module port( operation: in std_logic_vector (1 downto 0); operandA: in std_logic_vector (7 downto 0); operandB: in std_logic_vector (7 downto 0); result: out std_logic_vector (7 downto 0); ); end component;
Arithmetic Module Logic Module MUX operation operandA result inputA operandB output Logic Module operation result inputB operandA selection operandB component logic_module port( operation: in std_logic_vector (1 downto 0); operandA: in std_logic_vector (7 downto 0); operandB: in std_logic_vector (7 downto 0); result: out std_logic_vector (7 downto 0); ); end component;
Arithmetic Module Logic Module MUX operation operandA result inputA operandB output Logic Module operation result inputB operandA selection operandB component mux port( selection: in std_logic; inputA: in std_logic_vector (7 downto 0); inputB: in std_logic_vector (7 downto 0); output: out std_logic_vector (7 downto 0); ); end component;
Signals In VHDL, signals: represent wires in hardware are assigned to and read from (like variables in traditional programming languages) signal signal-name : signal-type; signal signal-name : signal-type := initial-value; Declarations: signal-name <= constant-value; signal-name <= signal-name; signal-name <= expression; Assignments:
signal arith_result : std_logic_vector(7 downto 0); Arithmetic Module MUX operation arith_result operandA result inputA operandB alu_result output Logic Module operation logic_result result inputB operandA selection operandB signal arith_result : std_logic_vector(7 downto 0); signal logic_result : std_logic_vector(7 downto 0);
Arithmetic Module Logic Module MUX arith_result alu_result operation arith_result operandA result inputA operandB alu_result output Logic Module operation logic_result result inputB architecture alu_arch of alu is • • • begin Inst_alu_arith: arithmetic_module Port Map ( result => arith_result ); Inst_alu_mux: mux inputA => arith_result, inputB => logic_result, output => alu_result end alu_arch operandA selection operandB
ALU Structure How do we connect the inputs and output of the ALU to the modules? 2 MUX Arithmetic Module Logic arith_result logic_result operand1 operand2 alu_result 1 opcode Though the Port Maps in the component instantiations.
Arithmetic Module Logic Module MUX opcode(1-0) operand1 arith_result operation operand1 arith_result operandA result inputA operand2 operandB alu_result output Logic Module opcode(1-0) operation logic_result result inputB operand1 operandA selection operand2 operandB opcode(2) architecture alu_struct_arch of alu is • • • begin Inst_alu_arith: arithmetic_module Port Map ( operation => opcode(1 downto 0) operandA => operand1 operandB => operand2 result => arith_result ); • • • Inst_logic_arith: logic_module Port Map ( operation => opcode(1 downto 0) operandA => operand1 operandB => operand2 result => arith_result );
Arithmetic Module Logic Module MUX opcode(1-0) operand1 arith_result operation operand1 arith_result operandA result inputA operand2 operandB alu_result output Logic Module opcode(1-0) operation logic_result result inputB operand1 operandA selection operand2 operandB opcode(2) • • • Inst_alu_mux: mux Port Map ( selection => opcode(2); inputA => arith_result, inputB => logic_result, output => alu_result ); end alu_struct_arch
If-Then-Else Statements Used for conditional behaviour if condition then statements elsif condition then ... else end if; Syntax: if signal_1 = '1' then signal_2 <= signal_3; else signal_2 <= signal_4; end if; Example:
Processes Processes are used in VHDL to separate behaviours within an architecture sensitivity list indicates signals the process should respond to if-then-else structure only used within process Process-Name: process (sensitivity-list) begin statements end process; Syntax:
Process example: Defining the function of the MUX Functionally, the multiplexor outputs either inputA or inputB, depending on the value of the selection. Therefore the mux is sensitive to all its inputs. architecture mux_arch of mux is begin SelectionProcess: process (inputA,inputB,selection) if selection = ’0' then output <= inputA; else output <= inputB; end if; end process; end mux_arch;
MUX entity Although MUX is defined as a component in the ALU, it must be also defined as an independent entity so that it can be reused in other designs. entity mux is Port( selection: in std_logic; inputA: in std_logic_vector (7 downto 0); inputB: in std_logic_vector (7 downto 0); output: out std_logic_vector (7 downto 0); ); end mux;
Constants Provide constant values for settings, etc. used as in other programming languages constant constant-name : constant-type := value Example: constant ADDR_MAX: integer := 16; constant INCLUDE_BUF: boolean := true;
Constant Example: Operations in arith. mod. architecture arithmetic_module_arch of arithmetic_module is architecture alu_arith_arch of alu_arith is -- declare math opcode constants constant ADD : std_logic_vector(1 downto 0) := "00"; constant SUB : std_logic_vector(1 downto 0) := "01"; constant MUL : std_logic_vector(1 downto 0) := "10"; constant NEG : std_logic_vector(1 downto 0) := "11"; begin • • • end arithmetic_module_arch; constant constant-name : constant-type := value
Modifying Existing Code So far we coded the ALU to operate with 8 bit operands and result. If now we want an ALU to operate with 16 bit operands and results, we will have to change the code in many places. VHDL provide Generics and Generic Statements that can be used to build much more flexible designs.
Generic Generics are used in entity declaration define constants in the architecture Syntax: entity entity-name generic( generic-name: type := default-value; . . . ); port( end entity; Undefined generics (in structural designs) take this value
Complete Arithmetic Module Entity Definition entity arithmetic_module is Generic ( OPERAND_WIDTH : integer := 8 ); port( operation: in std_logic_vector (OPERAND_WIDTH-1 downto 0); operandA: in std_logic_vector (OPERAND_WIDTH-1 downto 0); operandB: in std_logic_vector (OPERAND_WIDTH-1 downto 0); result: out std_logic_vector (OPERAND_WIDTH-1 downto 0); end arithmetic_module;
Case Statements Used to enumerate cases of expression Example: Syntax: case signal_1 is when “00” => signal_2 <= '1'; signal_3 <= '0'; when “10” => signal_2 <= '0'; signal_3 <= '1'; when others => end case; Example: case condition is when value => statements . . . when others => end case Syntax:
Case Statement Example: Function of Arithmetic Mod. architecture arithmetic_module_arch of arithmetic_module is -- multiplication returns a result with length = sum of lengths of operands signal ext_result : std_logic_vector(OPERAND_WIDTH*2-1 downto 0); begin EVAL_ARITH: process(operandA, operandB, operation) case operation is when ADD => ext_result(OPERAND_WIDTH-1 downto 0) <= operand1 + operand2; when SUB => ext_result(OPERAND_WIDTH-1 downto 0) <= operand1 - operand2; when MUL => ext_result <= operand1 * operand2; when NEG => ext_result(OPERAND_WIDTH-1 downto 0) <= ZERO - operand1; -- cover all cases not explicitly stated in case statement when others => ext_result <= (others => '0'); end case; end process EVAL_ARITH; end arithmetic_module_arch;
Makes all values 256 bits wide Generalizing Code architecture alu_struct_arch of alu_struct is component alu_mux generic ( DATA_WIDTH: integer; ); port ( . . . ); end component; . . . begin inst_alu_mux : alu_mux generic map( DATA_WIDTH => 256 ) port map ( . . . ); end architecture; Example: Makes all values 256 bits wide
Generate one piece of code for each element in range Generalizing Code Generate Statements used to conditionally write code in architectures: can generate parallel code or decide whether or not to generate code Generate one piece of code for each element in range Syntax: generate-name: for identifier in range generate statements . . . end generate; generate name: if condition generate Generate code only if condition holds
Generalizing Code Example: 16 x n RAM existing component for 16 entry x 1 bit RAM want to build multi-bit RAM 1 . 14 15 1 . 14 15 n-1 n-2 . . . One entry n bits wide One-bit wide
Generalizing Code Example: 16 x n RAM Corresponds to n signal write_data : std_logic_vector(DATA_WIDTH-1 downto 0); signal read_data : std_logic_vector(DATA_WIDTH-1 downto 0); signal addr_sig: std_logic_vector(ADDRESS_WIDTH-1 downto 0); RamGen: for i in 0 to DATA_WIDTH-1 generate RamInst: Ram16x1 port map( web => web_sig, clk => clk, data_in => write_data(i), data_out => read_data(i), addr => addr_sig ); end generate; 16 entries => 4 bits each bit in separate RAM
VHDL Types IEEE Defined Types: std_logic used to define signals in hardware std_logic_vector used to define buses (collection of multiple signals) std_logic std_logic_vector signal signal-name: std_logic; signal bus-name: std_logic_vector (start to end); signal bus-name: std_logic_vector (start downto end);
VHDL Types Useful Built-in Types integer: defined as in other languages, though its width is inferred boolean: as in other languages signal signal-name: boolean := true; signal int-name: integer range start to end;