在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2308|回复: 4

状态机在疑惑

[复制链接]
发表于 2007-5-16 23:31:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
大家帮我理解理解!谢谢了!
我的理解:
比如说状态机:

1:
always @(CS or in)
case(CS)
S0: if(in)  NS=S1;
     else   NS=S0;

组合逻辑跟时序没有关系,它不断的对输入信号(in)进行判断,只要输入信号发生变化就改变NS,反之NS=CS保持原状态

always   @(posedge clk  )

case(NS)
S0ut<=2'b00;

如果这样说的没错,可不可以理解为在第一个上升沿对当前输入进行判断,决定下一状态,同时输出上一状态NS,也就是说在输出的同时进行判断!算是同步吧!

不知道我理解的对不对,愿大家指导!
2:
我想要问的是:

如果我改变状态的条件不是有输入决定的,而是由逻辑的运算结果决定的,可不可以去代替输入(IN)进行判断?
比如:
always  @(posedge clk)
begin
       count<=count+1;
if(count==10)
      in<=1;
      count<=0;
else
      in<=0;

end

3:
我想解决的:

就是我想把一个大模块,分成小模块,想用状态机解决,可是试了好多次,结果不正确,有时候就是不同步,当然加上RESET也不行!
所以我 对FPGA的工作流程产生的不小的疑问!希望大家能解决我的疑惑!
发表于 2007-5-18 23:54:50 | 显示全部楼层
1。
always   @(posedge clk  )
case(NS)
S0 out<=2'b00;
这是次态寄存器输出,他和现态组合逻辑输出效果是一样的,但是比现态寄存器输出要早一拍,具体怎么输出要有具体的时序要求决定。
还有你这里说的同步是什么意思?
2。完全没有问题。
3。你可以把一个大模块分成小模块,每一个小模块用状态机,大模块用状态机,大模块的状态机在适当的时候产生信号激活小模块状态机,这就是所谓major FSM和minor FSM。可以给一个例子,说明你要做什么,你怎么做了但行不通。
 楼主| 发表于 2007-5-20 20:26:49 | 显示全部楼层

比交通灯简单点,这是代码
当然这个代码不对,我写在一个模块里没错误,想写成状态机就不行了,主要就是不能在不同的模块里该同一变量赋值
用tir,要做个三态驱动吗,怎么做呢?
我所指的同步是在改变状态的同时有输出
还请大虾指点

module traffic1(CLK,LAMP,nrst,num);
output[7:0] num;
output[2:0] LAMP;
input CLK,nrst;
reg[7:0] num,numa;
reg[2:0] LAMP,CS,NS;
reg temp;
parameter[2:0] IDLE=3'b000, S1=3'b001, S2=3'b010,S3=3'b011;
parameter[7:0] red=8'd15,yellow=8'd10,bule=8'd5;   

always @(posedge CLK )
if(!nrst)
   CS<=IDLE;
else
   CS<=NS;

always @(CS or temp )//三灯循环点亮,在变换状态的同时
begin
   NS=3'bx;
case(CS)
IDLE: begin
    if(temp) NS=IDLE;
    if(!temp) NS=S1;
   end
   
S1:  begin
    if(temp) NS=IDLE;
    if(!temp) NS=S2;
   end      
S2:  begin
    if(temp) NS=IDLE;
    if(!temp) NS=S3;
   end
S3:  begin
    if(temp) NS=IDLE;
    if(!temp) NS=S1;
   end
   
default:NS=IDLE;
endcase

end
always @(posedge CLK )//三灯循环点亮,在变换状态的同时
     //改变倒计时,时间
if(!nrst)
begin
LAMP<=3'b000;
end
else
begin
case(NS)
  IDLE: begin
    LAMP<=3'b000;
    numa<=8'd0;
    end
   
  S1:  begin
    LAMP<=3'b001;
    numa<=red;
    end
      
  S2:  begin
    LAMP<=3'b010;
    numa<=yellow;
    end
   
  S3:  begin
    LAMP<=3'b100;
    numa<=bule;
    end
  endcase
end
   
always @(posedge CLK ) //倒计时模块         
if(!nrst)
num<=8'd0;
else
begin //想在倒计时到0时重新给倒计时赋值
num<=numa;//,因为不能在两个模块给同一变量赋值
   //这里没办法了我用一个中间变量(numa)传递
if(num>0)//最小情况为1
begin
  if(num[3:0]==0)
   begin   
    num[3:0]<=9;
    num[7:4]<=num[7:4]-1;
   end
  else
   num[3:0]<=num[3:0]-1;
   
  if(num==1) temp<=0;  //因为是非阻塞,全结束之前还是旧值,结束后才变为0,
       //所以等与1时结束后就为0 ,这样理解行吗?
