【FPGA】Verilog狀態機設計
阿新 • • 發佈:2019-01-28
狀態機是fpga設計中極其重要的一種技巧,掌握狀態機的寫法可以使fpga的開發事半功倍。
下面記錄一下狀態機的基本知識理論。
例項:
三種狀態機實現程式碼:
// 一段式狀態機 module style1_fsm(i_clk, rst_n, i1, i2, o1, o2, err); input i_clk, rst_n, i1, i2; output o1, o2, err; parameter [3:0] IDLE = 4'b0001, S1 = 4'b0010, S2 = 4'b0100, ERROR= 4'b1000; reg o1, o2, err; reg [3:0] state; always @(posedge i_clk or negedge rst_n) begin if(!rst_n) begin state <= IDLE; {o1, o2, err} <= 3'b000; end else case(state) IDLE: begin if(!i1) begin {o1, o2, err} <= 3'b000; state <= IDLE; end if(i1 & i2) begin {o1, o2, err} <= 3'b100; state <= S1; end if(i1 & !i2) begin {o1, o2, err} <= 3'b111; state <= ERROR; end end S1: begin if(!i2) begin {o1, o2, err} <= 3'b100; state <= S1; end if(i1 & i2) begin {o1, o2, err} <= 3'b010; state <= S2; end if(!i1 & i2) begin {o1, o2, err} <= 3'b111; state <= ERROR; end end S2: begin if(i2) begin {o1, o2, err} <= 3'b010; state <= S2; end if(i1 & !i2) begin {o1, o2, err} <= 3'b000; state <= IDLE; end if(!i1 & !i2) begin {o1, o2, err} <= 3'b111; state <= ERROR; end end ERROR: begin if(i1) begin {o1, o2, err} <= 3'b111; state <= ERROR; end if(!i1) begin {o1, o2, err} <= 3'b000; state <= IDLE; end end default:begin {o1, o2, err} <= 3'b000; state <= IDLE; end endcase end endmodule
// 兩段式狀態機 module style2_fsm(i_clk, rst_n, i1, i2, o1, o2, err); input i_clk, rst_n, i1, i2; output o1, o2, err; parameter [3:0] IDLE = 4'b0001, S1 = 4'b0010, S2 = 4'b0100, ERROR= 4'b1000; reg o1, o2, err; reg [3:0] curr_state, next_state; always @(posedge i_clk or negedge rst_n) begin if(!rst_n) curr_state <= IDLE; else curr_state <= next_state; end always @(curr_state or i1 or i2) begin case(curr_state) IDLE: begin if(!i1) begin IDLE_OUT; next_state = IDLE; end if(i1 & i2) begin S1_OUT; next_state = S1; end if(i1 & !i2) begin ERROR_OUT; next_state = ERROR; end end S1: begin if(!i2) begin S1_OUT; next_state = S1; end if(!i1 & i2) begin ERROR_OUT; next_state = ERROR; end if(i1 & i2) begin S2_OUT; next_state = S2; end end S2: begin if(i2) begin S2_OUT; next_state = S2; end if(i1 & !i2) begin IDLE_OUT; next_state = IDLE; end if(!i1 & !i2) begin ERROR_OUT; next_state = ERROR; end end ERROR: begin if(i1) begin ERROR_OUT; next_state = ERROR; end if(!i1) begin IDLE_OUT; next_state = IDLE; end end default:begin IDLE_OUT; next_state <= IDLE; end endcase end task IDLE_OUT; {o1, o2, err} = 3'b000; endtask task S1_OUT; {o1, o2, err} = 3'b100; endtask task S2_OUT; {o1, o2, err} = 3'b010; endtask task ERROR_OUT; {o1, o2, err} = 3'b111; endtask endmodule
// 三段式狀態機 module style3_fsm(i_clk, rst_n, i1, i2, o1, o2, err); input i_clk, rst_n, i1, i2; output o1, o2, err; parameter [3:0] IDLE = 4'b0001, S1 = 4'b0010, S2 = 4'b0100, ERROR= 4'b1000; reg o1, o2, err; reg [3:0] curr_state, next_state; always @(posedge i_clk or negedge rst_n) begin if(!rst_n) curr_state <= IDLE; else curr_state <= next_state; end always @(curr_state or i1 or i2) begin case(curr_state) IDLE: begin if(!i1) next_state = IDLE; if(i1 & i2) next_state = S1; if(i1 & !i2) next_state = ERROR; end S1: begin if(!i2) next_state = S1; if(i1 & i2) next_state = S2; if(!i1 & i2) next_state = ERROR; end S2: begin if(i2) next_state = S2; if(i1 & !i2) next_state = IDLE; if(!i1 & !i2) next_state = ERROR; end ERROR: begin if(i1) next_state = ERROR; if(!i1) next_state = IDLE; end default:begin next_state = IDLE; // 不加這個default項 輸出會一直是000!!! end endcase end always @(posedge i_clk or negedge rst_n) begin if(!rst_n) {o1, o2, err} <= 3'b000; else begin case(next_state) IDLE: {o1, o2, err} <= 3'b000; S1: {o1, o2, err} <= 3'b100; S2: {o1, o2, err} <= 3'b010; ERROR: {o1, o2, err} <= 3'b111; default:{o1, o2, err} <= 3'b000;//不加這個default 復位前訊號都為不定值X endcase end end endmodule