ECE 332 Digital Electronics and Logic Design Lab Lab 5 VHDL Design Styles Testbenches Concurrent Statements & Adders VHDL Design Styles VHDL Design Styles BEHAVIORAL DATAFLOW “concurrent” statements STRUCTURAL components and interconnects SYTHESIZABLE NONSYNTHESIZABLE “sequential” statements • State machines • Registers • Test Benches • Modeling IP VHDL subset most suitable for synthesis ECE 332 George Mason University XOR3 Example ECE 332 George Mason University Entity XOR3 (same for all architectures) LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY xor3 IS PORT( A : IN B : IN C : IN Result ); END xor3; ECE 332 STD_LOGIC; STD_LOGIC; STD_LOGIC; : OUT STD_LOGIC George Mason University Dataflow Architecture ARCHITECTURE dataflow OF xor3 IS SIGNAL U1_out: STD_LOGIC; BEGIN U1_out <= A XOR B; Result <= U1_out XOR C; END dataflow; U1_out ECE 332 George Mason University Dataflow Description • Describes how data moves through the system and the various processing steps. – Dataflow uses series of concurrent statements to realize logic. – Dataflow is most useful style when series of Boolean equations can represent a logic used to implement simple combinational logic • Concurrent statements are evaluated at the same time; thus, the order of these statements doesn’t matter – This is not true for sequential/behavioral statements This order… U1_out <= A XOR B; Result <= U1_out XOR C; Is the same as this order… Result <= U1_out XOR C; U1_out <= A XOR B; ECE 332 George Mason University Structural Architecture (XOR3 gate) ARCHITECTURE structural OF xor3 IS SIGNAL U1_OUT: STD_LOGIC; COMPONENT xor2 IS PORT( I1 : IN STD_LOGIC; I2 : IN STD_LOGIC; Y : OUT STD_LOGIC ); END COMPONENT; BEGIN U1: xor2 PORT MAP ( I1 I2 Y U2: xor2 PORT MAP ( I1 I2 Y END structural; ECE 332 => A, => B, => U1_OUT); => U1_OUT, => C, => Result); A B XOR3 Result C I1 I2 Y XOR2 U1_OUT A B C RESULT George Mason University Component and Instantiation • Named association connectivity (recommended) COMPONENT xor2 IS PORT( I1 : IN STD_LOGIC; I2 : IN STD_LOGIC; Y : OUT STD_LOGIC ); END COMPONENT; BEGIN U1: xor2 PORT MAP ( I1 => A, I2 => B, Y => U1_OUT); ... COMPONENT PORT NAME ECE 332 LOCAL WIRE George Mason University Component and Instantiation • Positional association connectivity (not recommended) COMPONENT xor2 IS PORT( I1 : IN STD_LOGIC; I2 : IN STD_LOGIC; Y : OUT STD_LOGIC ); END COMPONENT; BEGIN U1: xor2 PORT MAP (A, B, U1_OUT); ... ECE 332 George Mason University Structural Description • Structural design is the simplest to understand. This style is the closest to schematic capture and utilizes simple building blocks to compose logic functions. • Components are interconnected in a hierarchical manner. • Structural descriptions may connect simple gates or complex, abstract components. • Structural style is useful when expressing a design that is naturally composed of sub-blocks. ECE 332 George Mason University Behavioral Architecture (XOR3 gate) ARCHITECTURE behavioral OF xor3 IS BEGIN PROCESS (A,B,C) BEGIN IF ((A XOR B XOR C) = '1') THEN Result <= '1'; ELSE Result <= '0'; END IF; END PROCESS; END behavioral; ECE 332 George Mason University Behavioral Description • It accurately models what happens on the inputs and outputs of the black box (no matter what is inside and how it works). • This style uses PROCESS statements in VHDL. • Statements are executed in sequence in a process statement order of code matters! ECE 332 George Mason University Single Wire Versus Bus SIGNAL a : STD_LOGIC; a 1 wire SIGNAL b : STD_LOGIC_VECTOR(7 downto 0); b 8 ECE 332 bus George Mason University Standard Logic Vectors SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL a: b: c: d: e: f: STD_LOGIC; STD_LOGIC_VECTOR(3 DOWNTO 0); STD_LOGIC_VECTOR(3 DOWNTO 0); STD_LOGIC_VECTOR(7 DOWNTO 0); STD_LOGIC_VECTOR(15 DOWNTO 0); STD_LOGIC_VECTOR(8 DOWNTO 0); ………. a b c d e f <= <= <= <= <= <= ECE 332 '1'; "0000"; B"0000"; "0110_0111"; X"AF67"; O"723"; ------ Binary base Binary base You can use Hexadecimal Octal base assumed by default explicitly specified '_' to increase readability base George Mason University Single versus Double Quote • Use single quote to hold a single bit signal – a <= '0', a <='Z' • Use double quote to hold a multi-bit signal – b <= "00", b <= "11" ECE 332 George Mason University Testbenches ECE 332 George Mason University Testbench Block Diagram Testbench Processes Generating Stimuli Design Under Test (DUT) Observed Outputs ECE 332 George Mason University Testbench Defined • A testbench applies stimuli (drives the inputs) to the Design Under Test (DUT) and (optionally) verifies expected outputs. • The results can be viewed in a waveform window or written to a file. • Since a testbench is written in VHDL, it is not restricted to a single simulation tool (portability). • The same testbench can be easily adapted to test different implementations (i.e. different architectures) of the same design. ECE 332 George Mason University Testbench Anatomy ENTITY tb IS --TB entity has no ports END tb; ARCHITECTURE arch_tb OF tb IS --Local signals and constants COMPONENT TestComp -- All Design Under Test component declarations PORT ( ); END COMPONENT; ----------------------------------------------------BEGIN DUT:TestComp PORT MAP( -- Instantiations of DUTs ); testSequence: PROCESS -- Input stimuli END PROCESS; END arch_tb; ECE 332 George Mason University Testbench for XOR3 LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY xor3_tb IS END xor3_tb; ARCHITECTURE xor3_tb_architecture OF xor3_tb IS -- Component declaration of the tested unit COMPONENT xor3 PORT( A : IN STD_LOGIC; B : IN STD_LOGIC; C : IN STD_LOGIC; Result : OUT STD_LOGIC ); END COMPONENT; -- Stimulus signals - signals mapped to the ports of tested entity SIGNAL A, B, C : STD_LOGIC; SIGNAL test_result : STD_LOGIC; BEGIN DUT : xor3 PORT MAP ( A => A, B => B, C => C, Result => test_result); ECE 332 George Mason University Testbench for XOR3 (2) PROCESS BEGIN A <= ‘0’; B <= ‘0’; WAIT FOR 10 ns; A <= ‘0’; B <= ‘0’; WAIT FOR 10 ns; A <= ‘0’; B <= ‘1’; WAIT FOR 10 ns; A <= ‘0’; B <= ‘1’; WAIT FOR 10 ns; A <= ‘1’; B <= ‘0’; WAIT FOR 10 ns; A <= ‘1’; B <= ‘0’; WAIT FOR 10 ns; A <= ‘1’; B <= ‘1’; WAIT FOR 10 ns; A <= ‘1’; B <= ‘1’; WAIT; END PROCESS; END xor3_tb_architecture; ECE 332 C <= ‘0’; C <= ‘1’; C <= ‘0’; C <= ‘1’; C <= ‘0’; C <= ‘1’; C <= ‘0’; C <= ‘1’; George Mason University Testbench waveform ECE 332 George Mason University Dataflow VHDL Major instructions Concurrent statements • • • • concurrent signal assignment () conditional concurrent signal assignment (when-else) selected concurrent signal assignment (with-select-when) generate scheme for equations (for-generate) Conditional concurrent signal assignment When - Else target_signal <= value1 when condition1 else value2 when condition2 else . . . valueN-1 when conditionN-1 else valueN; Value N Value N-1 0 1 .… … 0 1 0 1 Value 2 Value 1 Condition N-1 Condition 2 Condition 1 Target Signal Operators • Relational operators = /= < <= > >= • Logic and relational operators precedence Highest Lowest = and /= or not < <= nand nor > xor >= xnor Priority of Logic and Relational Operators compare a = bc Incorrect … when a = b and c else … equivalent to … when (a = b) and c else … Correct … when a = (b and c) else … Tri-state Buffer – example ena LIBRARY ieee; USE ieee.std_logic_1164.all; input output ENTITY tri_state IS PORT ( ena: IN STD_LOGIC; input: IN STD_LOGIC_VECTOR(7 downto 0); output: OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ); END tri_state; ARCHITECTURE tri_state_dataflow OF tri_state IS BEGIN output <= input WHEN (ena = '0') ELSE (OTHERS => 'Z'); END tri_state_dataflow; OTHERS means all bits not directly specified, in this case all the bits. Dataflow VHDL Major instructions Concurrent statements • • • • concurrent signal assignment () conditional concurrent signal assignment (when-else) selected concurrent signal assignment (with-select-when) generate scheme for equations (for-generate) Selected concurrent signal assignment With –Select-When with choice_expression select target_signal <= expression1 when choices_1, expression2 when choices_2, . . . expressionN when choices_N; expression1 choices_1 expression2 choices_2 target_signal expressionN choices_N choice expression Allowed formats of choices_k WHEN value WHEN value_1 to value_2 WHEN value_1 | value_2 | .... | value N this means boolean “or” Allowed formats of choice_k - example WITH sel SELECT y <= a WHEN "000", b WHEN "011" to "110", c WHEN "001" | "111", d WHEN OTHERS; MLU: Block Diagram MUX_0 A1 A IN 0 NEG_A MUX_1 IN 1 MUX_2 Y1 IN 2 IN 3 Y O U T PU T S E L1 S E L0 B B1 MUX_4_1 MUX_3 NEG_B L1 L0 NEG_Y MLU: Entity Declaration LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY mlu IS PORT( NEG_A : IN STD_LOGIC; NEG_B : IN STD_LOGIC; NEG_Y : IN STD_LOGIC; A : IN STD_LOGIC; B : IN STD_LOGIC; L1 : IN STD_LOGIC; L0 : IN STD_LOGIC; Y : OUT STD_LOGIC ); END mlu; MLU: Architecture Declarative Section ARCHITECTURE mlu_dataflow OF mlu IS SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL A1 : STD_LOGIC; B1 : STD_LOGIC; Y1 : STD_LOGIC; MUX_0 : STD_LOGIC; MUX_1 : STD_LOGIC; MUX_2 : STD_LOGIC; MUX_3 : STD_LOGIC; L: STD_LOGIC_VECTOR(1 DOWNTO 0); MLU - Architecture Body BEGIN A1<= NOT A WHEN (NEG_A='1') ELSE A; B1<= NOT B WHEN (NEG_B='1') ELSE B; Y <= NOT Y1 WHEN (NEG_Y='1') ELSE Y1; MUX_0 MUX_1 MUX_2 MUX_3 <= <= <= <= A1 A1 A1 A1 AND B1; OR B1; XOR B1; XNOR B1; L <= L1 & L0; with (L) select Y1 <= MUX_0 WHEN "00", MUX_1 WHEN "01", MUX_2 WHEN "10", MUX_3 WHEN OTHERS; END mlu_dataflow; Data-flow VHDL Major instructions Concurrent statements • • • • concurrent signal assignment () conditional concurrent signal assignment (when-else) selected concurrent signal assignment (with-select-when) generate scheme for equations (for-generate) For Generate Statement For - Generate label: FOR identifier IN range GENERATE BEGIN {Concurrent Statements} END GENERATE [label]; PARITY Example PARITY: Block Diagram PARITY: Entity Declaration LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY parity IS PORT( parity_in parity_out ); END parity; : IN STD_LOGIC_VECTOR(7 DOWNTO 0); : OUT STD_LOGIC PARITY: Block Diagram xor_out(1) xor_out(2) xor_out(3) xor_out(4) xor_out(5) xor_out(6) PARITY: Architecture ARCHITECTURE parity_dataflow OF parity IS SIGNAL xor_out: std_logic_vector (6 downto 1); BEGIN xor_out(1) xor_out(2) xor_out(3) xor_out(4) xor_out(5) xor_out(6) parity_out <= <= <= <= <= <= <= parity_in(0) XOR parity_in(1); xor_out(1) XOR parity_in(2); xor_out(2) XOR parity_in(3); xor_out(3) XOR parity_in(4); xor_out(4) XOR parity_in(5); xor_out(5) XOR parity_in(6); xor_out(6) XOR parity_in(7); END parity_dataflow; PARITY: Block Diagram (2) xor_out(0) xor_out(1) xor_out(2) xor_out(3) xor_out(4) xor_out(5) xor_out(6) xor_out(7) PARITY: Architecture ARCHITECTURE parity_dataflow OF parity IS SIGNAL xor_out: STD_LOGIC_VECTOR (7 downto 0); BEGIN xor_out(0) xor_out(1) xor_out(2) xor_out(3) xor_out(4) xor_out(5) xor_out(6) xor_out(7) parity_out <= <= <= <= <= <= <= <= <= parity_in(0); xor_out(0) XOR xor_out(1) XOR xor_out(2) XOR xor_out(3) XOR xor_out(4) XOR xor_out(5) XOR xor_out(6) XOR xor_out(7); END parity_dataflow; parity_in(1); parity_in(2); parity_in(3); parity_in(4); parity_in(5); parity_in(6); parity_in(7); PARITY: Architecture (2) ARCHITECTURE parity_dataflow OF parity IS SIGNAL xor_out: STD_LOGIC_VECTOR (7 DOWNTO 0); BEGIN xor_out(0) <= parity_in(0); G2: FOR i IN 1 TO 7 GENERATE xor_out(i) <= xor_out(i-1) XOR parity_in(i); END GENERATE; parity_out <= xor_out(7); END parity_dataflow; Combinational Logic Synthesis for Beginners Simple Rules For combinational logic, use only concurrent statements • • • • concurrent signal assignment () conditional concurrent signal assignment (when-else) selected concurrent signal assignment (with-select-when) generate scheme for equations (for-generate) Simple Rules • For circuits composed of: – simple logic operations (logic gates) – simple arithmetic operations (addition, subtraction, multiplication) – shifts/rotations by a constant • Use – concurrent signal assignment () Simple Rules • For circuits composed of – multiplexers – decoders, encoders – tri-state buffers • Use: – conditional concurrent signal assignment (when-else ) – selected concurrent signal assignment (with-selectwhen) Left versus Right Side Left side <= Right side <= when-else with-select <= • Internal signals (defined in a given architecture) • Ports of the mode - out - inout - buffer (don’t recommend using buffer in this class) Expressions including: • Internal signals (defined in a given architecture) • Ports of the mode - in - inout - buffer Explicit Component Declaration Tips • For simple projects put entity .vhd files all in same directory • Declare components in main code • Xilinx will figure out hierarchy automatically METHOD #2: Package component declaration • Components declared in package • Actual instantiations and port maps always in main code Packages • Instead of declaring all components can declare all components in a PACKAGE, and INCLUDE the package once – This makes the top-level entity code cleaner – It also allows that complete package to be used by another designer • A package can contain – Components – Functions, Procedures – Types, Constants Package – example (1) LIBRARY ieee ; USE ieee.std_logic_1164.all ; PACKAGE GatesPkg IS COMPONENT mux2to1 PORT (w0, w1, s f END COMPONENT ; COMPONENT priority PORT (w : IN y : OUT z : OUT END COMPONENT ; : IN STD_LOGIC ; : OUT STD_LOGIC ) ; STD_LOGIC_VECTOR(3 DOWNTO 0) ; STD_LOGIC_VECTOR(1 DOWNTO 0) ; STD_LOGIC ) ; Package – example (2) COMPONENT dec2to4 PORT (w : IN En : IN y : OUT END COMPONENT ; STD_LOGIC_VECTOR(1 DOWNTO 0) ; STD_LOGIC ; STD_LOGIC_VECTOR(0 TO 3) ) ; COMPONENT regn GENERIC ( N : INTEGER := 8 ) ; PORT ( D : IN STD_LOGIC_VECTOR(N-1 DOWNTO 0) ; Enable, Clock : IN STD_LOGIC ; Q : OUT STD_LOGIC_VECTOR(N-1 DOWNTO 0) ) ; END COMPONENT ; Package – example (3) constant constant constant constant constant constant constant constant END GatesPkg; ADDAB : std_logic_vector(3 downto 0) := "0000"; ADDAM : std_logic_vector(3 downto 0) := "0001"; SUBAB : std_logic_vector(3 downto 0) := "0010"; SUBAM : std_logic_vector(3 downto 0) := "0011"; NOTA : std_logic_vector(3 downto 0) := "0100"; NOTB : std_logic_vector(3 downto 0) := "0101"; NOTM : std_logic_vector(3 downto 0) := "0110"; ANDAB : std_logic_vector(3 downto 0) := "0111"; Package usage (1) LIBRARY ieee ; USE ieee.std_logic_1164.all ; USE work.GatesPkg.all; ENTITY priority_resolver1 IS PORT (r : IN STD_LOGIC_VECTOR(5 DOWNTO 0) ; s : IN STD_LOGIC_VECTOR(1 DOWNTO 0) ; clk : IN STD_LOGIC; en : IN STD_LOGIC; t : OUT STD_LOGIC_VECTOR(3 DOWNTO 0) ) ; END priority_resolver1; ARCHITECTURE structural OF priority_resolver1 IS SIGNAL SIGNAL SIGNAL SIGNAL p : q : z : ena STD_LOGIC_VECTOR (3 DOWNTO 0) ; STD_LOGIC_VECTOR (1 DOWNTO 0) ; STD_LOGIC_VECTOR (3 DOWNTO 0) ; : STD_LOGIC ; Package usage (2) BEGIN u1: mux2to1 PORT MAP ( w0 => r(0) , w1 => r(1), s => s(0), f => p(0)); p(1) <= r(2); p(2) <= r(3); u2: mux2to1 PORT MAP ( w0 => r(4) , w1 => r(5), s => s(1), f => p(3)); u3: priority PORT MAP ( w => p, y => q, z => ena); u4: dec2to4 PORT MAP ( w => q, En => ena, y => z); u5: regn GENERIC MAP ( N => 4) PORT MAP ( D => z , Enable => En , Clock => Clk, Q => t ); END structural; Explicit Component Declaration versus Package • Explicit component declaration is when you declare components in main code – When have only a few component declarations, this is fine – When have many component declarations, use packages for readability • Packages also help with portability and sharing of libraries among many users in a company • Remember, the actual instantiations always take place in main code – Only the declarations can be in main code or package How to add binary numbers • Consider adding two 1-bit binary numbers x and y – 0+0 = 0 – 0+1 = 1 x y Carry – 1+0 = 1 0 0 0 – 1+1 = 10 0 0 1 0 1 1 0 0 1 1 0 1 1 • Carry is x AND y • Sum is x XOR y • The circuit to compute this is called a half-adder 60 Sum = s (sum) c (carry) x y s c 1 1 0 1 1 0 1 0 0 1 1 0 0 0 0 0 61 A full adder is a circuit that accepts as input thee bits x, y, and c, and produces as output the binary sum cs of a, b, and c. c HA X Y x y x y c s (sum) c (carry) X HA Y s S S C C S c C 1 1 1 1 1 0 1 0 0 1 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 0 0 62 The full adder • The full circuitry of the full adder c s x y c 63 Adding bigger binary numbers • We can use a half-adder and full adders to compute the sum of two Boolean numbers 1 0 1 1 +1 1 ? 0 64 0 0 0 1 0 1 0 Adding bigger binary numbers • Just chain one half adder and full adders together, e.g., to add x=x3x2x1x0 and y=y3y2y1y0 we need: x0 y0 x1 y1 x2 y2 x3 y3 X Y HA s0 S C C FA s1 S X Y C C FA s2 S X Y C C FA S X Y C s3 c 65