Chia sẻ:
Notifications
Clear all

Viết code VHDL cho mạch 4-bit adder.

2 Bài viết
2 Thành viên
0 Reactions
72 Lượt xem
(@admin)
Thành Viên Moderator
Tham gia: 6 năm trước
Bài viết: 27
Topic starter  

Viết code VHDL cho mạch 4-bit adder.


   
Trích dẫn
Thẻ chủ đề
(@Anonymous)
New Member Khách
Tham gia: 1 giây trước
Bài viết: 0
 

Dưới đây là mã VHDL cho mạch cộng 4 bit, cùng với lời giải thích và một số lựa chọn thiết kế:

```vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder_4bit is
port (
a : in std_logic_vector(3 downto 0); -- Đầu vào 4 bit A
b : in std_logic_vector(3 downto 0); -- Đầu vào 4 bit B
cin : in std_logic; -- Đầu vào Carry
s : out std_logic_vector(3 downto 0); -- Đầu ra tổng 4 bit
cout : out std_logic -- Đầu ra Carry
);
end entity adder_4bit;

architecture behavioral of adder_4bit is

-- Tín hiệu Carry nội bộ
signal carry : std_logic_vector(4 downto 0);

begin

carry(0) <= cin; -- Carry đầu vào ban đầu

-- Instantiating 4 full adders
process (a, b, carry)
begin
-- Bit 0
s(0) <= a(0) xor b(0) xor carry(0);
carry(1) <= (a(0) and b(0)) or (a(0) and carry(0)) or (b(0) and carry(0));

-- Bit 1
s(1) <= a(1) xor b(1) xor carry(1);
carry(2) <= (a(1) and b(1)) or (a(1) and carry(1)) or (b(1) and carry(1));

-- Bit 2
s(2) <= a(2) xor b(2) xor carry(2);
carry(3) <= (a(2) and b(2)) or (a(2) and carry(2)) or (b(2) and carry(2));

-- Bit 3
s(3) <= a(3) xor b(3) xor carry(3);
carry(4) <= (a(3) and b(3)) or (a(3) and carry(3)) or (b(3) and carry(3));

cout <= carry(4); -- Gán carry cuối cùng cho đầu ra cout
end process;

-- Dưới đây là một cách khác để làm cho nó nhỏ gọn hơn (sử dụng vòng lặp)
-- Bạn cần chọn một trong hai cách (process hoặc loop), không thể sử dụng cả hai cùng một lúc.
-- generate_adder : for i in 0 to 3 generate
-- s(i) <= a(i) xor b(i) xor carry(i);
-- carry(i+1) <= (a(i) and b(i)) or (a(i) and carry(i)) or (b(i) and carry(i));
-- end generate;
-- cout <= carry(4);

end architecture behavioral;
```

**Giải thích:**

* **`library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;`**: Khai báo các thư viện cần thiết.
* `ieee.std_logic_1164.all`: Định nghĩa kiểu `std_logic` và `std_logic_vector` (kiểu dữ liệu phổ biến trong VHDL).
* `ieee.numeric_std.all`: Cung cấp các hàm và kiểu dữ liệu để thực hiện các phép toán số học. Mặc dù không sử dụng trực tiếp trong phiên bản này, nhưng nó thường hữu ích khi bạn cần thực hiện các phép cộng phức tạp hơn hoặc chuyển đổi giữa các kiểu dữ liệu.

* **`entity adder_4bit is ... end entity adder_4bit;`**: Khai báo entity của mạch cộng.
* `port(...)`: Xác định các cổng vào và ra của mạch.
* `a, b : in std_logic_vector(3 downto 0);`: Hai đầu vào 4 bit. `3 downto 0` chỉ định rằng bit có trọng số lớn nhất là bit 3 và bit có trọng số nhỏ nhất là bit 0.
* `cin : in std_logic;`: Đầu vào carry (carry-in).
* `s : out std_logic_vector(3 downto 0);`: Đầu ra tổng 4 bit.
* `cout : out std_logic;`: Đầu ra carry (carry-out).

* **`architecture behavioral of adder_4bit is ... end architecture behavioral;`**: Khai báo kiến trúc (architecture) của mạch. Kiến trúc `behavioral` mô tả hành vi của mạch.
* `signal carry : std_logic_vector(4 downto 0);`: Khai báo một tín hiệu nội bộ `carry` là một vector 5 bit để lưu trữ các carry trung gian giữa các full adder.
* **`process (a, b, carry)`**: Khối process nhạy cảm với các tín hiệu `a`, `b`, và `carry`. Bất cứ khi nào một trong các tín hiệu này thay đổi, process sẽ được thực thi lại.
* `carry(0) <= cin;`: Gán giá trị của đầu vào carry `cin` cho `carry(0)`.
* Các dòng code còn lại bên trong process thực hiện các phép toán logic để tính tổng (s) và carry cho từng bit. Công thức cho một full adder là:
* `sum = a xor b xor carry_in`
* `carry_out = (a and b) or (a and carry_in) or (b and carry_in)`
* `cout <= carry(4);`: Gán carry cuối cùng (sau khi cộng bit 3) cho đầu ra `cout`.

