lihui_140601的个人空间 https://blog.eetop.cn/1494260 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

FPGA研发之道(24)-控制(下)

已有 1129 次阅读| 2015-11-22 19:28 |个人分类:FPGA研发之道

 首先依次回答上篇提出的几个问题:

      第一个问题:如何避免状态机产生lacth 示例如下,通过在always*)语句块中,添加默认赋值,ns_state = cs_state;

always@(*)

      ns_state = cs_state;

      case(cs_state)     

         idle :

                  if(start)

                  ns_state =  op1_state;

         op0_state :

                if(op0_over)

                  ns_state =  op1_state;

         op1_state :

                if(op1_over)

                  ns_state =  op2_state;

         op2_state :

                if(op2_over)

                  ns_state =  op3_state;

         op3_state :

                if(op3_over)

                  ns_state =  op4_state;

         op4_state :

                if(op4_over)

                  ns_state =  op4_state;

         default ns_state = idle;

       endcase

这样,分支没有赋值的语句全部会赋值为ns_state = cs_state ;IDLE状态为例,当前cs_stateidle。因此实际上 ns_state=idle。这条语句的作用,即在没有分支赋值的情况下,默认赋值当前状态。

第二个问题:更直观的独热码的状态机实现方式。示例如下

//状态定义

parameter   idle == 0,

             op0_state == 1,

             op1_state == 2,

             op2_state == 3,

             op3_state == 4,

             op4_state == 5;

//1)当前状态

always@(posedge sys_clk or negedge rst_n)

       if(!rst_n)

         cs_state <=  6'b000001;

       else

         cs_state <= ns_state;

//2)下一状态的赋值

always@(*)

        ns_state = 0;

      case(1)     

         cs_state[idle] :

                  if(start)

                    ns_state[op0_state] =  1'b1;

                  else

                    ns_state[idle] = 1'b1; 

          cs_state[op0_state] :

                  if(op0_over)

                    ns_state[op1_state] = 1'b1;

                  else

                    ns_state[op0_state] = 1'b1; 

          cs_state[op1_state] :

                  if(op1_over)

                    ns_state[op2_state] = 1'b1;

                  else

                    ns_state[op1_state] = 1'b1; 

         cs_state[op2_state] :

                  if(op2_over)

                    ns_state[op3_state] = 1'b1;

                  else

                    ns_state[op2_state] = 1'b1; 

         cs_state[op3_state]:

                  if(op3_over)

                    ns_state[op4_state] = 1'b1;

                  else

                    ns_state[op3_state] = 1'b1; 

         cs_state[op4_state] :

                  if(op4_over)

                    ns_state[idle]= 1'b1;

                  else

                    ns_state[op4_state] = 1'b1; 

         default    ns_state[idle]= 1'b1;

       endcase

//3)输出状态  

assign out1 = cs_state [op1_state];

always@(posedge sys_clk or negedge rst_n)

       if(!rst_n)

         out2_reg <= 1'b0;

       else if (cs_state[op2_state])

         out2_reg <= 1'b1;

       else

         out2_reg <= 1'b0;

        

上例中,定义状态机是,同样定义为0,1,2,3,4,5,6的值而不是独热码,只不过使用时,这些值用于赋值的为状态机的某一bit。值得注意的是,在ns_state 通过组合逻辑赋值时,首先需要将ns_state赋值为零,也就数说,除了需要赋值为1的状态,其他都需要赋值为0。但此种编码方式下,就需要谨慎对待分支赋值不全的情况,因此此时,ns_state会赋值为0。产生非想要的后果。

   通过第三段的输出赋值可以看出,其输出分别是cs_state [op1_state]的直接输出,cs_state[op2_state]的寄存后一拍再输出。其产生的效果与前文(控制-上)中介绍的产生的效果是一致的。因此可根据习惯,选择一种的实现即可。

最后一个问题:状态机使用可以直观的通过定义的状态来控制各个信号的输出和控制,独热码本质上还是将状态机转变成一组某一时刻只有一个起效的寄存器,换个角度可以看做加强版的移位寄存器。其他需要注意问题有,

1)如果状态机定义而没有使用,综合工具将综合掉此状态,因此综合后的状态会和工程师所定义的状态不同。通过检查综合文件,就能得知其对应关系,避免通过嵌入式逻辑分析仪抓信号时,信号与实际不一致现象。

2)如通过单周期信号启动状态机,要注意,如单周期信号起效时,状态机未跳转回有效状态,会导致出错,应该将单周期信号转换成电平信号,等启动有效后再将电平信号拉低。

3)状态如出现未定义的状态(如独热码出现全零状态),latch是其中一个主要的原因,上电后未有效复位也会导致此种可能。

4)状态机结合移位寄存器可以有效减少状态的数目。例如某个状态中,每个周期要进行多个操作,不需要再分解成多个小状态,通过移位寄存器来控制这些状态的操作能够简化设计。

总之:状态机是FPGA设计的一项基本设计,而“独热码”和“三段式的设计能够使设计达到事半功倍的效果。也是事实上行业内的FPGA设计的标准写法。而标准化能使难以理解的FPGA的代码能够有更好的移植和IP化的基础。


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 0

    获赞
  • 2

    评论
  • 访问数
关闭

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


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

GMT+8, 2024-12-23 00:17 , Processed in 0.016001 second(s), 11 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部