
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
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)