
Phép gán Blocking và Nonblocking trong Verilog
Nắm vững Blocking và Nonblocking giúp các nhà thiết kế Verilog tạo ra mạch số hoạt động đúng như mong muốn.
Khái niệm về phép gán chặn (Blocking) và phép gán không chặn (Nonblocking) là một khái niệm đặc trưng trong các ngôn ngữ mô tả phần cứng. Lý do chính để sử dụng phép gán chặn hoặc không chặn là để mô tả mạch logic tổ hợp hoặc mạch logic tuần tự. Trong phần mềm, các phép gán thường được thực thi tuần tự, từng phép một. Ví dụ, trong đoạn mã C dưới đây:
1
2 LED_on = 0;
3 count = count + 1;
LED_on = 1;
Dòng lệnh thứ hai chỉ được phép thực thi sau khi dòng lệnh đầu tiên hoàn thành. Mặc dù có thể bạn chưa nhận ra, đây là một ví dụ về phép gán chặn. Một phép gán sẽ ngăn không cho phép gán tiếp theo được thực thi cho đến khi phép gán hiện tại hoàn thành. Trong các ngôn ngữ mô tả phần cứng như Verilog, có những đoạn logic có thể được thực thi đồng thời thay vì tuần tự từng dòng một, vì vậy cần có cách để xác định cách các phép gán tương tác với nhau.
<= Phép gán không chặn
= Phép gán chặn
1
2 always @(posedge i_clock)
3 begin
4 r_Test_1 <= 1'b1;
5 r_Test_2 <= r_Test_1;
6 r_Test_3 <= r_Test_2;
endKhối always trong đoạn mã Verilog ở trên sử dụng phép gán không chặn (Nonblocking Assignment), có nghĩa là giá trị 1 sẽ mất 3 chu kỳ xung nhịp để lan truyền từ r_Test_1 đến r_Test_3. Bây giờ hãy xem xét đoạn mã này:
1
2 always @(posedge i_clock)
3 begin
4 r_Test_1 = 1'b1;
5 r_Test_2 = r_Test_1;
6 r_Test_3 = r_Test_2;
endBạn thấy sự khác biệt chứ? Trong khối always ở trên, phép gán chặn (Blocking Assignment) được sử dụng. Trong ví dụ này, giá trị 1 sẽ ngay lập tức được truyền đến r_Test_3. Phép gán chặn ngay lập tức lấy giá trị ở phía bên phải và gán nó cho phía bên trái. Đây là một quy tắc hữu ích khi sử dụng Verilog:
Trong Verilog, nếu bạn muốn tạo mạch logic tuần tự, hãy sử dụng khối always có xung nhịp với các phép gán không chặn. Nếu bạn muốn tạo mạch logic tổ hợp, hãy sử dụng khối always với các phép gán chặn. Cố gắng không trộn lẫn hai loại phép gán này trong cùng một khối always.
Bạn có thể kết hợp cả phép gán không chặn và phép gán chặn trong cùng một khối always. Tuy nhiên, bạn phải cẩn thận khi làm điều này! Trên thực tế, việc xác định một phép gán chặn trong khối always được điều khiển bằng xung nhịp có tạo ra Flip-Flop hay không còn tùy thuộc vào công cụ tổng hợp. Nếu có khả năng tín hiệu được đọc trước khi được gán, công cụ sẽ tạo ra logic tuần tự. Nếu không, công cụ sẽ tạo ra logic tổ hợp. Vì lý do này, tốt nhất là nên tách biệt mã tổ hợp và mã tuần tự càng nhiều càng tốt.
Một điểm cuối cùng: bạn cũng nên hiểu ngữ nghĩa của Verilog. Khi nói về phép gán chặn (Blocking Assignment) và phép gán không chặn (Nonblocking Assignment), chúng ta đang đề cập đến các phép gán chỉ được sử dụng trong các thủ tục (always, initial, task, function). Trong các thủ tục, bạn chỉ được phép gán cho kiểu dữ liệu reg. Điều này khác với phép gán liên tục (Continuous Assignment). Phép gán liên tục không thuộc các thủ tục và được sử dụng để cập nhật kiểu dữ liệu wire.




