Khác biệt giữa reg và wire trong Verilog là gì?
Sự khác biệt chính giữa `reg` và `wire` trong Verilog nằm ở cách chúng lưu trữ và truyền dữ liệu:
**Wire:**
* **Mô tả:** `wire` đại diện cho một kết nối vật lý giữa các phần tử trong mạch. Nó không lưu trữ giá trị; nó chỉ đơn giản là truyền tín hiệu từ điểm này sang điểm khác.
* **Tính chất:**
* **Không lưu trữ:** `wire` không có bộ nhớ. Giá trị của nó thay đổi ngay lập tức khi tín hiệu được kết nối với nó thay đổi.
* **Gán liên tục:** Giá trị của `wire` được xác định bởi gán liên tục (sử dụng `assign`).
* **Sử dụng:** Sử dụng để kết nối các cổng logic, module, và các thành phần khác trong mạch.
* **Ví dụ:**
```verilog
wire a, b, c;
assign c = a & b; // c sẽ thay đổi ngay lập tức khi a hoặc b thay đổi.
```
**Reg:**
* **Mô tả:** `reg` đại diện cho một biến có thể lưu trữ giá trị. Nó hoạt động như một bộ nhớ tạm thời.
* **Tính chất:**
* **Lưu trữ:** `reg` có thể giữ một giá trị cho đến khi nó được gán một giá trị mới.
* **Gán tuần tự:** Giá trị của `reg` được gán trong các khối tuần tự (`always` block) sử dụng các câu lệnh gán thủ tục (`<=` trong các khối `always @(posedge clock)`) hoặc (`=` trong các khối `always @*`).
* **Sử dụng:** Thường được sử dụng để mô tả các phần tử lưu trữ như flip-flop, thanh ghi, và bộ nhớ.
* **Ví dụ:**
```verilog
reg q;
always @(posedge clk) begin
q <= d; // q sẽ cập nhật giá trị của d tại cạnh lên của xung clock.
end
```
**Tóm tắt Bảng:**
| Tính chất | Wire | Reg |
| --------------- | ---------------------------------------- | -------------------------------------------- |
| Chức năng | Kết nối, truyền tín hiệu | Lưu trữ giá trị, bộ nhớ tạm thời |
| Lưu trữ | Không | Có |
| Gán giá trị | Liên tục (assign) | Tuần tự (trong `always` block) |
| Sử dụng | Kết nối các thành phần mạch | Mô tả flip-flop, thanh ghi, bộ nhớ |
| Tổng hợp | Thường tổng hợp thành dây dẫn vật lý | Thường tổng hợp thành flip-flop hoặc latch |
**Điểm quan trọng cần nhớ:**
* **`reg` *không phải* luôn luôn là một flip-flop:** Việc sử dụng `reg` không tự động biến nó thành một flip-flop. Nó chỉ là một biến lưu trữ. Cách bạn sử dụng nó trong khối `always` sẽ quyết định cách nó được tổng hợp. Ví dụ, nếu bạn sử dụng `reg` trong một khối `always @*` (combinational logic), nó có thể tổng hợp thành một mạch logic combinational chứ không phải flip-flop.
* **`wire` *không thể* được gán trong `always` block:** `wire` chỉ có thể được gán bằng câu lệnh `assign` bên ngoài `always` block.
* **`output reg`:** Bạn có thể khai báo đầu ra của một module là `reg`. Điều này có nghĩa là đầu ra của bạn sẽ lưu trữ giá trị của nó. Nó thường được sử dụng khi đầu ra được gán trong một khối `always`.
**Ví dụ minh họa:**
```verilog
module example (
input clk,
input d,
input a,
output reg q, // q là một thanh ghi (flip-flop)
output wire y // y là một dây
);
always @(posedge clk) begin
q <= d; // q được cập nhật tại cạnh lên của xung clock
end
assign y = a & q; // y là kết quả của phép AND giữa a và q, thay đổi ngay lập tức khi a hoặc q thay đổi
endmodule
```
Trong ví dụ trên:
* `q` là một `reg` và được gán trong một khối `always` được kích hoạt bởi cạnh lên của xung clock `clk`. Điều này có nghĩa là `q` sẽ giữ giá trị cho đến cạnh lên tiếp theo của clock. Nó sẽ được tổng hợp thành một flip-flop.
* `y` là một `wire` và được gán bằng câu lệnh `assign`. Giá trị của `y` sẽ luôn là kết quả của phép AND giữa `a` và `q`, và nó sẽ thay đổi ngay lập tức khi `a` hoặc `q` thay đổi.
Hiểu sự khác biệt giữa `reg` và `wire` là rất quan trọng để viết mã Verilog chính xác và hiệu quả. Hãy luôn xem xét liệu bạn cần lưu trữ một giá trị hay chỉ cần truyền tín hiệu để chọn loại biến phù hợp.
