打印

问一个VHDL的基础问题

[复制链接]
2884|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
frily|  楼主 | 2007-9-16 10:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
小弟刚学VHDL不久,昨天写了一个状态机,在仿真的时候,发现状态的转换跟我预期的不

一样,是两个周期才转换一次。实在找不出问题,就慢慢的删程序,最后把程序删到了只

有状态转换部分,但是仿真出来还是两个周期才切换一次状态。

我感觉应该是一个周期转换一次状态才对。
不知道是我的理解有问题,还是程序有问题。
我把代码贴在下面了,麻烦各位帮我看看。

谢谢了!!!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity NonStopWrite is
    port(
        clk:in std_logic;
        rst:in std_logic
    ) ;
end NonStopWrite;

architecture Behavioral of NonStopWrite is
type NonStopState is (IDLE,WR1,WR2,WR3,WR4,WR5);
signal pre_state,next_state: NonStopState;
begin
    
    process(clk,rst)
    begin
        if(rst='1')then
            next_state <= IDLE;
        elsif(rising_edge(clk))then
            case pre_state is
                when IDLE =>
                    next_state <= WR1;
                when WR1 =>
                    next_state <= WR2;
                when WR2 =>    
                    next_state <= WR3;
                when WR3 =>
                    next_state <= WR4;
                when WR4 =>
                    next_state <= WR5;
                when WR5 =>
                    next_state <= WR1;
                when others=>
                    next_state <= IDLE;
            end case;
        end if;
    end process;
    
    process(clk,rst)
    begin
        if(rst='1')then
            pre_state <= IDLE;
        elsif(rising_edge(clk))then
            pre_state <= next_state;
        end if;
    end process;

end Behavioral;

相关帖子

沙发
frily|  楼主 | 2007-9-16 10:15 | 只看该作者

仿真波形

仿真波形如下

使用特权

评论回复
板凳
frily|  楼主 | 2007-9-17 11:41 | 只看该作者

bangmang

麻烦大家帮忙看看啊

使用特权

评论回复
地板
amtek| | 2007-9-17 15:45 | 只看该作者

N年前俺好象也犯过同样错误


 把第一个process(clk,rst)的clk去掉,但还存在很多很多问题。你最好找个师傅先带带,不然你要走很多弯路。

使用特权

评论回复
5
liangzhitu| | 2007-9-17 20:18 | 只看该作者

回复

按我的注解修改即可!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity NonStopWrite is
    port(
        clk:in std_logic;
        rst:in std_logic
    ) ;
end NonStopWrite;

architecture Behavioral of NonStopWrite is
type NonStopState is (IDLE,WR1,WR2,WR3,WR4,WR5);
signal pre_state,next_state: NonStopState;
begin
    
    process(clk,rst)
    begin
        if(rst='1')then
            next_state <= IDLE;
        else         -- if(rising_edge(clk))then
            case pre_state is
                when IDLE =>
                    next_state <= WR1;
                when WR1 =>
                    next_state <= WR2;
                when WR2 =>    
                    next_state <= WR3;
                when WR3 =>
                    next_state <= WR4;
                when WR4 =>
                    next_state <= WR5;
                when WR5 =>
                    next_state <= WR1;
                when others=>
                    next_state <= IDLE;
            end case;
        end if;
    end process;
    
    process(clk,rst)
    begin
        if(rst='1')then
            pre_state <= IDLE;
        elsif(rising_edge(clk))then
            pre_state <= next_state;
        end if;
    end process;

end Behavioral;

使用特权

评论回复
6
frily|  楼主 | 2007-9-17 21:00 | 只看该作者

非常感谢

非常感谢上面两位大侠的帮助!

不过我还是想不明白的一个问题就是:

按照我原来的写法,感觉应该是每个上升沿状态就会有一次变化啊,
但是实际上为什么就要两个周期才变化一次呢?

使用特权

评论回复
7
frily|  楼主 | 2007-9-17 21:21 | 只看该作者

回复

不过4楼的方法好象有问题

如果把clk从敏感信号列表中去掉的话,那将只有rst变化的时候才会引起该进程的工作,系统将一直停留在WR1的状态
仿真波形如下:

使用特权

评论回复
8
amtek| | 2007-9-18 15:35 | 只看该作者

所以说只去掉CLK不行


  
 process(rst,pre_state)
    begin
        if(rst='1')then
            next_state <= IDLE;
        else  --if(rising_edge(clk))then
            case pre_state is
                when IDLE =>
                    next_state <= WR1;
                when WR1 =>
                    next_state <= WR2;
                when WR2 =>    
                    next_state <= WR3;
                when WR3 =>
                    next_state <= WR4;
                when WR4 =>
                    next_state <= WR5;
                when WR5 =>
                    next_state <= WR1;
                when others=>
                    next_state <= IDLE;
            end case;
        end if;
    end process;

    以上为专业做法,你如果不理解,就需要花点时间。

使用特权

评论回复
9
frily|  楼主 | 2007-9-18 22:46 | 只看该作者