end
   
else
  temp<=0; //到0时要改变状态
  
end
endmodule  

谢谢关心我的人
发表于 2007-5-22 20:14:29 | 显示全部楼层
1.  
if(temp) NS=IDLE;
if(!temp) NS=S1;
这个地方我不知道会不会综合出latch,也许综合器能认出来是组合逻辑,但最好改为:
if(temp)
    NS=IDLE;
else
    NS=S1;
2.
在不同的模块对一个信号多次赋值是不行的,相当于一个信号点有多个信号源输入,这需要仲裁。

3.建议将次态逻辑和输出逻辑放在一起,采用现态组合逻辑输出,这样的效果和次态寄存器输出一样,但是少用一些寄存器资源。
我修改如下,加了一个计数器来计时,状态转移模块在状态转移时产生信号将计数器清零重新开始计数:
reg [7:0] count;
reg clr_count;
always @( CS  )//三灯循环点亮,在变换状态的同时
begin
clr_count = 1'b1
case( CS, coun t)
IDLE:  
     NS = S1;
     LAMP = 3'b000;  
S1:
    LAMP = 3'b001;  
    if ( count == red )
    begin
        clr_count = 1'b0;
       NS = S2;
    end
    else
       NS = S1;   
S2:
    LAMP = 3'b010;  
    if ( count == yellow )
    begin
        clr_count = 1'b0;
       NS = S3;
    end
    else
       NS = S2;
S3:
    LAMP = 3'b100;  
    if ( count== blue )
    begin
        clr_count = 1'b0;
       NS = S1;
    end
    else
       NS = S3;
default:
   LAMP = 3'b000;
   NS = IDLE;
endcase
end

always @(posedge clk)
begin
   if (clr_count==1'b0 or nrst==1'b0 )
      count = 0;
   else
      count <= count + 1;
end
 楼主| 发表于 2007-5-26 14:48:50 | 显示全部楼层
终于都分成模块了,虽然程序很小,但是就是想掌握这样的方法



//LAMP:灯的状态
//num: 倒计时
//numa: 倒计时赋值的中间变量
module traffic0(CLK,LAMP,nrst,num);
output[7:0] num;
output[2:0] LAMP;
input CLK,nrst;
reg[7:0] num,numa;
reg[3:0] CS,NS;
reg[2:0] LAMP;
reg temp;//倒计时赋值标志
parameter IDLE=4'b001, S1=4'b0010, S2=4'b0100,S3=4'b1000; //one_hot
parameter red=8'd15,yellow=8'd10,bule=8'd5; //红,黄,蓝各亮的时间  
always @(posedge CLK )
if(!nrst)
   CS<=IDLE;
else
   CS<=NS;
always @(CS or temp )
begin
   NS=4'bx;
case(CS)
IDLE:
   if(temp)
  NS=IDLE;
    else
     NS=S1;
S1:
    if(temp)
  NS=S1;
    else
     NS=S2;      
S2:   
    if(temp)
  NS=S2;
    else
     NS=S3;
      
S3:  
    if(temp)
     NS=S3;
    else
     NS=S1;
      
default:NS=IDLE;
endcase
end
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
always @(NS or nrst)//倒计时模块 赋值模块
   
if(!nrst)
begin
numa=8'd0;
end
else   
begin
case(NS)
  IDLE:
    numa=8'd0;   
  S1:
    numa=red;      
  S2:  
    numa=yellow;
  S3:  
    numa=bule;
endcase
end
  
always @(posedge CLK)//灯的状态模块
   
if(!nrst)
LAMP<=3'b000;
else   
begin
case(NS)
   IDLE:
     LAMP<=3'b000;
   S1:  
     LAMP<=3'b001;
   
   S2:  
     LAMP<=3'b010;
      
   S3:  
     LAMP<=3'b100;  
   endcase
end
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  
always @(posedge CLK ) //倒计时模块         
if(!nrst)
begin
num<=0;
temp<=0;
end
else
begin               
  
   if(!temp)
    begin
    num<=numa;
    temp<=1;
    end            
  
   else  
     begin            
   if(num>0)            
     
    begin
      if(num[3:0]==0)
        begin   
        num[3:0]<=9;
        num[7:4]<=num[7:4]-4'b0001;
        end
      else
        num[3:0]<=num[3:0]-4'b0001;
   
      if(num==1)
     temp<=0;
    else
     temp<=1;
     end
        
         else
       temp<=0;
   end            
   
   end
   

endmodule
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-2 04:56 , Processed in 0.030873 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表