Least Common Multiple (LCM) Task: Implement an LCM algorithm that is able to handle any combination of 8-bit (sign bit included) numbers. Use two's complement format to represent negative values. Provide the circuit with an interface for repetitive data input (using buttons and switches) and result output (using LEDs). The design should be developed in accordance with the same methodology as described in the example below: • prepare the flowchart of the algorithm that is based on the selected LCM computation method • prepare GSA and state transition table for the control part of the design • develop a suitable datapath Verify and implement the design on FPGA development board. Greatest Common Divisor Example The greatest common divisor of two non-zero integers is the largest positive integer that divides both numbers without remainder. One way to compute GCD is to use Euclidean algorithm. The flowchart of Euclidean algorithm is presented on Figure 1. For this example it is assumed that input operands are unsigned 8-bit numbers and none of them is zero. GCD circuit includes a control unit (FSM), which is complemented with a datapath. On this stage the datapath consists of two registers (RG1 and RG2), multiplexers for selecting the source of data to be stored in these registers and comparator logic. The remainder computation is treated as “black box”. As most of the basic FPGAs do not feature any dedicated logic for performing division, it must be synthesized separately. A simple division algorithm is presented on Figure 2. At each step it checks whether divisor, which is multiplied by corresponding power of two (starting from the maximum possible), fits into dividend. If it doesn’t, then the dividend is restored. BEGIN No START Yes RG1 := OP1; RG2 := OP2; Yes RG1 = RG2 No RG1 < RG2 Yes RG1 := RG2; RG2 := RG1; No Remainder Computation Yes Remainder = 0 No READY := 1; ANSW := RG2; END Figure 1: GCD Algorithm Register RG1 is loaded with dividend, while register RG2 – with divisor. At first the divisor is normalized. As the quotient is of no interest, its computation is omitted from the algorithm. After the final run, RG1 should contain the remainder, while divisor in RG2 is back to normal. Note, that RG1 is a 9-bit registers, as it should include a sign bit as well. Remainder computation algorithm invokes additional elements in the datapath: Arithmetic Logic Unit (ALU) and up/down counter. ALU is, in a sense, a custom block, its functionality is design specific. For this particular algorithm ALU should handle addition, subtraction and right/left shift operations, as well as comparison. The block scheme of the complete datapath is presented on Figure 3. Remainder Computation RG2(7) = 1 No Yes L1(RG2.0); C := C + 1; YesNo RG1 := RG1 - RG2; Yes RG1(8) = 1 No RG1 := RG1 + RG2; Yes C=0 No R1(0.RG2); C := C - 1; Figure 2: Remainder Computation Algorithm Elements of the datapath are controlled via eleven (Y10-Y0) signals – a control word. Y0, Y1 and Y2 are enable signals for the registers (RG1 and RG2) and the counter. Y3 signal selects the counting direction. Y7-Y4 control the multiplexers, which feed data to registers RG1 and RG2. Y8 and Y9 select the ALU operation (addition, subtraction or right/left shift). Y10 enables the ANSW output, when the result is ready. The control unit gets feedback from datapath via six (X6-X1) signals. X1 indicates whether the content of RG1 equals the content of RG2. X2 signals whether the value stored in RG1 is greater than the value of RG2. X3 is the most significant bit of RG2. X4 is the sign bit of RG1. Signals X5 and X6 indicate when content of counter and RG1 equal zero. y5 y4 y0 x4 x6 y9 y8 OP1 RG1 x1 ALU x2 RG2 OP2 y1 y7 y6 x3 ANSW Counter y3 y2 x5 y10 DATA PATH UNIT Figure 3: Datapath Of GCD Circuit At this stage it is possible to represent the control unit by means of graph-scheme of algorithm (GSA). In this GSA the computational statements (actions of ALU and counter) are replaced with the corresponding control signals (Y-s) and the conditions - with binary conditions signals (X-s). Simultaneously executed statements are grouped into common blocks. The resultant GSA is presented on Figure 4. It can be synthesized as either Moore or Mealy FSM to form a control unit for the GCD circuit. BEGIN 0 x0 1 y7 y5 y1 y0 1 0 x1 x2 1 y6 y4 y1 y0 0 x3 0 y9 y2 y1 1 y8 y0 1 x4 0 y0 1 1 x6 x5 0 y9 y8 y3 y2 y1 0 y10 END Figure 4: GSA Of GCD Algoritm VHDL descriptions of the main components of the datapath are provided in Listing 1, Listing 2 and Listing 3. Signals reg and counter_value infer registers during synthesis, as they are assigned a value inside an edge sensitive if statement. This makes the else path excessive, as the storage element should hold the data unchanged in any other case. Both registers are write-protected with enable signals, so they could store data only when it is required. Counter's activity is also protected with enable signal. Note, that example register and example counter are fully synchronous. Their control signals are not present in the sensitivity list, because such circuits should react to the rising edge of the clock signal only. Listing 1: VHDL Description of ALU process (OP1, OP2, op_sel) begin case op_sel is when "00" => result <= OP1 + OP2; when "01" => result <= OP1 - OP2; when "10" => result <= OP2(7 downto 0)&'0'; when "11" => result <= '0'&OP2(8 downto 1); when others => result <= (others => '0'); end case; if OP1 = OP2 then equal <= '1'; else equal <= '0'; end if; if OP1 < OP2 then greater <= '1'; else greater <= '0'; end if; end process; The counter should definitely be implemented as a signal (not a variable), because its value must be available to other processes. ALU is a purely combinational circuit, thus it reacts to the change on any of its inputs. Listing 2: VHDL Description of Register process (clk) begin if clk'event and clk = '1' then if reg_en = '1' then reg <= reg_input; end if; end if; end process; Listing 3: VHDL Description of Up/Down Counter process (clk) begin if clk'event and clk = '1' then if counter_en = '1' then if count_direction = '1' then counter_value <= counter_value - 1; else counter_value <= counter_value + 1; end if; end if; end if; end process; To check zero equality of a register, its content can be NORed bitwise. The condition becomes High only when all bits of the register are Low. VHDL description of a zero equality check for a 4-bit register is presented in Listing 4. Listing 4: Zero Equality Check for a 4-bit Register reg_zero <= not (reg(3) or reg(2) or reg(1) or reg(0) );