在状态机中,一般也要将大的计数器移到状态机外,因为计数器这东西一般是经常是大于4输入的,如果再和其它条件一起做为状态的跳变判据的话,必然会增加LUT的级联,从而增大组合逻辑。以一个6输入的计数器为例,我们原希望当计数器计到111100后状态跳变,现在我们将计数器放到状态机外,当计数器计到111011后产生个enable信号去触发状态跳变,这样就将组合逻辑减少了。
状态机一般包含三个模块,
(1)一个输出模块,
(2)一个决定下个状态是什么的模块
(3)一个保存当前状态的模块。
组成三个模块所采用的逻辑也各不相同。输出模块通常既包含组合逻辑又包含时序逻辑;决定下一个状态是什么的模块通常由组合逻辑构成;保存现在状态的通常由时序逻辑构成。三个模块的关系如下图9所示。

图9 状态机的组成
所有通常写状态机时也按照这三个模块将状态机分成三部分来写,如下面就是一种良好的状态机设计方法:
/*-----------------------------------------------------
This is FSM demo program
Design Name : arbiter
File Name : arbiter2.v
-----------------------------------------------------*/
module arbiter2 (
clock , // clock
reset , // Active high, syn reset
req_0 , // Request 0
req_1 , // Request 1
gnt_0 ,
gnt_1
);
//-------------Input Ports-----------------------------
input clock ;
input reset ;
input req_0 ;
input req_1 ;
//-------------Output Ports----------------------------
output gnt_0 ;
output gnt_1 ;
//-------------Input ports Data Type-------------------
wire clock ;
wire reset ;
wire req_0 ;
wire req_1 ;
//-------------Output Ports Data Type------------------
reg gnt_0 ;
reg gnt_1 ;
//-------------Internal Constants--------------------------
parameter SIZE = 3 ;
parameter IDLE = 3'b001 ,
GNT0 = 3'b010 ,
GNT1 = 3'b100 ;
//-------------Internal Variables---------------------------
reg [SIZE-1:0] state ; // Seq part of the FSM
wire [SIZE-1:0] next_state ; // combo part of FSM
//----------Code startes Here------------------------
assign next_state = fsm_function(req_0, req_1);
//------------fsm_function--------------//
function [SIZE-1:0] fsm_function;
input req_0; //parameter
input req_1; //parameter
begin
case(state)
IDLE :
if (req_0 == 1'b1)
fsm_function = GNT0;
else if (req_1 == 1'b1)
fsm_function = GNT1;
else
fsm_function = IDLE;
GNT0 :
if (req_0 == 1'b1)
fsm_function = GNT0;
else
fsm_function = IDLE;
GNT1 :
if (req_1 == 1'b1)
fsm_function = GNT1;
else
fsm_function =IDLE;
default : fsm_function = IDLE;
endcase
end
endfunction
always@(posedge clock)
begin
if (reset == 1'b1)
state <= IDLE;
else
state <= next_state;
end
//----------Output Logic-----------------------------
always @ (posedge clock)
begin
if (reset == 1'b1)
begin
gnt_0 <= #1 1'b0;
gnt_1 <= #1 1'b0;
end
else
begin
case(state)
IDLE :
begin
gnt_0 <= #1 1'b0;
gnt_1 <= #1 1'b0;
end
GNT0 :
begin
gnt_0 <= #1 1'b1;
gnt_1 <= #1 1'b0;
end
GNT1 :
begin
gnt_0 <= #1 1'b0;
gnt_1 <= #1 1'b1;
end
default :
begin
gnt_0 <= #1 1'b0;
gnt_1 <= #1 1'b0;
end
endcase
end
end // End Of Block OUTPUT_
endmodule
状态机通常要写成3段式,从而避免出现过大的组合逻辑。
上面说的都是可以通过流水的方式切割组合逻辑的情况,但是有些情况下我们是很难去切割组合逻辑的,在这些情况下我们又该怎么做呢?
状态机就是这么一个例子,我们不能通过往状态译码组合逻辑中加入流水。如果我们的设计中有一个几十个状态的状态机,它的状态译码逻辑将非常 |