• 两种fifo实现方式的差异


    减少数据通路翻转来降低功耗:
    FIFO (当容量较小而使用寄存器作为存储部分)设计为例,虽然理论上可以使用比较简单的数据表项逐次移位的方式,实现FIFO 的先入先出功能,但是却应该使用维护读写指针的方式(数据表项寄存器则不用移位)实现先入先出的功能。因为数据表项逐次移位的方式会造成寄存器的大量翻转,相比而言,使用读写指针的方式实现则保持了表项寄存器中的值静止不动,从而大幅减少动态功耗,因此应该优先采用此方法。

    数据表项逐次移位方式:

    数据存储在数组中,通过逐次移位的方式实现数据的入队和出队操作。
    入队操作时,将新数据写入队尾,并将队尾指针指向下一个位置。
    出队操作时,读取队首的数据,并将队首指针指向下一个位置。
    这种方式下,数据表项的顺序是按照入队的顺序依次排列的,即新数据会覆盖掉旧数据。

    module fifo (
      input clk,
      input reset,
      input [DATA_WIDTH-1:0] data_in,
      input push,
      input pop,
      output reg [DATA_WIDTH-1:0] data_out,
      output reg full,
      output reg empty
    );
    
      parameter DATA_WIDTH = 8;  // 数据宽度
      parameter DEPTH = 16;      // FIFO深度
    
      reg [DATA_WIDTH-1:0] buffer [DEPTH-1:0];  // FIFO缓冲区
      reg [4:0] head_ptr;   // 指向队首的指针
      reg [4:0] tail_ptr;   // 指向队尾的指针
      reg [4:0] count;      // 当前队列中的数据项数量
    
      always @(posedge clk or posedge reset) begin
        if (reset) begin
          data_out <= 0;
          full <= 0;
          empty <= 1;
          head_ptr <= 0;
          tail_ptr <= 0;
          count <= 0;
        end else begin
          // 入队操作
          if (push && !full) begin
            buffer[tail_ptr] <= data_in;
            tail_ptr <= tail_ptr + 1;
            count <= count + 1;
          end
    
          // 出队操作
          if (pop && !empty) begin
            data_out <= buffer[head_ptr];
            head_ptr <= head_ptr + 1;
            count <= count - 1;
          end
    
          // 更新队列状态
          full <= (count == DEPTH);
          empty <= (count == 0);
        end
      end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    在上述Verilog代码中,定义了一个fifo模块,该模块包含了输入和输出信号,以及FIFO缓冲区和相关指针等变量。在时钟上升沿或复位事件发生时,根据不同的条件进行入队和出队操作。push信号表示入队操作,在FIFO非满的情况下,将数据写入队尾,并更新队尾指针和数据项数量。pop信号表示出队操作,在FIFO非空的情况下,读取队首的数据,更新队首指针和数据项数量。

    维护读写指针的方式:

    数据存储仍然使用数组,但不再需要逐次移位。
    入队操作时,将新数据写入当前队尾指针所指向的位置,并更新队尾指针为下一个位置。
    出队操作时,读取当前队首指针所指向的数据,并更新队首指针为下一个位置。
    队首指针和队尾指针通过取模运算来循环更新,确保在达到深度上限时能够回到初始位置。
    这种方式下,数据表项的顺序与入队的顺序相同,不会发生顺序覆盖。

    module fifo (
      input clk,
      input reset,
      input [DATA_WIDTH-1:0] data_in,
      input push,
      input pop,
      output reg [DATA_WIDTH-1:0] data_out,
      output reg full,
      output reg empty
    );
    
      parameter DATA_WIDTH = 8;  // 数据宽度
      parameter DEPTH = 16;      // FIFO深度
    
      reg [DATA_WIDTH-1:0] buffer [DEPTH-1:0];  // FIFO缓冲区
      reg [4:0] head_ptr;   // 指向队首的指针
      reg [4:0] tail_ptr;   // 指向队尾的指针
      reg [4:0] count;      // 当前队列中的数据项数量
    
      always @(posedge clk or posedge reset) begin
        if (reset) begin
          data_out <= 0;
          full <= 0;
          empty <= 1;
          head_ptr <= 0;
          tail_ptr <= 0;
          count <= 0;
        end else begin
          // 入队操作
          if (push && !full) begin
            buffer[tail_ptr] <= data_in;
            tail_ptr <= (tail_ptr + 1) % DEPTH;
            count <= count + 1;
          end
    
          // 出队操作
          if (pop && !empty) begin
            data_out <= buffer[head_ptr];
            head_ptr <= (head_ptr + 1) % DEPTH;
            count <= count - 1;
          end
    
          // 更新队列状态
          full <= (count == DEPTH);
          empty <= (count == 0);
        end
      end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    vue2编辑markdown
    ReactNative 学习总结 个人梳理
    王道p18 第12题假设 A中的 n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素:否则输出-1
    python篇----进程+线程
    罕见病 对称性脂肪瘤(MSL) 马德龙病
    17 多远线性回归
    final、finalize 和 finally
    mysql索引、事务、存储引擎
    Elasticsearch系列教程之核心概念及用法
    Javaweb之javascript的详细解析
  • 原文地址:https://blog.csdn.net/qq_40113966/article/details/133275018