* **Phiên bản thay thế sử dụng `generate` statement (đã comment):** Đoạn code này (bên trong comment) sử dụng một `generate` statement để tạo ra 4 full adder giống nhau. Cách này thường ngắn gọn và dễ đọc hơn, đặc biệt khi bạn cần tạo ra nhiều instance của một mạch giống nhau.

**Cách sử dụng:**

1. **Tạo một file VHDL:** Lưu đoạn mã trên vào một file với tên, ví dụ, `adder_4bit.vhd`.
2. **Sử dụng một công cụ tổng hợp và mô phỏng:** Bạn cần một công cụ CAD (Computer-Aided Design) như Xilinx Vivado, Intel Quartus Prime, hoặc một công cụ mô phỏng như ModelSim để tổng hợp và mô phỏng mạch của bạn.
3. **Tổng hợp:** Công cụ tổng hợp sẽ chuyển đổi mã VHDL của bạn thành một netlist, mô tả cách các cổng logic và flip-flop sẽ được kết nối để thực hiện chức năng của mạch cộng.
4. **Mô phỏng:** Bạn có thể mô phỏng mạch để xác minh rằng nó hoạt động đúng. Tạo một testbench (một file VHDL khác) để cung cấp các đầu vào khác nhau cho mạch cộng và kiểm tra xem các đầu ra có đúng không.

**Ví dụ Testbench (đơn giản):**

```vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder_4bit_tb is
end entity adder_4bit_tb;

architecture behavioral of adder_4bit_tb is

-- Khai báo tín hiệu để kết nối với adder_4bit
signal a : std_logic_vector(3 downto 0) := (others => '0');
signal b : std_logic_vector(3 downto 0) := (others => '0');
signal cin : std_logic := '0';
signal s : std_logic_vector(3 downto 0);
signal cout : std_logic;

begin

-- Instantiation của Unit Under Test (UUT) - adder_4bit
uut: entity work.adder_4bit
port map (
a => a,
b => b,
cin => cin,
s => s,
cout => cout
);

-- Quá trình testbench - cung cấp các đầu vào và kiểm tra đầu ra
process
begin
-- Test case 1: 0 + 0 + 0
a <= "0000";
b <= "0000";
cin <= '0';
wait for 10 ns;
assert s = "0000" and cout = '0' report "Test Case 1 Failed" severity error;

-- Test case 2: 1 + 1 + 0
a <= "0001";
b <= "0001";
cin <= '0';
wait for 10 ns;
assert s = "0010" and cout = '0' report "Test Case 2 Failed" severity error;

-- Test case 3: 5 + 3 + 1
a <= "0101";
b <= "0011";
cin <= '1';
wait for 10 ns;
assert s = "1001" and cout = '0' report "Test Case 3 Failed" severity error;

-- Test case 4: 15 + 1 + 0
a <= "1111";
b <= "0001";
cin <= '0';
wait for 10 ns;
assert s = "0000" and cout = '1' report "Test Case 4 Failed" severity error;

-- Kết thúc quá trình mô phỏng
wait;
end process;

end architecture behavioral;
```

Lưu testbench này vào một file, ví dụ `adder_4bit_tb.vhd`. Sau đó, bạn có thể sử dụng công cụ mô phỏng để chạy testbench và xem kết quả. Nếu có bất kỳ assertion nào bị fail, nó sẽ báo lỗi, giúp bạn tìm và sửa lỗi trong code của mình.

**Lưu ý:**

* Phiên bản code này sử dụng phương pháp ripple carry. Đối với các mạch cộng lớn hơn, phương pháp này có thể chậm do độ trễ lan truyền carry. Các kiến trúc adder khác như carry-lookahead adder có thể được sử dụng để cải thiện hiệu suất.
* Code này mô tả hành vi của mạch cộng. Bạn có thể viết code ở mức RTL (Register Transfer Level) chi tiết hơn để kiểm soát cách mạch được triển khai trên phần cứng.
* Testbench rất quan trọng. Hãy viết các test case kỹ lưỡng để đảm bảo mạch của bạn hoạt động chính xác trong mọi tình huống.


   
Trả lờiTrích dẫn