FPGA学习杂记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Sean_92/article/details/51056051

FPGA学习杂记

  • for语句在RTL级编码中极少使用,原因是for循环会被综合器展开为所有变量情况的执行语句,每个变量单独占用寄存器资源,不能有效地复用资源,造成巨大的资源浪费。

  • if……else if……else语句是有优先级的,而case语句是平行的结构。建立优先级结构会消耗大量的组合逻辑,所以能使用case语句的地方尽量用case替代。

  • 同步时序电路

    1. 电路的核心逻辑用触发器实现;
    2. 电路的主要信号和输出信号等都是由时钟沿驱动触发器产生的
    3. 同步时序电路可以很好地避免毛刺;
    4. 有利于静态时序分析,验证时序性能;
    5. 利于器件移植。
  • 稳定可靠的数据采样必须遵从以下两个基本原则:

    1. 在有效时钟沿到达前,数据输入至少已经稳定了采样寄存器的setup时间之久,这条原则简称满足setup时间原则;
    2. 在有效时钟沿到达后,数据输入至少还将稳定保持采样寄存器的hold时间之久,这条原则简称满足hold时间原则。
  • reg型不一定综合成寄存器

    1. 一般来说,wire型指定的数据和网线通过组合逻辑实现,reg型的定义有可能只是纯组合逻辑。
      case(Addr)
          2'b00: Dout = Din[1:0];
          2'b01: Dout = Din[3:2];
          2'b10: Dout = Din[5:4];
          default: Dout = Din[7:6];
      endcase
  • 亚稳态

    如果触发器的setup和hold时间不满足,就可能产生亚稳态,此时触发器输出端Q在有效时钟沿之后较长一段时间内处于不确定的状态,这段时间内Q端产生毛刺并不断振荡,最终固定在某一电压值。

    亚稳态的危害主要体现在破坏系统的稳定性上。毛刺、振荡或固定的某一电压值可能会造成逻辑误判,使状态输出出错。只要系统中有异步元件,亚稳态就无法避免。

  • 模块复用

    模块复用or逻辑复制属于速度or面积的问题。简单地从组合逻辑上来说,当时序满足要求的情况下,一般采用模块复用的方式节省面积,相反当时序紧张时,采用逻辑复制的方式提高速度。

    //使用了两个乘法器
    assign databar = ~datain + 1;
    assign square = (datain[7]) ? (databar * databar) : (datain * datain);
    //只使用一个乘法器
    assign datatmp = (datain[7]) ? (~datain + 1) : datain;
    assign square = datatmp * datatmp;
    //上面两种设计占用的资源相差一倍以上。因此对时序要求没有太高的时候尽量少用乘法器。
  • 状态机的设计

    待续。

可编程逻辑设计中常用的4种设计思想与技巧

  • 乒乓操作

    乒乓操作通“输入数据流选择单元”和“输出数据流选择单元”按节拍切换,将经过缓冲的数据没有时间停顿地送到“数据流运算处理模块”。乒乓操作非常适合对数据流进行流水线式处理。

    乒乓操作基本框图

    乒乓操作一般可用双口ram和fifo。如果数据完全是按顺序进行存取的话,fifo会更加简便(无需对地址进行操作)。

    /*控制单元*/
    always @(posedge CLK or negedge nRST)
    begin
        if(!nRST)
        begin
           wr_flag <= 0;
           rd_flag <= 0;
        end
        else
        begin
            case(flag)
                1'b0: 
                    begin
                        wr_flag <= 0;
                        rd_flag <= 1;
                    end
                1'b1: 
                    begin
                        wr_flag <= 1;
                        rd_flag <= 0;
                    end
            endcase
        end
    end
    /*输入数据流选择单元*/
    always @(posedge CLK or negedge nRST)
    begin
        if(!nRST)
        begin
            buffer1 <= 0;
            buffer2 <= 0;
        end
        else
        begin
            case(wr_flag)
                1'b0: buffer1 <= datain;
                1'b1: buffer2 <= datain;
            endcase
        end
    end
    /*输出数据流选择单元*/
    always @(posedge CLK or negedge nRST)
    begin
        if(!nRST)
            dataout <= 0;
        else
        begin
            case(rd_flag)
                1'b0: dataout <= buffer1;
                1'b1: dataout <= buffer2;
            endcase
        end
    end
  • 串并转换

    串并转换的核心思想是速度与面积的互换。数据量小的串并转换一般使用寄存器移位即可完成。

    temp <= {temp[6:0],datain};
  • 流水线操作

    如果某个设计的处理流程分为若干步骤,且整个数据处理是单向的,前一步骤的输出是下一步骤的输入,则可以使用流水线设计方式,实现类似移位寄存器组的设计。进行流水线操作时应统筹考虑各模块的数据速率应相同。

    if(!inflag)
    begin
        if(inclk)
        begin
            outclk <= 1;
            outflag <= 0;
        end
        else
            outclk <= 0;
    end
    else
    begin
        if(inclk)
        begin
            outclk <= 1;
            outflag <= 1;
            outdata <= {outdata[6:0],outdata[7]};
            //在这里对输出进行处理//
        end
        else
            outclk <= 0;
    end
    
  • 数据接口同步

    数据接口同步中主要问题在于异步时钟域数据的同步,其中主要有以下两种情况:

    1. 两个时钟频率相同,但相差不固定,或相差固定但是不可测,简称同频异相问题

      同频异相问题简单的解决方法是用后级时钟对前级数据采样两次。可靠的做法是用DPRAM或FIFO完成数据的存取。

    2. 两个时钟域频率根本不同,简称异频问题

      异频问题的解决办法也是通过DPRAM或FIFO实现的。由于时钟频率不同,两个端口的数据吞吐率不同,设计时应开好缓冲区,并监控确保数据不会溢出。

状态机的设计

  • 选择状态机的编码方式

    Binary Gray Code(格雷码)使用最少的触发器和较多的组合逻辑,而one-hot编码相反。由于CPLD更多地提供组合逻辑资源,而FPGA更多提供触发器资源,因而CPLD多使用格雷码,FPGA多使用one-hot编码。另一方面,对于小型设计使用格雷码更有效,而大型状态机使用one-hot更高效。

  • 状态机的描述方法

    状态机描述时关键是要描述清楚几个状态机的要素,即如何进行状态转移每个状态的输出是什么状态转移的条件等。具体描述时方法各种各样,最常见的有三种描述方式:

    1. 一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;
    2. 二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;
    3. 三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出

    一般而言,推荐的FSM 描述方法是后两种。这是因为:FSM和其他设计一样,最好使用同步时序方式设计,以提高设计的稳定性,消除毛刺。状态机实现后,一般来说,状态转移部分是同步时序电路而状态的转移条件的判断是组合逻辑。

    第二种描述方法同第一种描述方法相比,将同步时序和组合逻辑分别放到不同的always模块中实现,这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。但组合逻辑容易使输出产生毛刺

    第三种描述方式与第二种相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。

猜你喜欢

转载自blog.csdn.net/Sean_92/article/details/51056051
今日推荐