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!
  • Create an account
    *
    *
    *
    *
    *
    Fields marked with an asterisk (*) are required.
wafer.jpg

Máy trạng thái trong Verilog ( FSM )

E-mail Print PDF

Bạn đã bao giờ nghe thấy FSM ? hay máy trạng thái ?

Trong coding verilog, FSM được dùng rất phổ biến vì tính ưu việt của nó. Nó có thể tạo ra cách code rất đơn giản cho những tiến trình xử lý, nhưng công việc gồm nhiều công đoạn. Nói cách khác, sử dụng FSM là một cách thức để nâng cao hiệu quả trong thiết kế số và thiết kế logic.

1. Đặt vấn đề, máy trạng thái ( State Machine ) là gì ?

- Ban đầu, nếu các bạn nghe thấy từ máy, hoặc machine, các bạn dễ liên tưởng đến cái gì đó có thể tự vận hành, hoặc vận hành với một số đầu vào điều khiển nào đó. State Machine cũng vậy. Nó là một cái "máy" hay đúng hơn là một cơ chế, vận hành dựa trên sự chuyển đổi của các trạng thái.

- Trạng thái tiếp theo được quyết định bời trạng thái hiện tại và các đầu vào khác, và thường được đặt là "next_state".

- Các hoạt động Logic của hệ thống tùy thuộc vào trạng thái hiện tại ( current_state )

 

2. Cách thiết kế:

a) Current State:

Phần tử trung tâm của State Machine là State, hay còn gọi là Current State. Có nghĩa là State ở thời điểm nào đó. Giá trị của State có thể thay đổi theo chu kỳ clock hoặc thay đổi theo điều kiện đầu vào và có tính tuần hoàn. Vì vậy, để lưu giá trị của State hiện thời, FlipFlop sẽ được sử dụng:

 

Thông thường, State là một FlipFlop có N bits. Do đó, nó có thể mã hóa được 2 lũy thừa N State. Tùy vào yêu cầu của thiết kế mà bạn có thể tạo ra FlipFlop với số bits tương ứng.

Ví dụ: để điều khiển xe thì có yêu cầu về trạng thái như sau:

    - Dừng

    - Tiến

    - Rẻ phải

    - Rẻ trái

    - Hãm

    - Lùi

--> Tổng số State là M = 6.

Vậy tổng cộng là có tất cả 6 trạng thái, hay còn gọi là 6 State. Vì State là biến có khả năng mã hóa được 2 ^N State, do đó N phải được chọn sao cho 2^N >= M.

Ở đây, ta chọn N là 3. Vì 2 ^ 3 = 8 ( > 6 ).

Vậy, code của Current State khá đơn giản:

always @ ( posedge clock ) begin

    if ( reset_n == 1'b0 ) begin

        state <= 3'b000; // IDLE state;

    end

    else begin

        state <= next_state;

    end

end 

Tại sao 2^4 > 6, mà ta không nên chọn N = 4 ?

 

b) Next State:

Next state là trạng thái kế tiếp mà State sẽ chuyển sang. Để dễ hiểu, các bạn có thể hình dung cái State Machine này là cái máy có M bước. Giả sử bước hiện tại ( có thể hiểu là State hiện tại, hoặc current state ) là bước thứ i. Do bước kế tiếp thì phụ thuộc vào các sự kiện đầu vào, cũng như chính vị trí của bước hiện tại. Bên cạnh đó, State là một FlipFlop, nó sẽ nhận giá trị của Next State khi nào có xung clock. Khi next state thay đổi, thì ở cạnh clock tiếp theo, State sẽ mang giá trị của Next State. Đó là lý do vì sao người ta gọi trạng thái kế tiếp, hay next state.

Tới đây, các bạn phải hiểu được rằng, trong State Machine thì Logic Next State sẽ phức tạp và quan trọng hơn nhiều so với State. Để thiết kế được Logic của next state 1 cách đơn giản nhất, người ta thường dùng các bảng thể hiện sự liên quan giữa State, Next State và các điều kiện đầu vào. Sau đây là 1 ví dụ:

State: IDLE, FORWARD, RIGHT, LEFT

Đầu vào gồm 2 tín hiệu: Sensor1 và Sensor2.

Cách đọc bảng này: Cột đầu tiên là Current State. Khi State đang ở Current State, thì next_state sẻ chuyển đổi giá trị theo như 4 cột bên phải của bảng.

 

