Hướng Dẫn Lập Trình FPGA các Bài Cơ Bản
Bài 1: Cài đặt Phần Mềm Và Cấu Hình mạch Nạp
Trong loạt bài hướng dẫn cơ bản về lập trình FPGA mình sẽ giới thiệu đến các bạn những ví dụ cơ bản nhất điều khiển led, switch, nút bấm, led 7 thanh, lcd 1602, VGA...
Kit được sử dụng trong bài là loại FPGA do Terasic sản xuất gồm DE1 , DE2 - 35, DE2 - 70. Trước khi vào bước lập trình thì mình khuyên các bạn nên đọc qua sematic của 1 trong những loại Kit mà mình nêu trên ( cũng k quan trọng ai lười có thể bỏ qua :D ) để hiểu được những thành phần cơ bản như nguồn, các ngoại vi....
Công cụ lập trình ở đây mình dùng Quartus 9.1 bản này đã gồm đầy đủ các chức năng và tương đối nhẹ ( 1,4Gb ) ngôn ngữ mình sử dụng là Verilog. Trong thời gian tới sẽ cố gắng tìm hiểu VHDL để giới thiệu với các bạn.
Đầu tiên các bạn dowload Quartus 9.1 tại đây, click vào dòng như hình dưới
Kit được sử dụng trong bài là loại FPGA do Terasic sản xuất gồm DE1 , DE2 - 35, DE2 - 70. Trước khi vào bước lập trình thì mình khuyên các bạn nên đọc qua sematic của 1 trong những loại Kit mà mình nêu trên ( cũng k quan trọng ai lười có thể bỏ qua :D ) để hiểu được những thành phần cơ bản như nguồn, các ngoại vi....
Công cụ lập trình ở đây mình dùng Quartus 9.1 bản này đã gồm đầy đủ các chức năng và tương đối nhẹ ( 1,4Gb ) ngôn ngữ mình sử dụng là Verilog. Trong thời gian tới sẽ cố gắng tìm hiểu VHDL để giới thiệu với các bạn.
Đầu tiên các bạn dowload Quartus 9.1 tại đây, click vào dòng như hình dưới
Sau khi tải thành công các bạn chạy file và tiến hành cài đặt.
Tiếp theo là chọn các phần mềm bạn muốn cài gồm 3 phần mềm : Quartus II, Nios II, ModelSim ở đây mình khuyên bạn cài Quartus và ModelSim thôi nhé, sau đó tiến hành cài đặt như bình thường.
Sau khi cài đặt thành công các bạn mở phần mềm ngoài destop (hoặc vào all programs trong nút starts)
Mình sẽ giới thiệu qua về tạo project trong quartus.
1. Chuẩn bị 1 folder mới để đảm bảo bạn quản lý project của mình dễ dàng hơn, ví dụ mình sẽ đặt ở ổ D:\Project Altera. Đây là nơi lưu các project của bạn, tiếp theo bạn tạo folder test để làm ví dụ đầu tiên.
2. Mở Quartus vào file -> New Project Wizard
Sau khi cài đặt thành công các bạn mở phần mềm ngoài destop (hoặc vào all programs trong nút starts)
Mình sẽ giới thiệu qua về tạo project trong quartus.
1. Chuẩn bị 1 folder mới để đảm bảo bạn quản lý project của mình dễ dàng hơn, ví dụ mình sẽ đặt ở ổ D:\Project Altera. Đây là nơi lưu các project của bạn, tiếp theo bạn tạo folder test để làm ví dụ đầu tiên.
2. Mở Quartus vào file -> New Project Wizard
Lưu ý phải nhớ tên module đã nhập trong ô thứ 2 vì tên này sẽ được set làm module top-level (sẽ trình bày ở bài sau) ví dụ mình nhập ô thứ 2 là mux2to1
Nhập xong thì next 2 lần sẽ hiện lên khung chọn chip ở đây mình sử dụng Kit DE2-70 thì chip là Cyclone II và loại EP2C70F896C6 ( bước chọn chip rất quan trọng nếu bạn làm việc với KIT ) tiếp tục next và kết thúc
Vậy là project đã tạo xong bây giờ mình sẽ tiếp tục tạo file verilog để lập trình, vào file -> New -> Verilog HDL file 1 page sẽ hiện ra nơi chúng ta có thể lập trình.
Viết ví dụ đầu tiên như hình dưới và test thử nếu 0 errors là bạn đã thành công với chương trình đầu tiên
Nhập xong thì next 2 lần sẽ hiện lên khung chọn chip ở đây mình sử dụng Kit DE2-70 thì chip là Cyclone II và loại EP2C70F896C6 ( bước chọn chip rất quan trọng nếu bạn làm việc với KIT ) tiếp tục next và kết thúc
Vậy là project đã tạo xong bây giờ mình sẽ tiếp tục tạo file verilog để lập trình, vào file -> New -> Verilog HDL file 1 page sẽ hiện ra nơi chúng ta có thể lập trình.
Viết ví dụ đầu tiên như hình dưới và test thử nếu 0 errors là bạn đã thành công với chương trình đầu tiên
BÀI 2: Cơ bản về ngôn ngữ VERilog
Để thực hành các bài Lab do Altera cung cấp ngôn ngữ chúng ta sử dụng ở đây là verilog, trong bài này mình sẽ giới thiệu cơ bản để các bạn có thể lập trình bằng verilog, mình không hướng dẫn các bạn mô phỏng bằng quartus nhé (nếu quan tâm có thể dowload tài liệu Giáo trình thực hành Kit DE2 ).
Trong ví dụ mà Bài 1 phía trên mình có giới thiệu qua bây giờ mình sẽ phân tích lại ví dụ đó.
Trong ví dụ mà Bài 1 phía trên mình có giới thiệu qua bây giờ mình sẽ phân tích lại ví dụ đó.
1. Dòng 1 là dòng khai báo tên module cú pháp như sau module tenmodule ( các đầu vào đầu ra); ( chú ý các từ khóa của verilog không được viết hoa, tên module top-level phải trùng với tên module lúc tạo project )
Ví dụ : module and (a,b,out);
2. Khai báo input ở ví dụ trên a,b,sel là các đầu vào 1 bit, nếu đầu vào là 8 bit chúng ta khai báo như sau:
input [7:0] a,b,sel; // Khai báo này tương đương với 3 biến a,b,sel đều cùng là 8 bit
3. Tương tự dòng này dùng để khai báo output, với ví dụ trên đầu ra cũng là 1 bit, cách khai báo cho biến nhiều bit tương tự như với input.
4. Sau khi khai báo input và output thì phần này là phần chúng ta lập trình cho sự phụ thuộc đầu ra với các đầu vào, để làm tốt phần này chúng ta phải có kiến thức về C, biết cách sử dụng &,~,!...
assign out=sel?a:b;
trong verilog hỗi trợ 2 kiểu là Wire và Reg, các bạn cứ hiểu thế này cho đơn giản. Muốn gán cho Wire thì phải dùng từ khóa assgin còn gán cho Reg thì phải trong thủ tục always.
Khi khai báo output mặc định sẽ là kiểu Wire còn muốn là Reg ta khai báo như sau: output reg out;
5. endmodule từ khóa bắt buộc kết thúc 1 module
Vậy là mình đã giới thiệu qua cho các bạn về cách viết 1 module đơn giản trong Verilog bài sau mình sẽ bắt đầu hướng dẫn thực hành theo 10 bài Lab của Altera cung cấp kèm theo Kit DE2- 70.
Dowload tài liệu:
Bài 3: Hướng dẫn thực hành Lab 1 Altera
Giáo trình thực hành Kit DE2
Ví dụ : module and (a,b,out);
2. Khai báo input ở ví dụ trên a,b,sel là các đầu vào 1 bit, nếu đầu vào là 8 bit chúng ta khai báo như sau:
input [7:0] a,b,sel; // Khai báo này tương đương với 3 biến a,b,sel đều cùng là 8 bit
3. Tương tự dòng này dùng để khai báo output, với ví dụ trên đầu ra cũng là 1 bit, cách khai báo cho biến nhiều bit tương tự như với input.
4. Sau khi khai báo input và output thì phần này là phần chúng ta lập trình cho sự phụ thuộc đầu ra với các đầu vào, để làm tốt phần này chúng ta phải có kiến thức về C, biết cách sử dụng &,~,!...
assign out=sel?a:b;
trong verilog hỗi trợ 2 kiểu là Wire và Reg, các bạn cứ hiểu thế này cho đơn giản. Muốn gán cho Wire thì phải dùng từ khóa assgin còn gán cho Reg thì phải trong thủ tục always.
Khi khai báo output mặc định sẽ là kiểu Wire còn muốn là Reg ta khai báo như sau: output reg out;
5. endmodule từ khóa bắt buộc kết thúc 1 module
Vậy là mình đã giới thiệu qua cho các bạn về cách viết 1 module đơn giản trong Verilog bài sau mình sẽ bắt đầu hướng dẫn thực hành theo 10 bài Lab của Altera cung cấp kèm theo Kit DE2- 70.
Dowload tài liệu:
Bài 3: Hướng dẫn thực hành Lab 1 Altera
Giáo trình thực hành Kit DE2
Bài 3: Hướng dẫn thực hành Lab 1 Altera
Trong bài này chúng ta sẽ bắt đầu làm việc với Kit DE2 - 70, các bạn sẽ chuẩn bị Kit, driver USB Blaster ( nếu chưa biết có thể tham khảo cách cài đặt trong tài liệu Giáo trình thực hành Kit DE2 )
Dowload tài liệu hướng dẫn thực hành Lab 1 tại đây, file gán chân DE2 - 70 tại đây
Mọi hướng dẫn đều có trong tài liệu mình chỉ chủ yếu giải thích code
Part 1:
Bước 1: tạo project với tên module là part1 (theo hướng dẫn bài 1)
Bước 2: Gõ Code
chú ý phải đặt tên biến đầu vào và đầu ra theo file gán chân của DE2- 70 ở trên SW thay bằng iSW, LEDR thay bằng oLEDR
Part2:
ở đây mình giải thích thêm về biểu thức assign oLEDG = iSW[17]?iSW[15:8]:iSW[7:0];
nếu các bạn đã học C thì sẽ được học cú pháp sau a = biểu thức 1 ? biểu thức 2: biểu thức 3. khi biểu thức 1 đúng ( nghĩa là mức logic 1) thì a= biểu thức 2 và ngược lại khi biểu thức 1 sai ( logic 0 ) thì a= biểu thức 3.
Part3:
đoạn code bên trên always @ (iSW[17:15]) có nghĩa là khi 3 switch [17 : 15] thay đổi thì giá trị đầu ra sẽ thay đổi
cấu trúc
case (tham số)
các sự kiện tham số
default :
endcase
để lựa chọn đầu ra theo các trường hợp (cái này dễ mình k giải thích nhé )
Bài hôm nay kết thúc ở đây nhé, hôm sau mình sẽ giới thiệu thêm về Led 7 thanh.
code mẫu Lab 1 dowload tại đây (code của anh K54) mình nghĩ các bạn tự viết lại sẽ ngắn gọn và hiểu bài hơn
Trong bài này chúng ta sẽ bắt đầu làm việc với Kit DE2 - 70, các bạn sẽ chuẩn bị Kit, driver USB Blaster ( nếu chưa biết có thể tham khảo cách cài đặt trong tài liệu Giáo trình thực hành Kit DE2 )
Dowload tài liệu hướng dẫn thực hành Lab 1 tại đây, file gán chân DE2 - 70 tại đây
Mọi hướng dẫn đều có trong tài liệu mình chỉ chủ yếu giải thích code
Part 1:
Bước 1: tạo project với tên module là part1 (theo hướng dẫn bài 1)
Bước 2: Gõ Code
- module part1 (SW, LEDR);
- input [17:0] SW; // các công tắc gạt
- output [17:0] LEDR; // các LEDs đỏ
- assign LEDR = SW;
- endmodule
chú ý phải đặt tên biến đầu vào và đầu ra theo file gán chân của DE2- 70 ở trên SW thay bằng iSW, LEDR thay bằng oLEDR
Part2:
- module part2 (iSW,oLEDR,oLEDG);
- input [17:0] iSW;
- output [17:0]oLEDR;
- output [7:0] oLEDG;
- assign oLEDG = iSW[17]?iSW[15:8]:iSW[7:0];
- assign oLEDR = iSW;
- endmodule
ở đây mình giải thích thêm về biểu thức assign oLEDG = iSW[17]?iSW[15:8]:iSW[7:0];
nếu các bạn đã học C thì sẽ được học cú pháp sau a = biểu thức 1 ? biểu thức 2: biểu thức 3. khi biểu thức 1 đúng ( nghĩa là mức logic 1) thì a= biểu thức 2 và ngược lại khi biểu thức 1 sai ( logic 0 ) thì a= biểu thức 3.
Part3:
- module part3(iSW,oLEDG,oLEDR);
- input [17:0] iSW;
- output reg [2:0] oLEDG; // LED bao dau ra
- output [17:0] oLEDR; // LED bao SW
- always @ (iSW[17:15]) // iSW[17:15] tin hieu chon
- begin
- case (iSW[17:15])
- 3'b000 : oLEDG = iSW[14:12]; // iSW[14:12] dau ra U-dau vao
- 3'b001 : oLEDG = iSW[11:9]; // iSW[11:9] dau ra V-dau vao
- 3'b010 : oLEDG = iSW[8:6]; // iSW[8:6] dau ra W -dau vao
- 3'b011 : oLEDG = iSW[5:3]; // iSW[5:3] dau ra X-dau vao
- default : oLEDG = iSW[2:0]; // iSW[3:0] dau ra Y-dau vao
- endcase
- end
- assign oLEDR = iSW;
- endmodule
đoạn code bên trên always @ (iSW[17:15]) có nghĩa là khi 3 switch [17 : 15] thay đổi thì giá trị đầu ra sẽ thay đổi
cấu trúc
case (tham số)
các sự kiện tham số
default :
endcase
để lựa chọn đầu ra theo các trường hợp (cái này dễ mình k giải thích nhé )
Bài hôm nay kết thúc ở đây nhé, hôm sau mình sẽ giới thiệu thêm về Led 7 thanh.
code mẫu Lab 1 dowload tại đây (code của anh K54) mình nghĩ các bạn tự viết lại sẽ ngắn gọn và hiểu bài hơn
BÀI 4 : HIỂN THỊ LED 7 THANH
Nếu đã tìm hiểu về FPGA chắc hẳn các bạn đã biết qua về led 7 thanh, tác dụng của led 7 thanh là hiển thị số 0 - > 9 ( có thể mở rộng để hiện thị 0 - > F )
Trong bài này mình sẽ hướng dẫn các bạn hiển thị led 7 thanh với đầu vào là mã BCD 4 bit đầu ra là 7 cái thanh của cái led 7 thanh ( nghe hơi củ chuối ) đại loại nó là 7 bit.
4 bit đầu vào là 4 switch đầu ra chính là HEX0 ( Kit DE2 - 70 có 8 HEX trong bài này mình dùng HEX0 thôi nhá )
đầu tiên chung ta xem xét 1 chút về led 7 thanh
Nếu đã tìm hiểu về FPGA chắc hẳn các bạn đã biết qua về led 7 thanh, tác dụng của led 7 thanh là hiển thị số 0 - > 9 ( có thể mở rộng để hiện thị 0 - > F )
Trong bài này mình sẽ hướng dẫn các bạn hiển thị led 7 thanh với đầu vào là mã BCD 4 bit đầu ra là 7 cái thanh của cái led 7 thanh ( nghe hơi củ chuối ) đại loại nó là 7 bit.
4 bit đầu vào là 4 switch đầu ra chính là HEX0 ( Kit DE2 - 70 có 8 HEX trong bài này mình dùng HEX0 thôi nhá )
đầu tiên chung ta xem xét 1 chút về led 7 thanh
Mình giới thiệu Led 7 thanh anot chung nhé ( anot chung thì 0 là sáng, katot chung thì 1 là sáng nhá)
ví dụ mình muốn hiển thị số 0 chẳng hạng thì
HEX[6] =1 còn các HEX[5:1] = 0 ( ok dễ hiểu vãi )
chú ý còn cái này mình muốn nhắc thêm
ví dụ nếu bạn khai báo là output reg [0 :6]HEX0; thì muốn hiển thị số 0 bạn sẽ gán như sau HEX0 = 7'b0000001;
nếu bạn khai báo output reg [6:0]HEX0; thì hiển thị số 0 bạn sẽ gán như sau HEX0 = 7'b1000000;
tương tự bạn làm với số 1 - > 9 nhé!
ví dụ mình muốn hiển thị số 0 chẳng hạng thì
HEX[6] =1 còn các HEX[5:1] = 0 ( ok dễ hiểu vãi )
chú ý còn cái này mình muốn nhắc thêm
ví dụ nếu bạn khai báo là output reg [0 :6]HEX0; thì muốn hiển thị số 0 bạn sẽ gán như sau HEX0 = 7'b0000001;
nếu bạn khai báo output reg [6:0]HEX0; thì hiển thị số 0 bạn sẽ gán như sau HEX0 = 7'b1000000;
tương tự bạn làm với số 1 - > 9 nhé!
Code mẫu
các bạn có thể thực hành với part 4,5,6 của Lab 1 để biết thêm nhé.
Tài liệu Lab 2 và Code mẫu các bạn có thể dowload tại đây
- module display_number (SW,HEX);
- input [3:0] SW;
- output reg [0:6] HEX;
- always @ (SW)
- case (SW)
- 4'b0000 : HEX = 7'b0000001;
- 4'b0001 : HEX = 7'b1001111;
- 4'b0010 : HEX = 7'b0010010;
- 4'b0011 : HEX = 7'b0000110;
- 4'b0100 : HEX = 7'b1001100;
- 4'b0101 : HEX = 7'b0100100;
- 4'b0110 : HEX = 7'b1100000;
- 4'b0111 : HEX = 7'b0001111;
- 4'b1000 : HEX = 7'b0000000;
- 4'b1001 : HEX = 7'b0001100;
- default : HEX = 7'b0000001; // trang thai ban dau la 0
- endcase
- endmodule
các bạn có thể thực hành với part 4,5,6 của Lab 1 để biết thêm nhé.
Tài liệu Lab 2 và Code mẫu các bạn có thể dowload tại đây
BÀI 5 : HƯỚNG DẪN CHIA TẦN SỐ XUNG CLOCK
Giả sử chúng ta cần phải lập trình cứ sau 1s Led 7 thanh hiển thị từ số 0 - > 9 với 1 xung clock 50Mhz thì chúng ta phải làm như thế nào
điều đầu tiên chúng ta cần biết muốn sự kiện xảy ra sau 1s chúng ta phải có 1 xung 1hz (T = 1/f = 1/1 =1s dễ nhưng mình sẽ viết cho bạn nào chưa hiểu )
để đơn giản mình sẽ hướng dẫn các bạn chuyển 1 xung 10 Hz thành xung 1Hz
Giả sử chúng ta cần phải lập trình cứ sau 1s Led 7 thanh hiển thị từ số 0 - > 9 với 1 xung clock 50Mhz thì chúng ta phải làm như thế nào
điều đầu tiên chúng ta cần biết muốn sự kiện xảy ra sau 1s chúng ta phải có 1 xung 1hz (T = 1/f = 1/1 =1s dễ nhưng mình sẽ viết cho bạn nào chưa hiểu )
để đơn giản mình sẽ hướng dẫn các bạn chuyển 1 xung 10 Hz thành xung 1Hz
1 xung bao gồm cạnh lên và cạnh xuống. nếu xung 10hz thì chu kì của nó là 0.1s muốn có xung 1s ta phải có 10 chu kì của xung 10Mhz. nhưng để ý trên hình thì tần số 1hz gồm 2 mức logic 1 và 0 mỗi mức logic này ứng với 5 chu kì của xung 10hz.
Tư duy lập trình của chúng ta sẽ như sau: xung 10Hz là clock_in, xung đầu ra 1Hz là clock_out cần 1 biến đếm cứ 5 chu kì thi clock_out đảo mức logic vậy ta sẽ đếm từ 0 - > 4. Công thức đếm như sau xung đầu vào aHz xung đầu ra bHz thì sẽ phải đếm từ a/2b quá đơn giản. Mình sẽ viết code như sau:
Tại sao biến counter của mình lại 3 bit, đơn giản vì muốn đếm từ 0 - 4 thì cần 3 bit chứ sao :)))))))))
posedge clk_in , từ khóa posedge là khi sườn dương của xung clock thì nó sẽ thực hiện hàm bên trong always, mình nói luôn là xung clock thì dùng posedge còn nút bấm thì dùng negedge ( sườn âm ) bài sau mình sẽ giới thiệu.
Vậy là mình đã hướng dẫn các bạn xong bài chia tần, hãy tự code với đề bài mà mình đưa ra ở bên trên với bài đếm từ 0 - 9 sau 1s
Code tham khảo đếm từ 0 - 9 sau 1s dowload tại đây
Tư duy lập trình của chúng ta sẽ như sau: xung 10Hz là clock_in, xung đầu ra 1Hz là clock_out cần 1 biến đếm cứ 5 chu kì thi clock_out đảo mức logic vậy ta sẽ đếm từ 0 - > 4. Công thức đếm như sau xung đầu vào aHz xung đầu ra bHz thì sẽ phải đếm từ a/2b quá đơn giản. Mình sẽ viết code như sau:
- module chiatan (clk_in,clk_out);
- input clk_in;
- output reg clk_out;
- reg [2:0] counter;
- always @ (posedge clk_in)
- begin
- if(counter==4)
- begin
- counter=0;
- clk_out =!clk_out;
- end
- else
- counter = counter +1'b1;
- end
- endmodule
Tại sao biến counter của mình lại 3 bit, đơn giản vì muốn đếm từ 0 - 4 thì cần 3 bit chứ sao :)))))))))
posedge clk_in , từ khóa posedge là khi sườn dương của xung clock thì nó sẽ thực hiện hàm bên trong always, mình nói luôn là xung clock thì dùng posedge còn nút bấm thì dùng negedge ( sườn âm ) bài sau mình sẽ giới thiệu.
Vậy là mình đã hướng dẫn các bạn xong bài chia tần, hãy tự code với đề bài mà mình đưa ra ở bên trên với bài đếm từ 0 - 9 sau 1s
Code tham khảo đếm từ 0 - 9 sau 1s dowload tại đây
BÀI 6: ĐIỀU KHIỂN VỚI NÚT BẤM ( KEY )
Bài hôm trước mình có yêu cầu các bạn lập trình đếm từ 0 - 9 sau 1s, mình sẽ nói qua về phong cách lập trình vì càng về sau các module sẽ càng phức tạp.
Ví dụ các bạn thử tưởng tượng với yêu cầu như vậy thì đầu vào là gì và đầu ra là gì, à thì đầu vào là xung clock cứ sau 1s nó tăng lên 1 và đầu ra là led 7 thanh.
muốn sau 1s thì ta lại phải tạo tần số 1Hz, và để đếm từ 0 - 9 thì ta lại cần 1 biến counter, vậy trong cái module top-level thì ngoài đầu vào và đầu ra ta sẽ có 2 cái biến trung gian là 2 biến kiểu Wire hoặc Reg
Bài hôm trước mình có yêu cầu các bạn lập trình đếm từ 0 - 9 sau 1s, mình sẽ nói qua về phong cách lập trình vì càng về sau các module sẽ càng phức tạp.
Ví dụ các bạn thử tưởng tượng với yêu cầu như vậy thì đầu vào là gì và đầu ra là gì, à thì đầu vào là xung clock cứ sau 1s nó tăng lên 1 và đầu ra là led 7 thanh.
muốn sau 1s thì ta lại phải tạo tần số 1Hz, và để đếm từ 0 - 9 thì ta lại cần 1 biến counter, vậy trong cái module top-level thì ngoài đầu vào và đầu ra ta sẽ có 2 cái biến trung gian là 2 biến kiểu Wire hoặc Reg
Bạn nhìn vào hình bên trên, cái khung màu đỏ chính là 1 module top-level gồm 3 module con nhỏ, bạn thấy rằng module top thì đầu vào là iCLK_50 (xung 50Mhz) đầu ra là oHEX0_D (led 7 thanh) còn 2 cái Wire (2 dây đen trung gian giữa 3 module nhỏ ) chính là 2 biến clock và counter như mình đã trình bày ở trên, vậy nên trước khi viết code bạn phải biết module chính gồm những module nhỏ nào, các biến wire cần thêm vào là gì... cái này phải tưởng tượng chứ k ai dậy được các bạn đâu nhé :D
Code muốn tìm hiểu bạn dowload ở cuối bài 4 giờ sẽ quay trở lại để nói về KEY
Nút bấm khi bấm xuống tức là làm cho nút bấm nối đất ( mình chỉ nói trường hợp ứng với KIT thôi chứ thiết kế bấm là nối nguồn cũng đc nhé )
đế lập trình cho 1 sự kiện khi nút bấm xảy ra ta dùng thủ tục always với cú pháp như sau:
always @ ( negedge tennutbam )
begin
if( ! tennutbam ) // bắt sự kiện nút bấm về 0
// Code sự kiện nút bấm
end
mình sẽ lấy ví dụ như thế này để bạn hình dung khi nút được bấm xuống thì reset chẳng hạn
như các bạn thấy khi nút reset được bấm thì đầu ra được reset về 0
chắc sẽ khá nhiều bạn thắc mắc về dòng số 9, mình sẽ giải thích như sau: Verilog cung cấp gán theo khối ( "=" blocking) và không theo khối ( " <= " un-blocking) cái bên trên mình sử dụng un-blocking.
Ví dụ 2 câu lệnh như sau:
if(out==9) out = 0; //khi out = 9 nó sẽ là 0 luôn tức là nó k có số 9 nhé.
if(out==9) out <= 0; //khi out = 9 thì nó vẫn sẽ là 9 và sau khi clock tiếp theo nó mới về 0
Bạn có thể làm lại bài tập mình đưa ở Bài 4 với yêu cầu như sau : khi bấm 1 nút led 7 thanh sẽ hiển thị từ số 0 đến 9.
Code mình sẽ up sau :)
Nút bấm khi bấm xuống tức là làm cho nút bấm nối đất ( mình chỉ nói trường hợp ứng với KIT thôi chứ thiết kế bấm là nối nguồn cũng đc nhé )
đế lập trình cho 1 sự kiện khi nút bấm xảy ra ta dùng thủ tục always với cú pháp như sau:
always @ ( negedge tennutbam )
begin
if( ! tennutbam ) // bắt sự kiện nút bấm về 0
// Code sự kiện nút bấm
end
mình sẽ lấy ví dụ như thế này để bạn hình dung khi nút được bấm xuống thì reset chẳng hạn
- module counter (clock,key_reset,out);
- input key_reset;
- output reg [3:0] out;
- always @ (posedge clock or negedge key_reset)
- begin
- if(!key_reset) out = 4'b0000; // có thể viết if (key_reset==0) cũng đúng nhưng viết thế nào cho nguy hiểm tí nhé :))))
- else
- begin
- if(out==9) out <= 0;
- else out = out +1;
- end
- end
- endmodule
như các bạn thấy khi nút reset được bấm thì đầu ra được reset về 0
chắc sẽ khá nhiều bạn thắc mắc về dòng số 9, mình sẽ giải thích như sau: Verilog cung cấp gán theo khối ( "=" blocking) và không theo khối ( " <= " un-blocking) cái bên trên mình sử dụng un-blocking.
Ví dụ 2 câu lệnh như sau:
if(out==9) out = 0; //khi out = 9 nó sẽ là 0 luôn tức là nó k có số 9 nhé.
if(out==9) out <= 0; //khi out = 9 thì nó vẫn sẽ là 9 và sau khi clock tiếp theo nó mới về 0
Bạn có thể làm lại bài tập mình đưa ở Bài 4 với yêu cầu như sau : khi bấm 1 nút led 7 thanh sẽ hiển thị từ số 0 đến 9.
Code mình sẽ up sau :)
Bài 7: Chuyển Đổi MÔ Hình Trạng Thái (FSM)
Trong verilog mô hình trạng thái sẽ được sử dụng rất nhiều với những module yêu cầu nhiều tín hiệu điều khiển. Ngày xưa học trong điện tử số chắc các bạn đã tìm hiểu qua mô hình moore mealy, cũng chả cần phân biệt làm gì vì khi lập trình bạn đã quen thì cái nào cũng làm được hết.
Ví dụ như sau muốn hiển thị 1 kí tự lên LCD, đầu tiên là LCD đang ở trạng thái chờ tức là các tín hiệu điều khiển bằng 0, sau đó 1 xung clock đầu vào lcd báo hiệu bằng 1 tín hiệu LCD_ready nghĩa là LCD đã sẵn sàng, lúc này tín hiệu LCD_enable được kích hoạt, dữ liệu từ DATA BUS sẽ được đưa vào LCD_DATA để hiển thị, quá trình kết thúc LCD_ready và LCD_enable lại trở lại trạng thái chờ và đợi quá trình tiếp theo. ( các bạn cứ đọc qua để hiểu tại sao FSM quan trọng chứ chưa cần hiểu )
Ví dụ như sau muốn hiển thị 1 kí tự lên LCD, đầu tiên là LCD đang ở trạng thái chờ tức là các tín hiệu điều khiển bằng 0, sau đó 1 xung clock đầu vào lcd báo hiệu bằng 1 tín hiệu LCD_ready nghĩa là LCD đã sẵn sàng, lúc này tín hiệu LCD_enable được kích hoạt, dữ liệu từ DATA BUS sẽ được đưa vào LCD_DATA để hiển thị, quá trình kết thúc LCD_ready và LCD_enable lại trở lại trạng thái chờ và đợi quá trình tiếp theo. ( các bạn cứ đọc qua để hiểu tại sao FSM quan trọng chứ chưa cần hiểu )
Hình bên trên chúng ta có 4 trang thái, chúng ta sẽ lập trình sao cho khi có bit 1 vào thì nhảy lên trạng thái tiếp theo và 0 thì quay lại.
đầu vào chính là 1 bit (mũi tên xanh) đầu ra là 2 bit (mũi tên đỏ) đấy là cách xác định đầu vào đầu ra của FSM (quá đơn giản )
4 trạng thái thì ta dùng tối thiểu 2 bit để biểu diễn: state 1 là 0, state 2 là 1... hoặc bạn có thể mô hình tùy thích
vào bước code nhé, nếu các bạn có tìm hiểu qua thì có rất nhiều hướng dẫn về viết verilog cho FSM nhưng mình sẽ viết theo cách này đảm bảo nhanh k rườm rà :)
module FSM luôn có đầu vào là clock.
Code mẫu FSM dowload tại đây
Trên đây là tất cả các kiến thức cơ bản để lập trình verilog, bài hôm sau mình sẽ đi vào các module nâng cao.
đầu vào chính là 1 bit (mũi tên xanh) đầu ra là 2 bit (mũi tên đỏ) đấy là cách xác định đầu vào đầu ra của FSM (quá đơn giản )
4 trạng thái thì ta dùng tối thiểu 2 bit để biểu diễn: state 1 là 0, state 2 là 1... hoặc bạn có thể mô hình tùy thích
vào bước code nhé, nếu các bạn có tìm hiểu qua thì có rất nhiều hướng dẫn về viết verilog cho FSM nhưng mình sẽ viết theo cách này đảm bảo nhanh k rườm rà :)
- always @ (posedge clock or negedge reset)
- begin
- if(!reset)
- begin
- bit_out = 2'b10; // trang thai mac dinh la state 1
- state = 0; //state 1 nhung minh ma hoa no la 00
- end
- else
- begin
- case(state)
- 0: begin
- bit_out <= 2'b10;
- if(bit_next)state <= 1;
- else state <=3;
- end
- 1: begin
- bit_out <= 2'b11;
- if(bit_next)state <=2;
- else state <=0;
- end
- 2: begin
- bit_out <=2'b00;
- if(bit_next)state <=3;
- else state <=1;
- end
- 3: begin
- bit_out <=2'b01;
- if(bit_next)state <=0;
- else state <=2;
- end
- endcase
- end
- end
module FSM luôn có đầu vào là clock.
Code mẫu FSM dowload tại đây
Trên đây là tất cả các kiến thức cơ bản để lập trình verilog, bài hôm sau mình sẽ đi vào các module nâng cao.