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

2014-8-10 22:22 2662 13 15 分类: FPGA/CPLD 文集: 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化的基础。

文章评论2条评论)

登录后参与讨论

用户377235 2016-3-22 20:52

文章看完,受益匪浅,谢谢

loodao_812158451 2015-7-20 09:52

看完所有文章,赞
相关推荐阅读
阿昏豆 2015-11-21 23:25
把大象关冰箱的步骤 --- NAND FLASH控制器磨损管理算法芯片化硬实现
把大象关冰箱的步骤 --- NAND FLASH控制器磨损管理算法芯片化硬实现   目前,存储领域包括eMMC,SATA SSD ,PCIe SSD等控制器是一个非常热门的领域。通常,由于...
阿昏豆 2015-11-09 22:25
平行宇宙的追逐--异步FIFO控制器的设计
  平行宇宙的追逐--异步FIFO控制器的设计。    在逻辑设计中,通常会用到异步FIFO,异步FIFO控制器是经典的异步信号传输的范例,通过FIFO控制器与异步双端口RAM的组合实现数据的...
阿昏豆 2014-08-23 23:36
FPGA研发之道(25)-管脚
     管脚是FPGA重要的资源之一,FPGA的管脚分别包括,电源管脚,普通I/O,配置管脚,时钟专用输入管脚GCLK等。 (1)电源管脚:    通常来说: FPGA内部的电压包括...
阿昏豆 2014-08-07 21:53
FPGA研发之道(23)-控制(上)
本质上说,FPGA的模块设计就是将输入转化成想要得到的输出结果。而除了某些简单模块,即在当拍内完成,即将输入进行逻辑操作后,再输出。(如简单加法器等)。其余大部分的设计需要通过时序逻辑和组合逻辑混合实...
阿昏豆 2014-08-06 23:12
FPGA研发之道(23)-控制(上)
本质上说,FPGA的模块设计就是将输入转化成想要得到的输出结果。而除了某些简单模块,即在当拍内完成,即将输入进行逻辑操作后,再输出。(如简单加法器等)。其余大部分的设计需要通过时序逻辑和组合逻辑混合实...
我要评论
2
13
关闭 站长推荐上一条 /2 下一条