您的位置:首页 > 其它

FPGA——关于状态机

2018-01-19 16:34 120 查看
状态机,是我大二在实验室学习时,学长给我们安排的任务之一。那个时候,我还没有学过《数电》,一直搞不明白状态机的意思,做了一周,都没有结果。


任务是检测序列,检测到1011时输出一个高电平。

我们都知道verilog语言依靠不同的always语句块实现了硬件电路的并行执行,但是在工程中,我们不仅要处理并行执行电路,偶尔也会遇到需要串行执行的电路要求。刚开始学习FPGA的话,可能会想到我们可以利用很多很多的使能信号实现,但是这样维护的成本大大增加。状态机就可以完美的实现这一功能。先简单介绍一下状态机的基本概念。

状态机的基本要素是输入、输出和状态。输入是引起状态变化的条件,输出是状态变化引起的变化。状态就是字面理解的意思了,状态机,通俗的说就是因为输入导致状态在不断的变化的硬件电路。

Moore型状态机的输出仅与状态有关,与输入无关。

Mealy型状态机的输入不仅与状态有关,还与输入条件有关。



一段式写法,输入、输出和状态在一个always语句块中,后期不容易维护。

module pro(
input   clk,
input   rst_n,

input   data,
output  cntout
);
parameter   INITIALSTATE = 5'b00_001,
STATE_0 = 5'b00_010,
STATE_1 = 5'b00_100,
STATE_2 = 5'b01_000,
STATE_3 = 5'b10_000;

//————————————————————————————————————————————
//一段式写法, 既把输入、输出和状态写在一个always语句块

reg[4:0]    state_ce;       //状态寄存器
reg cnt;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)  begin
cnt <= 1'b0;
state_ce <= INITIALSTATE;
end
else
case(state_ce)
INITIALSTATE:   begin
cnt <= 1'b0;
if(data == 1'b1)
state_ce <= STATE_0;
else
state_ce <= INITIALSTATE;
end
STATE_0:            if(data == 1'b0)
state_ce <= STATE_1;
else
state_ce <= STATE_0;
STATE_1:            if(data == 1'b1)
state_ce <= STATE_2;
else
state_ce <= INITIALSTATE;
STATE_2:            if(data == 1'b1)
state_ce <= STATE_3;
else
state_ce <= STATE_1;
STATE_3:            begin
state_ce <= INITIALSTATE;
cnt <= 1'b1;
end
endcase
end

assign  cntout = cnt;
endmodule




二段式写法,分成了组合逻辑和时序逻辑。时序逻辑里作状态的转移,组合逻辑里作输入条件判断和输出。但是组合逻辑输出容易出现毛刺问题。

module pro(
input   clk,
input   rst_n,

input   data,
output  cntout
);
parameter   INITIALSTATE = 5'b00_001,
STATE_0 = 5'b00_010,
STATE_1 = 5'b00_100,
STATE_2 = 5'b01_000,
STATE_3 = 5'b10_000;

reg[4:0]    state_ce;
reg[4:0]    state_nt;
reg cnt;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
state_ce <= INITIALSTATE;
else
state_ce <= state_nt;
end

always @ (state_ce or data) begin
case(state_ce)
INITIALSTATE:   begin
cnt = 1'b0;
if(data == 1'b1)
state_nt = STATE_0;
else
state_nt = INITIALSTATE;
end
STATE_0:            begin
cnt = 1'b0;
if(data == 1'b0)
state_nt = STATE_1;
else
state_nt = STATE_0;
end
STATE_1:            begin
cnt = 1'b0;
if(data == 1'b1)
state_nt = STATE_2;
else
state_nt = INITIALSTATE;
end
STATE_2:            begin
if(data == 1'b1)
state_nt= STATE_3;
else
state_nt =STATE_1;
end
STATE_3:            begin
cnt = 1'b1;
state_nt = INITIALSTATE;
end
endcase
end

assign  cntout = cnt;

endmodule


三段式写法,又将输出写作时序逻辑输出,解决了二段式中毛刺的问题。

module pro(
input   clk,
input   rst_n,

input   data,
output  cntout
);
parameter   INITIALSTATE = 5'b00_001,
STATE_0 = 5'b00_010,
STATE_1 = 5'b00_100,
STATE_2 = 5'b01_000,
STATE_3 = 5'b10_000;

reg[4:0]    state_ce;
reg[4:0]    state_nt;
reg cnt;

always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
state_ce <= INITIALSTATE;
else
state_ce <= state_nt;
end

always @ (state_ce or data) begin
case(state_ce)
INITIALSTATE:   if(data == 1'b1)
state_nt = STATE_0;
else
state_nt = INITIALSTATE;
STATE_0:            if(data == 1'b0)
state_nt = STATE_1;
else
state_nt = STATE_0;
STATE_1:            if(data == 1'b1)
state_nt = STATE_2;
else
state_nt = INITIALSTATE;
STATE_2:            if(data == 1'b1)
state_nt = STATE_3;
else
state_nt = STATE_2;
STATE_3:        state_nt = INITIALSTATE;
endcase
end

always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 'd0;
else if(state_nt == STATE_3)
cnt <= 1'b1;
else
cnt <= 1'b0;
end

assign  cntout = cnt;
endmodule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: