Bài 7: Những điểm khác biệt trong lập trình phần cứng so với phần mềm

Bài viết quan trọng nhất cho một nhà thiết kế kỹ thuật số mới

Mọi nhà phát triển phần mềm biết một ngôn ngữ như C hay Java đều có cùng vấn đề khi cố bắt đầu lập trình trong VHDL hoặc Verilog. Ngôn ngữ phần cứng có những khác biệt mà các bạn cần lưu ý, nó hoạt động khác so với những gì chúng ta đã từng làm trong lập trình phần mềm. Nếu bạn mới phát triển phần cứng và đã biết một hoặc hai ngôn ngữ phần mềm nào đó, hãy đọc bài viết này để hiểu hơn về HDL. Bài viết này cung cấp các ví dụ về mã HDL và giải thích cách các mã hoạt động trong lập trình phần mềm và trong lập trình phần cứng để cho bạn thấy sự khác biệt.

Giả định # 1: Tuần tự và song song

Đây có lẽ là sự khác biệt cơ bản nhất giữa ngôn ngữ lập trình phần cứng và phần mềm. Các nhà thiết kế phần mềm lập ra các mã hoạt động tuần tự, nhưng có lẽ họ không nhận ra điều này. Điều này có nghĩa là mã tuần tự là mỗi dòng mã được thực hiện một tại một thời điểm. Ví dụ: Dòng # 2 chỉ có thể thực thi sau khi Dòng # 1 hoàn tất. VHDL và Verilog không cư xử theo cách này! Chúng được gọi là các ngôn ngữ logic song song và tất cả các dòng mã có thể và sẽ thực thi tất cả cùng một lúc.  Đây là một ví dụ minh họa sự khác biệt giữa logic tuần tự và song song. Giả sử một nhà thiết kế muốn bật đèn LED một lần sau mỗi mười chu kỳ đồng hồ.

Mã phần mềm ví dụ:

while (1)
{
  if (count == 9)
  {   
    LED_on = 1;
    count = 0;
  }
  else
  {
    LED_on = 0;
    count = count + 1;
  }
}
Mã VHDL tương đương:
P_INCREMENT : process (clock)
begin
  if rising_edge(clock) then
    if (count < 9) then
      count <= count + 1;
    else
      count <= 0;            
    end if;
  end if;
end process P_INCREMENT;
 
LED_on <= ‘1’ when count = 9 else ‘0’;
Ở mã phần mềm, mỗi dòng được thực thi theo thứ tự, dòng lệnh trước thực thi xong, sau đó dòng tiếp theo mới được phép thực thi. Điều này là không đúng trong VHDL và Verilog, và điều này được thể hiện bằng dòng cuối cùng gán tín hiệu LED_on. Dòng đó sẽ chạy đồng thời với quá trình VHDL. Nó luôn luôn gán một '1' hoặc '0' cho LED_on. Nếu đây là phần mềm, dòng này sẽ chỉ đạt được khi các dòng mã trước đã được thực thi. Một nhà thiết kế kỹ thuật số tốt cần phải luôn luôn nhớ rằng VHDL và Verilog là ngôn ngữ song song.

Giả định # 2: Đối với vòng lặp

Đây là một vấn đề lớn mà các nhà phát triển phần cứng mới có. Ví dụ, trong ngôn ngữ C ta đã từng sử dụng các vòng lặp rất dễ dàng, và có thể chúng ta nghĩ rằng các vòng lặp trong Verilog và VHDL cũng hoạt động như vậy! Thật không may, các vòng lặp trong ngôn ngữ phần cứng KHÔNG hành xử theo cùng một cách như trong phần mềm. Khi chưa hiểu cách các vòng lặp làm việc, bạn không nên sử dụng chúng.

Mã phần mềm ví dụ:

For (int i=0; i<10; i++)
  data[i] = data[i] + 1;
Mã này sẽ lấy mọi giá trị trong mảng “dữ liệu” và tăng nó bằng 1. Đây là mã tương đương trong VHDL:
P_INCREMENT : process (clock)
begin
  if rising_edge(clock) then
    if (index < 10) then
      data[index] <= data[index] + 1;
      index <= index + 1;
    end if;
  end if;
end process P_INCREMENT;

Chúng ta bắt đầu thấy sự khác biệt ở đây, mã C rất gắn, trong khi mã trong VHDL hoặc Verilog dài hơn, thực hiện nhiều công việc hơn. Một điều chắc chắn là: nếu bạn chưa thực hiện ít nhất 3 thiết kế FPGA bạn sẽ không bao giờ sử dụng được các vòng lặp. Vì vậy, suy nghĩ về cách mã bạn viết trong phần mềm có thể được viết lại để không bao giờ sử dụng vòng lặp for trong HDL. Thông thường tất cả những gì bạn cần là thêm một tín hiệu truy cập (như ở ví dụ trên) để làm điều tương tự với vòng lặp for.

Giả định # 3: Thực thi Mã ngay lập tức

Điều này liên quan đến logic song song. Các nhà phát triển phần mềm cần phải nhớ rằng một dòng mã không được thực hiện ngay lập tức, với giá trị của tín hiệu được cập nhật để sử dụng. Một ví dụ dưới đây mô tả chi tiết giả định này với trạng thái thiết bị. Ví dụ dưới đây cho thấy một thói quen khởi tạo cho một số thành phần ngoại vi thường thấy trong lập trình phần mềm, mà không áp dụng trong lập trình phần cứng.

Mã phần mềm ví dụ:

state = INITIALIZE;
data = 5;
state = LOAD_1;
data = 6;
state = LOAD_2;
data = 1;
state = DONE;
data = 0;

KHÔNG Mã phần cứng tương đương: (Mã lỗi)

P_STATE_MACHINE : process (clock)
begin
  if rising_edge(clock) then
    state <= INITIALIZE;
    data <= 5;
    state <= LOAD_1;
    data <= 6;
    state <= LOAD_2;
    data <= 1;
    state <= DONE;
    data <= 0;
  end if;
end process P_STATE_MACHINE;

Biểu diễn phần cứng của mã này bị sai! Vì mỗi dòng trong một tiến trình thực thi đồng thời, data luôn bằng 0 và trạng thái  state luôn bằng DONE. Mã này sẽ không bao giờ thực thi máy trạng thái theo cách nó sẽ làm trong mã phần mềm. Mã đúng trong VHDL:

Mã phần cứng tương đương:

P_STATE_MACHINE : process (clock)
begin
  if rising_edge(clock) then
    if (state == INITIALIZE) then
      data <= 5;
      state <= LOAD_1;
    elsif (state == LOAD_1) then
      data <= 6;
      state <= LOAD_2;
    elsif (state == LOAD_2) then
      data <= 1;
      state <= DONE;
    elsif (state == DONE) then
      data = 0;
    else
      state <= INITIALIZE;
    end if;
  end if;

Ba ví dụ trên là ba vấn đề mà các nhà phát triển phần mềm thường gặp khó khăn khi bắt đầu thiết kế phần cứng với VHDL hoặc Verilog. Ba vấn đề trên luôn luôn trong tâm trí của một nhà thiết kế kỹ thuật số mới. Các câu hỏi về lệnh song sang, các vòng lặp và việc thực thi mã phải luôn được đưa ra xem xét. Cần phải nắm vững những sự khác biệt trong ngôn ngữ phần cứng mới giúp bạn tìm hiểu sau hơn về FPGA.

Chapichuse

Đam mê công nghệ

You may also like...

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *