Hầu hết các phép tính số học chẳng hạn phép nhân, chia, trừ đều có thể thực hiện được thông qua phép tính cộng. Chẳng hạn, Hình 35 chỉ ra cấu trúc phần cứng đơn vị chức năng thực hiện cả phép tính cộng và trừ được xây dựng trên cơ sở một cộng 2 số 16-bit và một số mạch logic bổ trợ. Sở dĩ điều này có thể thực hiện được bởi vì, phép trừ A-B có thể thực hiện được bằng phép cộng A + (-B), tiếp đến –B có thể được tính bằng lấy bù 2 của B theo công thức: -B = (Not B) + 1.
Tín hiệu Mode được dùng để chọn chế độ hoạt động của bộ ADD/SUB là cộng (Mode = 0) hay trừ (Mode = 1).
Hình 35: Đơn vị chức năng thực hiện phép tính cộng và trừ 2 số 16-bit.
Như vậy, có thể thấy thực hiện một bộ cộng tốc độ cao cũng đồng nghĩa với việc thực hiện được các phép tính số học khác với tốc độ cao. Trong thiết kế bộ cộng, trễ lan truyền cờ nhớ thường là lớn nhất, do đó để cải thiện tốc độ của bộ cộng, nhiệm vụ quan trọng là giảm trễ lan truyền cờ nhớ. Có 3 phương pháp chính để thực hiện bộ cộng là: bộ cộng lan truyền cờ nhớ (Ripple carry adder: RCA), bộ cộng chọn cờ nhớ (Carry Select Adder: CSA) và bộ cộng với cờ nhớ được tính trước (Carry Lookahead Adder: CLA). Bài viết này chọn phương pháp thực hiện lai ghép giữa bộ cộng CLA và phương pháp chọn cờ nhớ CSA để đạt được sự dung hòa tốt giữa độ phức tạp phần cứng và tốc độ tính toán.
Bộ cộng RCA: Hình 36 chỉ ra cấu trúc của một bộ cộng RCA 4-bit, trong đó mỗi khối FA (Full Adder) là một cộng 1 bit có cấu trúc như Hình 37.
- Ưu điểm: đơn giản dễ thực hiện, chi phí diện tích thấp
- Nhược điểm: Trễ lan truyền cờ nhớ lớn, dẫn đến tốc độ tính toán chậm. Gọi τ là trễ lan tuyền qua mỗi cổng logic (trong hình Hình 37), thì trễ lan truyền cờ nhớ trong thực hiện bộ cộng RCA n-bit sẽ là (2n+1)τ. Rõ ràng cho giá trị n càng lớn thì trễ này sẽ càng lớn, dẫn đến tốc độ tính toán của bộ cộng rất chậm.
Hình 36: Bộ cộng lan truyền cờ nhớ RCA.
Hình 37: Cấu trúc của một bộ cộng FA (Full Adder).
Để nâng cao tốc độ tính toán của bộ cộng một phương pháp được sử dụng phổ biến là phương pháp tính toán trước cờ nhớ CLA. Nguyên lý cho việc thực hiện bộ cộng CLA là dựa trên sự phân tích luồng dữ liệu lan truyền qua bộ cộng FA trong Hình 37. Xét các tín hiệu trên bộ cộng FA được dùng để tính tổng Si và cớ nhớ Ci+1 của 2 bit thứ i (Ai và Bi) với cờ nhớ lối vào Ci từ tầng trước đó. Các tín hiệu trung gian Pi và Gi được tạo ra bởi phương trình:
Pi = Ai XOR Bi | (1) |
Gi = AiBi | (2) |
Giá trị tổng và cờ nhớ lối ra có thể được định nghĩa như:
Si = Pi ⊕ Ci | (3) |
Ci+1 = Gi + PiCi | (4) |
Trong đó:
- Tín hiệu Gi được gọi là tín hiệu tạo cờ nhớ (carry Generate) vì tín hiệu cờ nhớ (Ci+1) được tạo ra bất cứ khi nào Gi =1, bất kể giá trị của cờ nhớ đầu vào (Ci).
- Pi được gọi là tín hiệu lan truyền cờ nhớ (carry propagate) vì bất cứ khi nào Pi =1 và Gi =0 thì cờ nhớ đầu vào sẽ được lan truyền thành cờ nhớ đầu ra, tức là Ci+1= Ci.
Việc tính toán giá trị của Pi và Gi chỉ phụ thuộc vào các bit toán hạng đầu vào (Ai và Bi) như dễ thấy từ hình và các phương trình trên. Do đó các tín hiệu này thiết lập đến giá trị trạng thái ổn định sau khoảng trễ lan truyền qua các cổng tương ứng. Cụ thể, các giá trị được tính toán của tất cả các Pi là hợp lệ sau khoảng trễ lan truyền qua cổng XOR kể từ lúc các toán hạng A và B hợp lệ. Các giá trị được tính toán của tất cả các Gi là hợp lệ sau khoảng trễ lan truyền qua cổng AND kể từ lúc các toán hạng A và B hợp lệ.
Biểu thức Boolean của các đầu ra cờ nhớ tại tất cả các tầng có thể được viết ra như sau:
C1 = G0 + P0C0
C2 = G1 + P1C1 = G1 + P1 (G0 + P0C0) = G1 + P1G0 + P1P0C0 C3 = G2 + P2C2 = G2 + P2G1 + P2P1G0 + P2P1P0C0 C4 = G3 + P3C3 = G3 + P3G2 + P3P2G1 + P3P2P1G0 + P3P2P1P0C0 |
(5)
(6) (7) (8) |
Hình 38: Bộ cộng CLA 4-bit.
So với bộ cộng RCA, trễ lan truyền cho thực hiện bộ cộng CLA luôn là hằng số và bằng 4τ so với (2n+1)τ của RCA. Vấn đề của việc thực hiện bộ cộng CLA là biểu thức logic và do đó là mạch logic cho việc tính toán cờ nhớ sẽ trở lên phức tạp hơn cho n lớn hơn 4 bit. Nó sẽ cần các cổng AND và OR nhiều lối vào.
Do đó bài viết này chọn phương pháp thực hiện lai ghép giữa bộ cộng CLA và phương pháp chọn cờ nhớ CSA. Các số hạng lối vào A, B được tách thành các nible 4-bit và thực hiện tính tổng song song bởi 4 module bộ cộng CLA 4-bit. Kết quả tổng của A và B sẽ được lựa chọn bằng phương pháp chọn cờ nhớ. Sơ đồ khối bộ cộng 16 bit lai ghép được chỉ ra trong Hình 39. Mỗi khối CLA_ADDER là một bộ cộng hai số 4-bit theo phương pháp CLA có cấu trúc như được chỉ ra trong Hình 38.
Hình 39: Cấu trúc của bộ cộng lai ghép HBD_ADDER.
Mã nguồn VHDL
-- Hybrid adder combines 4-bit CLA adders in carry select adding method library IEEE; use ieee.std_logic_1164.all; USE ieee.numeric_std.all ; use IEEE.std_logic_unsigned.all; use work.RCA_define.all; Entity hbd_Adder is Port( A, B : in std_logic_vector( DATAWIDTH-1 downto 0); carry_in : in std_logic; carry_out : out std_logic; S : out std_logic_vector( DATAWIDTH-1 downto 0) ); end hbd_Adder; architecture RTL of hbd_Adder is signal tempC : signed( DATAWIDTH/4 downto 0); begin tempC(0) <= carry_in; --for firts 4-bit cla_adder0 : cla_adder port map(A(3 downto 0),B(3 downto 0),tempC(0),S(3 downto 0),tempC(1)); csa_adder1 : csa_adder port map(A(7 downto 4),B(7 downto 4),tempC(1),S(7 downto 4),tempC(2)); csa_adder2 : csa_adder port map(A(11 downto 8),B(11 downto 8),tempC(2),S(11 downto 8),tempC(3)); csa_adder3 : csa_adder port map(A(15 downto 12),B(15 downto 12),tempC(3),S(15 downto 12),tempC(4)); carry_out <= tempC(4); end;
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use work.RCA_define.all; entity cla_adder is port( A,B : in std_logic_vector(3 downto 0); cin : in std_logic; S : out std_logic_vector(3 downto 0); cout : out std_logic ); end cla_adder; architecture Behavioral of cla_adder is signal P,G : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; signal C : STD_LOGIC_VECTOR(4 DOWNTO 0) := "00000"; begin --first level P <= A xor B; G <= A and B; --second level gen_c : cla_block port map(P,G,C,cin); --third level S <= P xor C(3 downto 0); cout <= C(4); end Behavioral;
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use work.RCA_define.all; entity csa_adder is port( A,B : in std_logic_vector(3 downto 0); cin : in std_logic; S : out std_logic_vector(3 downto 0); cout : out std_logic ); end csa_adder; architecture Behavioral of csa_adder is signal temp0,temp1: STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; signal carry0,carry1 : STD_LOGIC := '0'; begin --for carry 0 cla0 : cla_adder port map(A,B,'0',temp0,carry0); --for carry 1 cla1 : cla_adder port map(A,B,'1',temp1,carry1); --mux for carry mux_carry : MUX2to1_1b port map(carry0,carry1,cin,cout); --mux's for sum mux_sum0 : MUX2to1_1b port map(temp0(0),temp1(0),cin,S(0)); mux_sum1 : MUX2to1_1b port map(temp0(1),temp1(1),cin,S(1)); mux_sum2 : MUX2to1_1b port map(temp0(2),temp1(2),cin,S(2)); mux_sum3 : MUX2to1_1b port map(temp0(3),temp1(3),cin,S(3)); end Behavioral;
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use work.RCA_define.all; entity cla_block is port ( P : in std_logic_vector(3 downto 0); G : in std_logic_vector(3 downto 0); C : out std_logic_vector(4 downto 0); cin : in std_logic ); end cla_block; architecture Behavioral of cla_block is begin C(0) <= cin; C(1) <= G(0) or (P(0) and cin); C(2) <= G(1) or (P(1) and G(0)) or (P(1) and P(0) and cin); C(3) <= G(2) or (P(2) and G(1)) or (P(2) and P(1) and G(0)) or (P(2) and P(1) and P(0) and cin); C(4) <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0)) or (P(3) and P(2) and P(1) and P(0) and cin); end Behavioral;
I really like and appreciate your article post. Thanks Again. Keep writing. Glynis Bobbie Joli