280 likes | 443 Views
Introduction to Design Tools COE 1502. Example design: ALU. Recall that the ALUOp is 4 bits High-order two bits used to determine operation class (ALUOp(3:2)) Low-order two bits used to determine which operation is performed within each class (ALUOp(1:0))
E N D
Example design: ALU • Recall that the ALUOp is 4 bits • High-order two bits used to determine operation class (ALUOp(3:2)) • Low-order two bits used to determine which operation is performed within each class (ALUOp(1:0)) • Next, let’s define “operation classes” and have subblocks compute intermediate results in parallel… • Logical operations (ALUOp(3:2) == “00”) • AND, OR, NOR, XOR • Arithmetic operations (ALUOp(3:2) == “01”) • ADD, ADDU, SUB, SUBU • Comparison (ALUOp(3:2) == “10”) • SLT, SLTU • Shift (ALUOp(3:2) == “11”) • SLL, SRL, SRA • Idea: perform each operation type in parallel and select the appropriate output using the two high-order bits of ALUOp
Example design: ALU • Add subblocks, name them, and wire them up… • Note that ALUOp needs a bus ripper… Use wire tool here
Example design: ALU • Let’s take a look at the generated VHDL for the top-level design… • Things to note • Same entity statement as before • Internal signal declarations • Subblocks declared as components (with interfaces) • Embedded block code • Instance port mappings
Example design: ALU COMPONENT Logical PORT ( A : IN std_logic_vector (63 DOWNTO 0); ALUOp : IN std_logic_vector (1 DOWNTO 0); B : IN std_logic_vector (63 DOWNTO 0); LogicalR : OUT std_logic_vector (63 DOWNTO 0) ); END COMPONENT; COMPONENT Mux4Bus32 PORT ( ALUOp : IN std_logic_vector (3 DOWNTO 2); ArithmeticR : IN std_logic_vector (63 DOWNTO 0); ComparisonR : IN std_logic_vector (63 DOWNTO 0); LogicalR : IN std_logic_vector (63 DOWNTO 0); ShifterR : IN std_logic_vector (63 DOWNTO 0); R : OUT std_logic_vector (63 DOWNTO 0) ); END COMPONENT; COMPONENT Shifter PORT ( A : IN std_logic_vector (63 DOWNTO 0); ALUOp : IN std_logic_vector (1 DOWNTO 0); SHAMT : IN std_logic_vector (5 DOWNTO 0); ShifterR : OUT std_logic_vector (63 DOWNTO 0) ); END COMPONENT; -- Optional embedded configurations -- pragma synthesis_off FOR ALL : Arithmetic USE ENTITY ALU.Arithmetic; FOR ALL : Comparison USE ENTITY ALU.Comparison; FOR ALL : Logical USE ENTITY ALU.Logical; FOR ALL : Mux4Bus32 USE ENTITY ALU.Mux4Bus32; FOR ALL : Shifter USE ENTITY ALU.Shifter; -- pragma synthesis_on LIBRARY ALU; ARCHITECTURE struct OF ALU IS -- Architecture declarations -- Internal signal declarations SIGNAL ArithmeticR : std_logic_vector(63 DOWNTO 0); SIGNAL Asign : std_logic; SIGNAL Bsign : std_logic; SIGNAL CarryOut : std_logic; SIGNAL ComparisonR : std_logic_vector(63 DOWNTO 0); SIGNAL LogicalR : std_logic_vector(63 DOWNTO 0); SIGNAL Rsign : std_logic; SIGNAL ShifterR : std_logic_vector(63 DOWNTO 0); -- Component Declarations COMPONENT Arithmetic PORT ( A : IN std_logic_vector (63 DOWNTO 0); ALUOp : IN std_logic_vector (1 DOWNTO 0); B : IN std_logic_vector (63 DOWNTO 0); ArithmeticR : OUT std_logic_vector (63 DOWNTO 0); CarryOut : OUT std_logic ; Overflow : OUT std_logic ; Zero : OUT std_logic ); END COMPONENT; COMPONENT Comparison PORT ( ALUOp : IN std_logic_vector (1 DOWNTO 0); Asign : IN std_logic ; Bsign : IN std_logic ; CarryOut : IN std_logic ; Rsign : IN std_logic ; ComparisonR : OUT std_logic_vector (63 DOWNTO 0) ); END COMPONENT;
Example design: ALU BEGIN -- Architecture concurrent statements -- HDL Embedded Text Block 1 eb1 Asign <= A(31); Bsign <= B(31); Rsign <= ArithmeticR(31); -- Instance port mappings. I1 : Arithmetic PORT MAP ( A => A, ALUOp => ALUOp(1 DOWNTO 0), B => B, ArithmeticR => ArithmeticR, CarryOut => CarryOut, Overflow => Overflow, Zero => Zero ); I2 : Comparison PORT MAP ( ALUOp => ALUOp(1 DOWNTO 0), Asign => Asign, Bsign => Bsign, CarryOut => CarryOut, Rsign => Rsign, ComparisonR => ComparisonR ); I0 : Logical PORT MAP ( A => A, ALUOp => ALUOp(1 DOWNTO 0), B => B, LogicalR => LogicalR ); I4 : Mux4Bus32 PORT MAP ( ALUOp => ALUOp(3 DOWNTO 2), ArithmeticR => ArithmeticR, ComparisonR => ComparisonR, LogicalR => LogicalR, ShifterR => ShifterR, R => R ); I3 : Shifter PORT MAP ( A => A, ALUOp => ALUOp(1 DOWNTO 0), SHAMT => SHAMT, ShifterR => ShifterR ); END struct;
Example design: ALU • Next, let’s create the logical sub-block… • Double-click the logical subblock • This design will perform all four logical operations in parallel and select the desired result using the low-order two bits of ALUOp • AND => 00 • OR => 01 • XOR => 10 • NOR => 11
Example design: ALU • Notice the new block diagram already has the interface ports and signals… • Add four embedded blocks (yellow blocks) to implement the operations • Next, wire up the blocks to the inputs (A,B), create an output mux, wire it to the output bus and ALUOp • We can change the symbols for the yellow blocks • We’ll need to assign names for the internal/intermediate signals in the design • Add the appropriate concurrent VHDL code for each block • What are concurrent semantics?
Example design: ALU • Let’s take a look at the generated VHDL... ARCHITECTURE struct OF Logical IS -- Architecture declarations -- Internal signal declarations SIGNAL ANDR : std_logic_vector(63 DOWNTO 0); SIGNAL NORR : std_logic_vector(63 DOWNTO 0); SIGNAL ORR : std_logic_vector(63 DOWNTO 0); SIGNAL XORR : std_logic_vector(63 DOWNTO 0); BEGIN -- Architecture concurrent statements -- HDL Embedded Text Block 1 ANDBlock ANDR <= A AND B; -- HDL Embedded Text Block 2 ORBlock ORR <= A OR B; -- HDL Embedded Text Block 3 XORBlock XORR <= A XOR B; -- HDL Embedded Text Block 4 NORBlock NORR <= A NOR B; -- HDL Embedded Text Block 5 Mux4B64 LogicalR <= ANDR when ALUOp="00" else ORR when ALUOp="01" else XORR when ALUOp="10" else NORR; -- Instance port mappings. END struct; LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; ENTITY Logical IS PORT( A : IN std_logic_vector (63 DOWNTO 0); ALUOp : IN std_logic_vector (1 DOWNTO 0); B : IN std_logic_vector (63 DOWNTO 0); LogicalR : OUT std_logic_vector (63 DOWNTO 0) ); -- Declarations END Logical ;
Example design: ALU Drag/drop signals (or right click) • Once we’re done, we’ll generate VHDL and compile the design in order to simulate • The “M” button will perform the entire design flow • We’re now presented with the ModelSim window • Under the View menu option, open the signals and wave windows • Drag the signals from the signals window to the wave window Structure Right click to change radix
Example design: ALU • From this point, we can use force/run commands to simulate the design • Examples • restart –f • view wave • add wave /ALU/A • force ALUOp “0010” • force A X”000000FF” • force A 10#32 • run 10 • run • Default runlength is 100 ns • Turn off warnings • Note that the signals can be represented in hexadecimal • Right-click the signals in the wave window to change its properties • We can also write a text “.do” file to aid in simulation • Invoked using “do” command • example: • do “i:/alpha/alu/test_logical.do”
Example design: ALU • Let’s go back to the top-level ALU block diagram and create the Shifter subblock • We’ll implement the Shifter as a flowchart (useful for testbenches) • Flowcharts implement a behavioral VHDL architecture as a process • Processes are executed sequentially, not concurrently • Started when signal in sensitivity list changes • Allows programming constructs and variables • Primarily, we use: • Start/end points • Action boxes (also hierarchical) • Decision boxes • Wait boxes (not synthesizable) • Loop boxes • Flows • Operations are assigned to ALUOp(1:0) • SLL => 00 • SRL => 10 • SRA => 11
Example design: ALU (assume 32-bit words) • Add decision box to check whether this is a left shift or a right shift • If this is a left shift, add another decision box to check the least significant bit of SHAMT • Then add an action box to assign a variable the input value, shifted 1 bit • Note the syntax for assigning variables • We’ll have to add this variable to the variable declaration list • Under “Flow Chart Properties”, right-click the design • We’ll need LeftOne, LeftTwo, LeftFour, LeftEight, and LeftSixteen • Right-click, “Flow Chart Properties” • Idea: For each set bit n in the SHAMT value, shift the input value 2n positions to the left • Always shift in 0
Example design: ALU • For the right shift, there’s a complication • What about arithmetic shifts? • For this, we use a LOOP block to assign a 16-bit Fill variable the value we will shift in • From then on, we’ll follow the same procedure as with the left shift, but with new variables • RightOne, RightTwo, RightFour, RightEight, and RightSixteen • When we’re finished, we’ll simulate this block as we did before
Example design: ALU • Final variable declaration list: variable LeftOne : std_logic_vector(31 downto 0); variable LeftTwo : std_logic_vector(31 downto 0); variable LeftFour : std_logic_vector(31 downto 0); variable LeftEight : std_logic_vector(31 downto 0); variable RightOne : std_logic_vector(31 downto 0); variable RightTwo : std_logic_vector(31 downto 0); variable RightFour : std_logic_vector(31 downto 0); variable RightEight : std_logic_vector(31 downto 0); variable Fill : std_logic_vector(31 downto 0);
Example design: ALU • Next, we’ll design the arithmetic subblock as another block diagram • We need to implement signed and unsigned addition and subtraction • We have a 32-bit adder component in the COELib library we can instantiate for use in this design • Use the green component button to add the ADD32 component from COELib • Wire up the design as follows… • Drag and drop components from component browser
Example design: ALU • Let’s note a few things about this design • How does the generated VHDL for the arithmetic block differ from the shifter block? • How is subtraction implemented using an adder? • What is the precise difference between signed and unsigned operations in this context? • How do we detect overflow in signed and unsigned arithmetic? • What reason would we have to detecting a zero result? • How well does our macro file test the unit?
Example design: ALU • Now let’s design the comparison subblock using the truth table view • Implementing signed and unsigned “set-on-less than” (A < B) • We need to utilize the subtraction results from the arithmetic subblock as inputs to the table • Need to make sure the two low-order bits match those for subtraction in the arithmetic unit • SLT => 10 • SLTU => 11 • Outputs from arithmetic unit used as inputs • The sign of the result • Carryout • Other inputs we need • Sign of A • Sign of B • Output • Single bit output in low-order bit • Rows and columns can be added by a right-click • Columns can be resized • Note: blank cells are considered “don’t cares” • Reminder: In VHDL, single bit literals (std_logic) are surrounded by single quotes, bit vectors (std_logic_vector) are surrounded by double quotes
Example design: ALU Initial truth table view • You will need to add rows • You might want to reorder the columns
Example design: ALU • Notes: • Keep in mind that we’re testing to determine if A is less than B • Keep in mind that our inputs assume that the operation being reflected by Rsign and CarryOut is A - B • (SLT) Why do we only consider Rsign when A and B’s signs match? • (SLTU) How do we use CarryOut to perform comparisons?
Example design: ALU 0 1 0 1 0 1 1 0
Example design: ALU --------------------------------------------------------------------------- truth_process: PROCESS(ALUOp, Asign, Bsign, CarryOut, Rsign) --------------------------------------------------------------------------- BEGIN -- Block 1 IF (ALUOp(1 DOWNTO 0) = "00") THEN ComparisonR <= "00000000000000000000000000000000"; ELSIF (ALUOp(1 DOWNTO 0) = "01") THEN ComparisonR <= "00000000000000000000000000000000"; ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '0') AND (Bsign = '0') AND (Rsign = '0') THEN ComparisonR <= "00000000000000000000000000000000"; ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '0') AND (Bsign = '0') AND (Rsign = '1') THEN ComparisonR <= "00000000000000000000000000000001"; ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '1') AND (Bsign = '1') AND (Rsign = '0') THEN ComparisonR <= "00000000000000000000000000000000"; ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '1') AND (Bsign = '1') AND (Rsign = '1') THEN ComparisonR <= "00000000000000000000000000000001"; ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '0') AND (Bsign = '1') THEN ComparisonR <= "00000000000000000000000000000000"; ELSIF (ALUOp(1 DOWNTO 0) = "10") AND (Asign = '1') AND (Bsign = '0') THEN ComparisonR <= "00000000000000000000000000000001"; ELSIF (ALUOp(1 DOWNTO 0) = "11") AND (CarryOut = '1') THEN ComparisonR <= "00000000000000000000000000000000"; ELSIF (ALUOp(1 DOWNTO 0) = "11") AND (CarryOut = '0') THEN ComparisonR <= "00000000000000000000000000000001"; END IF; END PROCESS truth_process;
Example design: ALU • Finally, let’s finish the top-level ALU design by designing the implementation for the Mux4bus32 • For this, we’ll use a VHDL architecture/entity view • Note: the entity is not necessary in this view… it will be generated automatically anyway R <= LogicalR when ALUOp(3 downto 2)="00" else ArithmeticR when ALUOp(3 downto 2)="01" else ComparisonR when ALUOp(3 downto 2)="10" else ShifterR;