谢谢大家

非常感谢大家,尤其是"amtek"!

8楼的"qinxg" 说:
"第一个process要一个时钟后才能作出反映.第2个process也是一样. 循环下来不就是2个Clk了"
 
我的理解是:next_state一直超前pre_state一个周期,要完成一次完整的状态的变换的话,首先要用一个周期给next_state变化,然后再用一个周期给pre_state转化,也就是你所说的两个周期完成一次完整的循环.

但是单独对于pre_state或者next_state来说的话,应该是一个周期就要变化一次,也就是说应该按照我在下面的图中注释的那样变化,不知道我理解有没有错.

使用特权

评论回复
10
frily|  楼主 | 2007-9-18 22:47 | 只看该作者

波形

使用特权

评论回复
11
frily|  楼主 | 2007-9-18 22:53 | 只看该作者

组合逻辑

对于amtek在9楼的写法我想我应该理解到了

这个状态机确实应该写成组合逻辑,而且也应该把敏感变量列表中的clk换成pre_state才更准确.
不过要靠自己想,估计....

多谢指点,非常感谢!

使用特权

评论回复
12
amtek| | 2007-9-19 10:36 | 只看该作者

我一直想在深圳业余


 我一直想在深圳业余收两个徒弟,免费传授国际专业的ASIC设计方法,可从来就没人相信,觉得天上不会掉馅饼。其实我只是想在以后筹建IC开发室时能有更多的选择。

 楼上如还有技术问题,或深圳真有哥们想学ASIC设计,可给我发邮件:amtek@126.com

 如果您原来是搞单片机的,又有兴趣创业的,可去“人才聘任”子论坛看帖子“大家一起创业”,那里有我们的一个计划。 

使用特权

评论回复
13
风中De舞者| | 2007-9-20 09:40 | 只看该作者

信号的代入不是即时的

                when IDLE =>
                    next_state <= WR1;
也就是说即使初态是IDLE  他需要转换成次态  首先需要一个上升沿除法这条语句  然后需要另一个上升沿来完成信号的代入  所以完成这个过程需要俩个信号的上升沿
这应该是8楼兄弟的意思  
顺便问问你的问题搞定了没?  把搞定的程序贴出来大家看看  也学习学习

使用特权

评论回复
14
风中De舞者| | 2007-9-20 09:49 | 只看该作者

amtek的做法应该是可靠的

也就是说不用判断CLK是否是上升沿  只进行状态转换  因为在信号代入语句会形成一个寄存器来保存信号的状态  一个CLK脉冲后才代入到另一个信号中  这样就省了那个触发信号代入语句执行的CLK脉冲  达到了1个CLK就进行转换的目的  看来你课本还没有理解透彻哦  书上一再强调 信号的代入不是即时生效  而变量的赋值是即时生效的  应该多钻研一下

使用特权

评论回复
15
frily|  楼主 | 2007-9-23 10:27 | 只看该作者

有点不明白

谢谢楼上的关注!
问题已经解决,就是采用的amtek的做法.

关于你在14楼提到的内容,我想问一下是不是应该这样理解:

状态的转换和next_state的真正的值的变化不是同一个行为?    

那假如我在编码的时候,定义IDLE编码为:00000,WR1为00001,按照你的意思是不是说:
case pre_state is   
     when IDLE =>
        next_state <= WR1;
如果要执行上面几句话,首先需要一个上升沿来把next_state的状态变为WR1,但是由于信号带入不是即时的,此时虽然next_state的状态已经是WR1了,但他的真正电平还是00000,需要在紧跟的下一个上升沿再把next_state的真正的电平值赋为00001,所以需要两个时钟.



不知道我的理解是否正确?




使用特权

评论回复
16
dspjs| | 2007-9-23 20:54 | 只看该作者

学习。

使用特权

评论回复
17
frily|  楼主 | 2007-9-29 12:07 | 只看该作者

呼唤 风中De舞者

风中De舞者 再来看看啊

使用特权

评论回复
18
zhanghao35| | 2007-9-29 20:23 | 只看该作者

我也在学习中!

使用特权

评论回复
19
ling631220| | 2007-10-6 20:51 | 只看该作者

回复frily

信号的执行赋值与完成赋值是不在同一时刻发生的!!完成赋值是执行赋值后一个小延时后发生的!第一个时钟周期next_state变成WR1,第二个时钟周期next_state还是WR1,因为pre_state还没有完成赋值,也就是说CLK上升的时候pre_state还是IDLE,pre_state在小延时后才变成WR1,所以next_state还是WRI,

使用特权

评论回复
20
风中De舞者| | 2007-10-10 08:49 | 只看该作者

恩 基本上是对的

因为第1个脉冲来的时候条件满足  所以要把next_state的状态变为WR1  而这是需要一个脉冲才能完成的  所以在第2个脉冲结束后next_state的值才真正变成WR1  但是在第2个脉冲来的时候next_state的值还不是WR1所以不满足下一个语句的触发条件  所以系统不会发生矛盾

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

54

帖子

0

粉丝