新闻中心

EEPW首页 > 嵌入式系统 > 牛人业话 > FPGA研发之道(23)-控制(上)

FPGA研发之道(23)-控制(上)

作者:时间:2014-12-02来源:网络收藏

  本质上说,的模块设计就是将输入转化成想要得到的输出结果。而除了某些简单模块,即在当拍内完成,即将输入进行逻辑操作后,再输出。(如简单加法器等)。其余大部分的设计需要通过时序逻辑和组合逻辑混合实现,时序逻辑带来就是延迟起效的问题,举例说,如实现某个信号(start)起效后,接下来五个周期需要分别进行五种操作,分别是op0,op1,op2,op3,op4 等等。如何进行控制,这就是每个工程师要面对的问题。

本文引用地址:http://www.amcfsurvey.com/article/266275.htm

  对于简单控制,分别可以采用计数和移位寄存器的方式来解决问题。而对于较为复杂的控制,则需要设计来解决。下面将分别介绍

  : 对于上述操作来说,start起效后,可以通过计数实现,设置寄存器count[2:0],有效信号开始时计数自加。 计数的方式带来的问题就是,计数从零开始还是从1开始,假如初始化为0,则从0-4状态可以分别输出op0,op1,op2,op3,op4,但是在无有效信号时,计数会保持0,从而造成op0的输出。 上述举例虽然简单,但是确实很多初学者或者工程师在仿真时会经常会犯的错误。从设计来说,计数需要考虑初始值对于输出的影响。同样计数带来的另一个问题就是,从零开始的计数会导致设计与实际不一致,例如,一个信号9拍后拉低,但从零计数到8时,已经到9拍了(0-8),这种设计会导致命名count==8 与9拍存在不一致的现象。当然也可以从1计数到9,这样状态在count==9时触发。这样就会初始化需要复位寄存器为1。当然这个问题大端和小端的争斗一样,没有终点。一个设计中如果多种计数来驱动计数的话,就需要特别小心这个问题计数。当然也可把问题交给仿真器,仿真时根据波形调整,计数的状态。

  移位寄存器:如采用移位寄存器,根据上述例子,则start信号有效后,设计5bit的移位寄存器flag[4:0]分别利用寄存器的某BIT来控制输出,从而在每BIT有效时,分别输出op0,op1,op2,op3,op4。假设此种状态较少,寄存器资源较为丰富,因此利用移位寄存器是一个不错的注意。

  assign op4 = ( count == 3’b100) ;

  assign op4 = flag[4] ;

  比较上述两种输出,则可以看出,通过计数的方式占用输出资源较多,而移位寄存器在此种应用下,占用逻辑就相对简单。(仅针对小规模的计数来说,对于超过16的计数,则使用更优)。另外,通过移位寄存器可以方便的进行时序控制,不用纠结从零开始还是从1开始的问题,在某些简单的处理下能够达到更小的面积和更快的时序。

  对于复杂的控制,则,就是必须的。对于实现,其实并不需要那么多的设计的方法。主要就是两个要点。(1)独热码。(2)三段式。

  对于第一点来说,独热码,因为FPGA内部寄存器资源较多,另外独热码将会带来额外的面积和时序优化的好处。则以上述例子为例,增加状态转移的触发信号,状态转移图如下所示:

  

 

  状态独热码(也可以用define localparam)建议使用parameter或者localparam

  parameter idle == 6’b000001,

  op0_state == 6’b000010,

  op1_state == 6’b000100,

  op2_state == 6’b001000,

  op3_state == 6’b010000,

  op4_state == 6’b100000;

  三段式结构如下

  //(1)当前状态

  always@(posedge sys_clk or negedge rst_n)

  if(!rst_n)

  cs_state <= idle;

  else

  cs_state <= ns_state;

  //(2)下一状态的赋值

  always@(*)

  case(cs_state)

  idle : if(start)

  ns_state = op0_state;

  else

  ns_state = idle;

  op0_state :

  if(op0_over)

  ns_state = op1_state;

  else

  ns_state = op0_state;

  op1_state :

  if(op1_over)

  ns_state = op2_state;

  else

  ns_state = op1_state;

  op2_state :

  if(op2_over)

  ns_state = op3_state;

  else

  ns_state = op2_state;

  op3_state :

  if(op3_over)

  ns_state = op4_state;

  else

  ns_state = op3_state;

  op4_state :

  if(op4_over)

  ns_state = op4_state;

  else

  ns_state = idle;

  default ns_state = idle;

  endcase

  //(3)输出状态

  assign out1 = (cs_state == op0_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;

  上述例子,介绍独热码和三段式。三段式的好处不用说,就是逻辑清楚。可以看出out1输出为组合输出。out_2_reg为寄存输出。那么独热码在FPGA内部的优势又有哪些?

  (1)综合后,逻辑简单

  例如assign out1 = (cs_state == op0_state); 综合后的电路等同于

  assign out1= cs_state(0) ;//可以看出无逻辑消耗

  而 out2_reg 的电路等同于 将cs_state(2)寄存一拍,只需一个寄存器的消耗

  (2)时序优化。

  从上述同样得出结论,如果是使用某状态cs_state(n)作为其他信号的输入来说,其本身为寄存器信号,因此关键路径就会减少一级。可能运行较快的频率就会增加。如不是独**,对比这两条语句cs_state = 3 与cs_state(3) 一个是组合输出,一个寄存器输出。其不同也就是上述计数与移位寄存器的区别一致。

  那么一般状态机会产生的错误会有哪些那?

  首先;就是状态不全产生LATCH,前文已述,这是FPGA设计的大敌,解决这个问题的方法可以通过所有分支都设定确定状态,如上例中。有没有更简单的方式?

  其此:状态机上述描述,并不直观的显现综合后电路的描述,有没有更直接的rtl的描述,一眼就能看出独热码的特征和好处?

  最后:状态机是一个较为成熟技术,还会有哪些值得关注的地方?

  这些问题,下节再述。



关键词: FPGA 状态机 计数器

评论


相关推荐

技术专区

关闭