Jul
18
Notes: FSM Coding Style without latch
[UPDATE@2009.03.18]
谢谢HJU的留言,让我再记起这篇文章。
由于这是很早的时候写的,重新看一遍感觉我原来的理解应该还是有些问题的。
原始出错的工程已经找不到了,暂时没办法再去探究原来出错的原因到底是什么。
最近写的《有限状态机编写》一文有更多的理解,我也会再根据各位同学的留言来更新那篇文章。
这篇文章就不要参考了,下月会将它下架:)
背景:在做Blackjack Project时,做到FSM模块,由于涉及到的usersum和robotsum两个(时序的状态转换,组合的状态译码和组合的输出译码)时, usersum和robotsum形成Latch。并且map report中也显示生成门控时钟。宏观上,整个设计下载到试验板上状态机运行不正确。
分析:通过FPGA Editor查看生成门控时钟的模块,发现这种情况是由于生成了Latch,而驱动Latch的状态信号形成了门控时钟。产生这种状态的主要原因是输出译码模块是组合逻辑,没有保持功能,当需要保持一个值时,系统就自动产生了latch。由于门控时钟容易引起glitch,门控时钟控制的latch导致了usersum的不正常。
解决方法:将输出译码电路转换为时序逻辑,由时钟控制。将原来控制latch的信号转接到FF的CE端口。具体方法见示例代码。
原始代码结构:(按照ISE中的Language Templates)
修改后代码:
谢谢HJU的留言,让我再记起这篇文章。
由于这是很早的时候写的,重新看一遍感觉我原来的理解应该还是有些问题的。
原始出错的工程已经找不到了,暂时没办法再去探究原来出错的原因到底是什么。
最近写的《有限状态机编写》一文有更多的理解,我也会再根据各位同学的留言来更新那篇文章。
这篇文章就不要参考了,下月会将它下架:)
背景:在做Blackjack Project时,做到FSM模块,由于涉及到的usersum和robotsum两个(时序的状态转换,组合的状态译码和组合的输出译码)时, usersum和robotsum形成Latch。并且map report中也显示生成门控时钟。宏观上,整个设计下载到试验板上状态机运行不正确。
分析:通过FPGA Editor查看生成门控时钟的模块,发现这种情况是由于生成了Latch,而驱动Latch的状态信号形成了门控时钟。产生这种状态的主要原因是输出译码模块是组合逻辑,没有保持功能,当需要保持一个值时,系统就自动产生了latch。由于门控时钟容易引起glitch,门控时钟控制的latch导致了usersum的不正常。
解决方法:将输出译码电路转换为时序逻辑,由时钟控制。将原来控制latch的信号转接到FF的CE端口。具体方法见示例代码。
原始代码结构:(按照ISE中的Language Templates)
type state_type is (st1_<name_state>, st2_<name_state>, ...);
signal state, next_state : state_type;
--Declare internal signals for all outputs of the state machine
signal <output>_i : std_logic; -- example output signal
--other outputs
--Insert the following in the architecture after the begin keyword
SYNC_PROC: process (<clock>)
begin
if (<clock>'event and <clock> = '1') then
if (<reset> = '1') then
state <= st1_<name_state>;
<output> <= '0';
else
state <= next_state;
<output> <= <output>_i;
-- assign other outputs to internal signals
end if;
end if;
end process;
--MOORE State Machine - Outputs based on state only
OUTPUT_DECODE: process (state)
begin
--insert statements to decode internal output signals
--below is simple example
if state = st3_<name> then
<output>_i <= '1';
else
<output>_i <= '0';
end if;
end process;
NEXT_STATE_DECODE: process (state, <input1>, <input2>, ...)
begin
--declare default state for next_state to avoid latches
next_state <= state; --default is to stay in current state
--insert statements to decode next_state
--below is a simple example
case (state) is
when st1_<name> =>
if <input_1> = '1' then
next_state <= st2_<name>;
end if;
when st2_<name> =>
if <input_2> = '1' then
next_state <= st3_<name>;
end if;
when st3_<name> =>
next_state <= st1_<name>;
when others =>
next_state <= st1_<name>;
end case;
end process;
signal state, next_state : state_type;
--Declare internal signals for all outputs of the state machine
signal <output>_i : std_logic; -- example output signal
--other outputs
--Insert the following in the architecture after the begin keyword
SYNC_PROC: process (<clock>)
begin
if (<clock>'event and <clock> = '1') then
if (<reset> = '1') then
state <= st1_<name_state>;
<output> <= '0';
else
state <= next_state;
<output> <= <output>_i;
-- assign other outputs to internal signals
end if;
end if;
end process;
--MOORE State Machine - Outputs based on state only
OUTPUT_DECODE: process (state)
begin
--insert statements to decode internal output signals
--below is simple example
if state = st3_<name> then
<output>_i <= '1';
else
<output>_i <= '0';
end if;
end process;
NEXT_STATE_DECODE: process (state, <input1>, <input2>, ...)
begin
--declare default state for next_state to avoid latches
next_state <= state; --default is to stay in current state
--insert statements to decode next_state
--below is a simple example
case (state) is
when st1_<name> =>
if <input_1> = '1' then
next_state <= st2_<name>;
end if;
when st2_<name> =>
if <input_2> = '1' then
next_state <= st3_<name>;
end if;
when st3_<name> =>
next_state <= st1_<name>;
when others =>
next_state <= st1_<name>;
end case;
end process;
修改后代码:
SYNC_PROC: process (<clock>)
begin
if (<clock>'event and <clock> = '1') then
if (<reset> = '1') then
state <= st1_<name_state>;
-- <output> <= '0';
-- 第一个同步模块中去掉输出部分
else
state <= next_state;
-- <output> <= <output>_i;
-- 第一个同步模块中去掉输出部分
end if;
end if;
end process;
OUTPUT_DECODE: process (<clock>)-- output 模块添加时序同步
begin
-- output 模块添加时序同步
if rising_edge(clk) then[/color]
--insert statements to decode internal output signals
--below is simple example
if state = st3_<name> then
<output>_i <= '1';
else
<output>_i <= '0';
end if;
end if; --结束上面添加的if
end process;
begin
if (<clock>'event and <clock> = '1') then
if (<reset> = '1') then
state <= st1_<name_state>;
-- <output> <= '0';
-- 第一个同步模块中去掉输出部分
else
state <= next_state;
-- <output> <= <output>_i;
-- 第一个同步模块中去掉输出部分
end if;
end if;
end process;
OUTPUT_DECODE: process (<clock>)-- output 模块添加时序同步
begin
-- output 模块添加时序同步
if rising_edge(clk) then[/color]
--insert statements to decode internal output signals
--below is simple example
if state = st3_<name> then
<output>_i <= '1';
else
<output>_i <= '0';
end if;
end if; --结束上面添加的if
end process;
Source Synchronize和System Synchronize
时序约束