( Lưu ý: Đây chỉ là ví dụ về cách viết và cách thiết kế next_state. Nó không giúp bạn giải quyết vấn đề về điều khiển động cơ của bạn. Thay vào đó, hãy xem xét logic của bạn trước rồi áp dụng cách này để tạo ra bảng riêng cho mình)

Và đây là Block Diagram của State machine khi có thêm khối logic của Next State:

 

Phần code của next_state sẽ được code dựa theo bảng. Lưu ý, next_state là khối logic có các phần tử tổ hợp. Nó thường được code sử dụng câu lệnh case trong verilog. Sau đây là một ví dụ:

always @ (*) begin

    case ( state )

        `IDLE: begin

                if (Sensor1 == 1 && Sensor2 == 1 )        next_state = `FORWARD;

                else if (Sensor1 == 0 && Sensor2 == 1 ) next_state = `LEFT;

                else if (Sensor1 == 1 && Sensor2 == 0 ) next_state = `RIGHT;

                else                                                       next_state = `IDLE;

         end

        `FORWARD: begin

                if (Sensor1 == 1 && Sensor2 == 0 )        next_state = `RIGHT;

                else if (Sensor1 == 0 && Sensor2 == 1 ) next_state = `LEFT;

                else if (Sensor1 == 0 && Sensor2 == 0 ) next_state = `RIGHT;

                else                                                       next_state = `FORWARD;

        end

        `RIGHT: begin

                if (Sensor1 == 1 && Sensor2 == 1 )        next_state = `FORWARD;

                else if (Sensor1 == 0 && Sensor2 == 1 ) next_state = `LEFT;

                else if (Sensor1 == 0 && Sensor2 == 0 ) next_state = `IDLE;

                else                                                       next_state = `RIGHT;

        end

        `LEFT: begin

                if (Sensor1 == 1 && Sensor2 == 1 )        next_state = `FORWARD;

                else if (Sensor1 == 1 && Sensor2 == 0 ) next_state = `RIGHT;

                else if (Sensor1 == 0 && Sensor2 == 0 ) next_state = `IDLE;

                else                                                       next_state = `LEFT;

        end

        default: next_state = `IDLE;

    endcase

end

 

c) Khối Logic thực thi:

Việc thiết kế State Machine sẽ không có ý nghĩa gì nếu như không có cách hoạt động logic tương ứng cho từng State. Thiết kế có block diagram hoàn thiện sử dụng 1 state machine sẽ có kiểu như sau:

 

Ở đây, tạm gọi là khối thực thi. Một cách đơn giản, đây là khối thực thi các nhiệm vụ của thiết kế dựa theo giá trị của State hiện tại.

 

Trong ví dụ này, các biến để điều khiển LED và Motor đều là các FlipFlop 1 bit. Do đó ta tham khảo code sau:

//////////////////////////////////////////////////////////////////////////////////

// Company: Degic Lab

// Engineer: Admin

//

//////////////////////////////////////////////////////////////////////////////////

`define IDLE 2'b00

`define RIGHT 2'b01

`define LEFT 2'b10

`define FORWARD 2'b11

`define ON 1'b1

`define OFF 1'b0

module state_machine(

    clock,

    reset_n,

    Sensor1,

    Sensor2,

    MOV_LED,

    STOP_LED,

    RIGHT_LED,

    LEFT_LED,

    RIGHT_MOT,

    LEFT_MOT

);

input clock;

input reset_n;

input Sensor1;

input Sensor2;

output MOV_LED;

output STOP_LED;

output RIGHT_LED;

output LEFT_LED;

output RIGHT_MOT;

output LEFT_MOT;

 

reg MOV_LED;

reg STOP_LED;

reg RIGHT_LED;

reg LEFT_LED;

reg RIGHT_MOT;

reg LEFT_MOT;

 

reg [1:0] state;

reg [1:0] next_state;

reg [7:0] pwm_count;

wire ON_PWM;

 

// State FLIPFLOP

always @ ( posedge clock ) begin

    if ( reset_n == 1'b0 ) begin

        state <= `IDLE;

    end

    else begin

        state <= next_state;

    end

end

 

