DLX-Microprocessor / components / carrygenerator.vhd
carrygenerator.vhd
Raw
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;

ENTITY CARRYGEN IS
  GENERIC (
            N: INTEGER := 32;
            NBIT_BLOCK: INTEGER := 4
          );
  PORT (
    Ci: IN STD_LOGIC;
    A, B: IN STD_LOGIC_VECTOR(N DOWNTO 1);
    Co: OUT STD_LOGIC_VECTOR(N/NBIT_BLOCK-1 DOWNTO 0)
  );
END ENTITY;

ARCHITECTURE STRUCTURAL OF CARRYGEN IS

  CONSTANT MAX_I: INTEGER := INTEGER(CEIL(LOG2(REAL(N))))+1;

  COMPONENT PG_BLOCK IS
    PORT (
      Pik, Gik, Pkj, Gkj: STD_LOGIC;
      Pij, Gij: OUT STD_LOGIC
    );
  END COMPONENT;

  COMPONENT G_BLOCK IS
    PORT (
      Pik, Gik, Gkj: IN STD_LOGIC;
      Gij: OUT STD_LOGIC
    );
  END COMPONENT;

  COMPONENT PG_NETWORK_BLOCK IS
    PORT (
      Ai, Bi: IN STD_LOGIC;
      Pi, Gi: OUT STD_LOGIC
    );
  END COMPONENT;

  COMPONENT PG_CARRY_BLOCK IS
    PORT (
      Ai, Bi, Ci: IN STD_LOGIC;
      Pi, Gi: OUT STD_LOGIC
    );
  END COMPONENT;

  TYPE MAT IS ARRAY(MAX_I-1 DOWNTO 0) OF STD_LOGIC_VECTOR(N DOWNTO 1);
  SIGNAL P_MAT, G_MAT: MAT;
BEGIN

  -- This loop creates the first row of PG blocks
  PG_NET_LOOP: FOR I IN 2 TO N GENERATE
  BEGIN
    PG_J: PG_NETWORK_BLOCK PORT MAP (Ai=>A(I), Bi=>B(I), Pi=>P_MAT(0)(I), Gi=>G_MAT(0)(I));
  END GENERATE;

  -- The first block takes also the Ci input
  PG_C: PG_CARRY_BLOCK PORT MAP (Ai=>A(1), Bi=>B(1), Ci=>Ci, Pi=>P_MAT(0)(1), Gi=>G_MAT(0)(1));

  -- This loop creates the three rows with only one G block
  FIRST_OUTER_LOOP: FOR I IN 1 TO 3 GENERATE
  BEGIN
    -- Since it is generic, this if checks if the row has to be generated or not (if N<16 I don't need all the rows)
    OUTER_CHECK: IF (2**I)<=N GENERATE
    BEGIN
      -- I need N/(2^I) blocks, but the least significant one is a G block
      FIRST_INNER_LOOP: FOR J IN 0 TO N/(2**I)-2 GENERATE
      BEGIN
        PG_J: PG_BLOCK PORT MAP (Pik=>P_MAT(I-1)(N-(2**I)*J), Gik=>G_MAT(I-1)(N-(2**I)*J), Pkj=>P_MAT(I-1)(N-(2**I)*J-(2**(I-1))),
                                  Gkj=>G_MAT(I-1)(N-(2**I)*J-(2**(I-1))), Pij=>P_MAT(I)(N-(2**I)*J), Gij=>G_MAT(I)(N-(2**I)*J));
      END GENERATE;

      SECOND_INNER_LOOP: FOR J IN 0 TO N GENERATE
        INNER_CHECK: IF (J REM (2**I))/=0 GENERATE
          P_MAT(I)(J)<=P_MAT(I-1)(J);
          G_MAT(I)(J)<=G_MAT(I-1)(J);
        END GENERATE;
      END GENERATE;

      G_I: G_BLOCK PORT MAP (Pik=>P_MAT(I-1)(2**I), Gik=>G_MAT(I-1)(2**I), Gkj=>G_MAT(I-1)((2**I)-(2**(I-1))), Gij=>G_MAT(I)(2**I));
      
      -- Assigning the correspondent G_MAT element to Co 
      -- Co(I-1)<=G_MAT(I+INTEGER(CEIL(LOG2(REAL(NBIT_BLOCK))))-1)(NBIT_BLOCK*I);
    END GENERATE;
  END GENERATE;

  -- From I=4 the pattern changes
  SECOND_OUTER_LOOP: FOR I IN 4 TO MAX_I GENERATE
  BEGIN
    INNER_CHECK: IF (2**I)<=N GENERATE
    BEGIN
      -- Loop to generate PG blocks
      FIRST_INNER_LOOP: FOR J IN 0 TO (N/(2**(I)))-2 GENERATE
      BEGIN
        INNER_INNER_LOOP: FOR K IN 0 TO 2**(I-3)-1 GENERATE
        BEGIN
          PG_J: PG_BLOCK PORT MAP (Pik=>P_MAT(I-1)(N-J*(2**I)-(4*K)), Gik=>G_MAT(I-1)(N-J*(2**I)-(4*K)), Pkj=>P_MAT(I-1)(N-J*(2**I)-(2**(I-1))),
                                    Gkj=>G_MAT(I-1)(N-J*(2**I)-(2**(I-1))), Pij=>P_MAT(I)(N-J*(2**I)-(4*K)), Gij=>G_MAT(I)(N-J*(2**I)-(4*K)));

          P_MAT(I)(N-J*(2**I)-(2**(I-1))-(4*K))<=P_MAT(I-1)(N-J*(2**I)-(2**(I-1))-(4*K));
          G_MAT(I)(N-J*(2**I)-(2**(I-1))-(4*K))<=G_MAT(I-1)(N-J*(2**I)-(2**(I-1))-(4*K));
        END GENERATE;

      END GENERATE;

      -- Loop to generate G blocks
      SECOND_INNER_LOOP: FOR K IN 0 TO 2**(I-3)-1 GENERATE
      BEGIN
        G_I: G_BLOCK PORT MAP (Pik=>P_MAT(I-1)((2**I)-4*K), Gik=>G_MAT(I-1)((2**I)-4*K), Gkj=>G_MAT(I-1)(2**(I-1)), Gij=>G_MAT(I)((2**I)-4*K));

        -- Assigning the correspondent G_MAT element to Co 
        -- Co((2**(I-INTEGER(CEIL(LOG2(REAL(NBIT_BLOCK))))))-K-1)<=G_MAT(I)((2**I)-NBIT_BLOCK*K);
      END GENERATE;
    END GENERATE;
  END GENERATE;

  -- Assigning the correspondent G_MAT element to Co 
  C_OUT_ASSIGNMENT: FOR I IN 1 TO N/NBIT_BLOCK GENERATE
    Co(I-1) <= G_MAT(INTEGER(CEIL(LOG2(REAL(I*NBIT_BLOCK)))))(I*NBIT_BLOCK);
  END GENERATE;
END ARCHITECTURE;