Trung tâm đào tạo thiết kế vi mạch Semicon


  • ĐĂNG KÝ TÀI KHOẢN ĐỂ TRUY CẬP NHIỀU TÀI LIỆU HƠN!
  • Đăng ký
    *
    *
    *
    *
    *
    Fields marked with an asterisk (*) are required.
semicon_lab.jpg

Verilog căn bản: bài 11: Finite State Machine - Thiết kế máy trạng thái

Email In PDF.
[​IMG]1. Giới thiệu.
- 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]
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).
- Sau đây mình sẽ hướng dẫn code và giải thích của từng thành phần trong FSM.

** Ở đâ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]

-- 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.
-- Mạch chính cho máy trạng thái:
demc.png

- 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]
++ Đ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
++ Đoạn code cho mạch tuần tự ( chữ nhật 2):
MÃ:
always @ (posedge clk, posedge reset )             begin                                if(reset)                         state_current      <=         2'b00;                 else                         state_current        <=            state_next;                                end
++ Đoạn code cho đầu ra ( ô vuông 3):
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    
// Ở đây mình dùng các tín hiệu R3, R2, R1 để quay lại điều khiển một đoạn code khác. Các bạn xem chương trình chính sẽ hiểu. Nếu không hiểu thic cmt ở dưới mình sẽ trả lời.
++ Đ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 

minion_bigminion_big
                                   Bạn có đam mê ngành thiết kế vi mạch

                   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
Lần cập nhật cuối ( Thứ tư, 17 Tháng 6 2015 19:42 )  

Related Articles

Chat Zalo