FPGA常用代码
- 计数
reg [19:0]cnt; reg en_cnt; //使能计数寄存器 //计数使能模块 always@(posedge Clk or negedge Rst_n) if(!Rst_n) cnt <= 20'd0; else if(en_cnt) cnt <= cnt + 1'b1; else cnt <= 20'd0; //计数模块 always@(posedge Clk or negedge Rst_n) if(!Rst_n) cnt_full <= 1'b0; else if(cnt == 999_999) cnt_full <= 1'b1; else cnt_full <= 1'b0;
- 延时
- 上升沿检测
- 下降沿检测
- 三段式状态机
状态编码格式,有二进制、格雷码、独热码。独热码,每一个状态均使用一个寄存器,相比其他译码简单;格雷码,所需寄存器数与二进制码一样,译码复杂,但相邻位只跳动一位,一般用于异步多时钟域多bit位的转换,如异步FIFO; 二进制码,最为常见的编码方式,所用寄存器少,译码较复杂。按照Altera给的建议,选择哪一种编码格式是要根据状态机的复杂度、器件类型以及从非法状态中恢复出来的要求均有关。在使用不同的编码格式生成出来的RTL视图中可以看出二进制比独热码使用更少的寄存器。二进制用7个寄存器就可以实现100个状态的状态机,但是独热码就需要100个寄存器。但是另一方面,虽然独热码使用更多的寄存器但是其组合逻辑相对简单。一般推荐在CPLD中由于提供较多的组合逻辑资源多使用前者,FPGA中提供较多的时序逻辑而多用后者。
三段式,在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。可以看出两段式有限状态机与一段式有限状态机的区别是FSM将时序部分(状态转移部分)和组合部分(判断状态转移条件和产生输出)分开,写为两个always语句,即为两段式有限状态机。将组合部分中的判断状态转移条件和产生输入再分开写,则为三段式有限状态机。这样就使得二段式在组合逻辑特别复杂时,注意需在后面加一个触发器以消除组合逻辑对输出产生的毛刺。三段式则没有这个问题,这是由于第三个always会生成触发器。其实现在的器件根本不在乎这一点资源消耗,推荐使用二段式或者三段式以及输出寄存的状态机输出来进行描述。
编写状态机还需主要注意的事项是状态穷举或者default 避免生成锁存器;在编写状态定义时推荐使用本地化参数定义localparam,这样可以在编写时状态更清晰且不容易出错,也方便修改;在复位或者跑飞能回到初始态或者预定态;要有异步或者同步复位来确保状态机上电有个初始态。