1. Giới thiệu
Verilog là một trong những ngôn ngữ mô tả phần cứng (HDL), được sử dụng rộng rãi trong thiết kế mạch số. Trong đó, câu lệnh case
là một cú pháp quan trọng để mô tả phân nhánh điều kiện một cách hiệu quả. Đặc biệt, nó thường được sử dụng trong thiết kế máy trạng thái (state machine) và bộ chọn đa kênh (multiplexer).
Bài viết này sẽ giải thích chi tiết về câu lệnh case
trong Verilog, từ cơ bản đến nâng cao, cùng với những lưu ý khi sử dụng. Chúng tôi sẽ đưa ra ví dụ mã nguồn cụ thể để người mới bắt đầu cũng dễ dàng hiểu, vì vậy hãy theo dõi đến cuối bài nhé.
2. Cú pháp cơ bản của câu lệnh case
trong Verilog
Câu lệnh case
là gì?
Câu lệnh case
trong Verilog được dùng để thực thi các xử lý khác nhau dựa trên giá trị điều kiện (selector). Nó tương tự như switch-case
trong ngôn ngữ C, nhưng có một số khác biệt đặc trưng.
Cú pháp cơ bản như sau:
case (biểu_thức)
điều_kiện1: câu_lệnh1;
điều_kiện2: câu_lệnh2;
điều_kiện3: câu_lệnh3;
default: câu_lệnh4; // khi không khớp với bất kỳ điều kiện nào
endcase
Cách sử dụng cơ bản của case
Ví dụ dưới đây minh họa một câu lệnh case
đơn giản: gán tín hiệu khác nhau cho out
tùy theo giá trị 2-bit của sel
.
module case_example(input [1:0] sel, output reg [3:0] out);
always @(*) begin
case (sel)
2'b00: out = 4'b0001;
2'b01: out = 4'b0010;
2'b10: out = 4'b0100;
2'b11: out = 4'b1000;
default: out = 4'b0000; // giá trị mặc định để đảm bảo an toàn
endcase
end
endmodule
Trong đoạn mã này, giá trị của out
thay đổi tùy theo sel
. Việc thêm default
giúp đảm bảo hệ thống vẫn hoạt động ổn định khi nhận đầu vào không mong đợi.
Sự khác biệt giữa case
, casex
và casez
Trong Verilog, ngoài case
còn có các biến thể casex
và casez
. Các biến thể này hoạt động như ký tự đại diện (wildcard), cho phép bỏ qua một số bit nhất định.
Cú pháp | Đặc điểm |
---|---|
case | Yêu cầu so khớp chính xác (mặc định) |
casex | Bỏ qua X (giá trị chưa xác định) và Z (trạng thái trở kháng cao) |
casez | Chỉ bỏ qua Z |
Ví dụ sử dụng casez
:
casez (sel)
2'b1?: out = 4'b1111; // khớp nếu bit cao nhất bằng 1
2'b01: out = 4'b0001;
default: out = 4'b0000;
endcase
Ở đây, 1?
nghĩa là chỉ cần bit cao nhất bằng 1 thì sẽ khớp, bất kể bit thấp hơn.

3. Ví dụ cụ thể về câu lệnh case
Phân nhánh điều kiện cơ bản
Ví dụ sau minh họa bộ giải mã CPU đơn giản: thực hiện thao tác khác nhau dựa trên giá trị của opcode
(8-bit).
module decoder(input [7:0] opcode, output reg [3:0] control_signal);
always @(*) begin
case (opcode)
8'h00: control_signal = 4'b0001; // NOP
8'h01: control_signal = 4'b0010; // ADD
8'h02: control_signal = 4'b0100; // SUB
default: control_signal = 4'b0000; // lệnh không xác định
endcase
end
endmodule
Sử dụng trong máy trạng thái (FSM)
Câu lệnh case
thường được dùng để triển khai máy trạng thái hữu hạn (FSM: Finite State Machine).
typedef enum reg [1:0] {IDLE, RUN, STOP} state_t;
state_t current_state, next_state;
always @(posedge clk) begin
if (reset)
current_state <= IDLE;
else
current_state <= next_state;
end
always @(*) begin
case (current_state)
IDLE: next_state = RUN;
RUN: next_state = STOP;
STOP: next_state = IDLE;
default: next_state = IDLE;
endcase
end
Đoạn mã này mô tả một FSM gồm 3 trạng thái. Khi cần quản lý trạng thái, việc dùng case
giúp mô tả rõ ràng và dễ hiểu hơn.
4. Lưu ý khi sử dụng câu lệnh case
Khi sử dụng câu lệnh case
trong Verilog, cần lưu ý các điểm sau:
1. Luôn viết trường hợp default
Điều quan trọng là phải bao phủ tất cả khả năng đầu vào. Nếu không có default
, quá trình tổng hợp trên FPGA/ASIC có thể sinh ra latch không mong muốn.
2. Cẩn thận với casex
và casez
Các biến thể này có thể khớp sai tín hiệu không mong muốn. Do đó, khi dùng, cần mô phỏng kỹ lưỡng để đảm bảo hoạt động đúng.
casez (sel)
2'b1?: out = 4'b1111; // khớp nếu bit cao nhất bằng 1
2'b01: out = 4'b0001;
default: out = 4'b0000;
endcase
3. Không lạm dụng case
Với các nhánh điều kiện nhỏ, if-else
có thể dễ hiểu và trực quan hơn. case
nên được dùng khi có nhiều lựa chọn cần phân nhánh.
5. Kết luận
Bài viết đã giải thích các điểm chính về câu lệnh case
trong Verilog:
✅ Cú pháp cơ bản và cách hoạt động của case
✅ Sự khác biệt giữa case
, casex
, casez
✅ Ví dụ thực tế: phân nhánh điều kiện & FSM
✅ Lưu ý khi sử dụng case
Khi thiết kế mạch với Verilog, việc sử dụng đúng case
sẽ giúp cải thiện khả năng đọc mã và giảm thiểu lỗi thiết kế. Hãy áp dụng ngay trong dự án của bạn!
Khái niệm Verilog quan trọng tiếp theo nên học
Sau khi nắm vững câu lệnh case
, bạn nên tìm hiểu thêm về câu lệnh always
và sự khác nhau giữa mạch tổ hợp & mạch tuần tự để nâng cao kiến thức.