always @ ( posedge clock ) begin

    if ( reset_n == 1'b0 ) begin

        pwm_count <= 8'd0;

    end

    else begin

        pwm_count <= pwm_count + 8'd1;

    end

end

assign ON_PWM = (pwm_count < 50 ) ? 1'b1 : 1'b0;

// pwm_count is 8bits: maximum val is 255

// ON_PWM = 1: when counter is 0 - 49.

// ON_PWM = 0: when counter is 50 - 255.

 

// Next state Logic

always @ (*) begin

    case ( state )

        `IDLE: begin

            if (Sensor1 == 1 && Sensor2 == 1 )

                next_state = `FORWARD;

            else if (Sensor1 == 0 && Sensor2 == 1 )

                next_state = `LEFT;

            else if (Sensor1 == 1 && Sensor2 == 0 )

                next_state = `RIGHT;

            else

                next_state = `IDLE;

        end

        `FORWARD: begin

            if (Sensor1 == 1 && Sensor2 == 0 )

                next_state = `RIGHT;

            else if (Sensor1 == 0 && Sensor2 == 1 )

                next_state = `LEFT;

            else if (Sensor1 == 0 && Sensor2 == 0 )

                next_state = `RIGHT;

            else

                next_state = `FORWARD;

        end

    `RIGHT: begin

        if (Sensor1 == 1 && Sensor2 == 1 )

            next_state = `FORWARD;

        else if (Sensor1 == 0 && Sensor2 == 1 )

            next_state = `LEFT;

        else if (Sensor1 == 0 && Sensor2 == 0 )

            next_state = `IDLE;

        else

            next_state = `RIGHT;

end

    `LEFT: begin

        if (Sensor1 == 1 && Sensor2 == 1 )

            next_state = `FORWARD;

        else if (Sensor1 == 1 && Sensor2 == 0 )

            next_state = `RIGHT;

        else if (Sensor1 == 0 && Sensor2 == 0 )

            next_state = `IDLE;

        else

            next_state = `LEFT;

    end

    default: next_state = `IDLE;

    endcase

end

 

// Motor + Led control

always @ ( posedge clock ) begin

    if ( reset_n == 1'b0) begin

        RIGHT_MOT    <= `OFF;

        LEFT_MOT      <= `OFF;

        MOV_LED       <= `OFF;

        STOP_LED      <= `ON;

        RIGHT_LED     <= `OFF;

        LEFT_LED       <= `OFF;

    end

    else begin

        case (state)

        `FORWARD: begin

            RIGHT_MOT <= `ON;

            LEFT_MOT <= `ON;

            MOV_LED <= `ON;

            STOP_LED <= `OFF;

            RIGHT_LED <= `OFF;

            LEFT_LED <= `OFF;

        end

        `RIGHT: begin

            RIGHT_MOT <= ON_PWM;

            LEFT_MOT <= `ON;

            MOV_LED <= `ON;

            STOP_LED <= `OFF;

            RIGHT_LED <= `ON;

            LEFT_LED <= `OFF;

        end

       `LEFT: begin

            RIGHT_MOT <= `ON;

            LEFT_MOT <= ON_PWM;

            MOV_LED <= `ON;

            STOP_LED <= `OFF;

            RIGHT_LED <= `OFF;

            LEFT_LED <= `ON;

        end

        `IDLE: begin

            RIGHT_MOT <= `OFF;

            LEFT_MOT <= `OFF;

            MOV_LED <= `OFF;

            STOP_LED <= `ON;

            RIGHT_LED <= `OFF;

            LEFT_LED <= `OFF;

       end

       default: begin

            RIGHT_MOT <= `OFF;

            LEFT_MOT <= `OFF;

            MOV_LED <= `OFF;

            STOP_LED <= `ON;

            RIGHT_LED <= `OFF;

            LEFT_LED <= `OFF;

        end

     endcase

   end

end

endmodule

Trên đây chỉ là các khái niệm cơ bản. Để có được cái nhìn đầy đủ và tổng quát hơn về State Machine ( hoặc FSM ) thì các bạn phải trải qua nhiều thực tế thiết kế.

Làm sao để test thiết kế phía trên ? Các bạn có thể tự viết 1 testbench được không ?

Nguồn: degic.freeforums

Bạn Có Đam Mê Với Vi Mạch hay Nhúng      -     Bạn Muốn Trau Dồi Thêm Kĩ Năng

Mong Muốn Có Thêm Cơ Hội Trong Công Việc

    Và Trở Thành Một Người Có Giá Trị Hơn

Bạn Chưa Biết Phương Thức Nào Nhanh Chóng Để Đạt Được Chúng

Hãy Để Chúng Tôi Hỗ Trợ Cho Bạn. SEMICON  

 

Hotline: 0972.800.931 - 0938.838.404 (Mr Long)

 

Last Updated ( Friday, 21 June 2019 18:42 )  

Related Articles

Chat Zalo