![[IMG]](https://lh4.googleusercontent.com/-We2LI1nSHeA/VRYpizC7wgI/AAAAAAAACEs/dMfw7YUW57s/w1364-h693-no/4.png)
- Về cơ bản một FSM bao gồm các mạch tổ hợp, tuần tự và đầu ra tổ hợp. Mạch tổ hợp được sử dụng để quyết định các trạng thái tiếp theo của FSM, mạch tuần tự được sử dụng để lưu trữ các trạng thái hiện tại của FSM. Mạch tổ hợp đầu ra: xác định tín hiệu ra của máy trạng thái phụ thuộc vào trạng thái hiện tại và tín hiệu đầu vào.
![[IMG]](https://lh6.googleusercontent.com/-LUwqiPFeI0I/VRYpimWYd6I/AAAAAAAACEo/jKOMlc4lOGQ/w1364-h671-no/2.png)
2, Cấu trúc.
-- Các loại máy trạng thái
- Máy trạng thái có nhiều loại phụ thuộc vào việc code của các bạn(mình trình bày phía dưới).Nhưng dù code theo thì máy trạng thái cũng có 2 loại cấu trúc chính là:
+ Mealy State Machine: Đầu ra của máy trạng thái phụ thuộc vào trạng thái hiện tại và tín hiệu đầu vào.
+ Moore State Machine : Đầu ra của máy trạng thái chỉ phụ thuộc vào trạng thái hiện tại, không phụ thuộc vào tín hiệu đầu vào.
Tùy vào nhu cầu mà chúng ta nên sử dụng loại Mealy hay Moore.Dù cho chúng ta dung loại thì chúng cũng có 3 thành phần cơ bản: Mạch tổ hợp xác định trạng thái kế tiếp (next state), Mạch tổ hợp xác định giá trị ngõ ra và mạch tuần tự lưu giữ trạng thái hiện tại (current state).
-- Encoding Style
- Có nhiều loại code cho máy trạng thái như mình giới thiệu ở trên. Và sau đây là một số loại code cơ bản phụ thuộc vào cách chúng ta biểu diễn trạng thái :
- Mã hóa nhị phân: mỗi trạng thái được biểu diện trong mã nhị phân (tức là 000, 001, 010 ....).
- Mã hóa nhị phân: mỗi trạng thái được thể hiện trong mã nhị phân (tức là 000, 001, 010 ....).
- One Hot: chỉ có một bit là ở mức cao và phần còn lại là mức ở thấp (tức là 0001, 0010, 0100, 1000).
- One Lạnh: chỉ có một bit là ở mức thấp, còn lại là ở mức cao (1110,1101,1011,0111).
** Ở đây mình sẽ ví dụ bộ đếm lên, xuống và dừng khi nhấn nút trong máy trạng thái.
-- Cho tý hình nhỉ:
![[IMG]](https://lh5.googleusercontent.com/-q2FuDl_sFU4/VRYpiMavQNI/AAAAAAAACEk/gUozk6gN3jQ/w1364-h492-no/hi.png)
-- Về cơ bản, chúng ta sẽ có các tín hiệu sau: tín hiệu vào( mình chọn nút nhấn), xung clk, tín hiệu reset và tín hiệu ra.
-- Trong đó:
- clock: là xung nhịp đồng bộ của FSM.
- reset: là tín hiệu reset FSM sau khi mới bật nguồn để FSM vào trạng thái khởi động. Reset đồng bộ tích cực mức cao.
- Tín hiệu vào: một trong 3 nút nhấn điều khiển lên, xuống, dừng.
- Tín hiệu ra: ngõ ra của bộ phát hiện (ngõ ra FSM). Trạng thái mặc định sẽ là đếm lên, sau đó tùy vào tín hiệu vào mà chúng ta cho đếm lên xuống hoặc dừng.

- Trong đó ta có 3 trạng thái chính là đếm lên, lùi và dừng cùng với biểu diễn lần lượt nhị phân là 001, 010,100. Trạng thái 000 mình sẽ mặc định là đếm lên. Chú ý: mình sử dụng loại Moore nha.
- Phân tích:
** Ở trạng thái hiện tại là tiến ( màu đỏ bên trong hình elip, có 3 mũi tên đi ra tương đương với 3 tín hiệu điều khiển đến trạng thái tiếp theo) biểu diễn nhị phân là 001:
o Nếu tín hiệu điều khiển là lùi ( màu đỏ, tương đương với chúng ta nhấn nút 1) thì trạng thái tiếp theo sẽ là trạng thái lui ( biểu diễn nhị phân là 010) cũng là tín hiệu ra output.
o Ngược lại tín hiệu điều khiển là dừng ( tương đương với nhấn nút 2) thì trạng thái tiếp theo sẽ là dừng ( biểu diễn nhị phân là 100) cũng là tín hiệu ra output.
o Còn tín hiệu điều khiển tiến thì trạng thái tiếp theo là tiến.
** Tương tự với trạng thái hiện tại là dừng, lùi: chúng ta cũng có 3 tín hiệu điều khiển và ba trạng thái tiếp theo tùy thuộc vào ba tín hiệu điều khiển đó.
** Sau đây là phần code từng phần:
![[IMG]](https://lh4.googleusercontent.com/-We2LI1nSHeA/VRYpizC7wgI/AAAAAAAACEs/dMfw7YUW57s/w1364-h693-no/4.png)
++ Đoạn code cho “Mạch tổ hợp xác định trạng thái kế tiếp”: ( vòng tròn 1)
MÃ:
always @(*) begin case (state_current) 2'b00 : begin if (nut_t1 == 1'b1) state_next = 2'b01; else if (nut_t2 == 1'b1) state_next = 2'b10; else if (nut_t3 == 1'b1) state_next = 2'b00; else state_next = 2'b00; end 2'b01: begin if (nut_t2 == 1'b1) state_next = 2'b10; else if (nut_t3 == 1'b1) state_next = 2'b00; else if (nut_t1 == 1'b1) state_next = 2'b01; else state_next = 2'b01; end 2'b10: begin if (nut_t3 == 1'b1) state_next = 2'b00; else if (nut_t1 == 1'b1) state_next = 2'b01; else if(nut_t2 == 1'b1) state_next = 2'b10; else state_next = 2'b10; end default state_next = 2'b00; endcase end
MÃ:
always @ (posedge clk, posedge reset ) begin if(reset) state_current <= 2'b00; else state_current <= state_next; end
MÃ:
always @(*) begin case ( state_current ) 2'b00: {R3,R2,R1} = 3'b001; 2'b01: {R3,R2,R1} = 3'b010; 2'b10: {R3,R2,R1} = 3'b100; default {R3,R2,R1} = 3'b000; endcase end
++ Đoạn code cho toàn bộ bài:
MÃ:
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 08:53:39 11/03/2014 // Design Name: PHẠM KIM LUÂN // Module Name: nut3 // Project Name: DEM LEN XUONG, DUNG // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module DEM( clk, reset, nut1_l, nut2_d, nut3_t, Q ); //input input clk; input reset; input nut1_l; input nut2_d; input nut3_t; //output output Q; wire Rs; wire nut_t3; wire nut_t2; wire nut_t1; reg R1; reg R2; reg R3; reg [1:0] state_next; reg [1:0] state_current; reg [28:0] Qs; reg [3:0] Q; reg nut_1; reg nut_2; reg nut_3; // tao xung 1S always @ (posedge clk) begin if (Rs) Qs <= 29'd0; else Qs <= Qs + 29'd1; end assign Rs = (Qs == 29'd50000000) ? 1'b1 : 1'b0; // bo dem 3 nut nhan always @ (posedge clk, posedge reset) begin if(reset) Q <= 4'd0; else begin if( ~Rs ) Q <= Q; else begin case ({R3,R2,R1}) 3'b000 : Q <= Q + 4'd1; // DEM LEN 3'b001 : Q <= Q + 4'd1; //DEM LEM 3'b010 : Q <= Q - 4'd1; //DEM XUONG 3'b100 : Q <= Q ; //DUNG default : Q <= 4'd0; endcase end end end always @ (posedge clk, posedge reset ) begin if(reset) state_current <= 2'b00; else state_current <= state_next; end always @(*) begin case (state_current) 2'b00 : begin if (nut_t1 == 1'b1) state_next = 2'b01; else if (nut_t2 == 1'b1) state_next = 2'b10; else if (nut_t3 == 1'b1) state_next = 2'b00; else state_next = 2'b00; end 2'b01: begin if (nut_t2 == 1'b1) state_next = 2'b10; else if (nut_t3 == 1'b1) state_next = 2'b00; else if (nut_t1 == 1'b1) state_next = 2'b01; else state_next = 2'b01; end 2'b10: begin if (nut_t3 == 1'b1) state_next = 2'b00; else if (nut_t1 == 1'b1) state_next = 2'b01; else if(nut_t2 == 1'b1) state_next = 2'b10; else state_next = 2'b10; end default state_next = 2'b00; endcase end always @(*) begin case ( state_current ) 2'b00: {R3,R2,R1} = 3'b001; 2'b01: {R3,R2,R1} = 3'b010; 2'b10: {R3,R2,R1} = 3'b100; default {R3,R2,R1} = 3'b000; endcase end // CẮT NGẮN MƯC CAO CỦA NUT NHẤN ĐỂ VỪA ĐỦ MỘT CHU KÌ XUNG CLK. always @ (posedge clk) begin nut_1 <= nut1_l; end assign nut_t1 = (~nut_1) & nut1_l; always @ (posedge clk) begin nut_2 <= nut2_d; end assign nut_t2 = (~nut_2) & nut2_d; always @ (posedge clk) begin nut_3 <= nut3_t; end assign nut_t3 = (~nut_3) & nut3_t; endmodule


Liên hệ đăng ký tham gia Hội Thảo & Khóa Học Thiết Kế Vi Mạch
HotLine: 0972 800 931 Ms Duyên