risc-v中文社区

 找回密码
 立即注册
查看: 1185|回复: 1

[原创] MemFifo

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-9-6 09:24:51 | 显示全部楼层 |阅读模式
import chisel3._
import chisel3.util._
class FifoIO[T <: Data](private val gen:T) extends Bundle {
  val enq = Flipped(new DecoupledIO[T](gen))   //DecoupledIO-->>ReadyValidIO-->>Bundle  是带有valid和ready的复杂信号  Flipped则将bits,ready和valid信号切换方向
  val deq = new DecoupledIO[T](gen) //deq是正常的bits,ready,valid方向
}
abstract class Fifo[T <: Data](gen:T,depth:Int) extends Module {  //带有valid和ready的FIFO,并且有二个“group”,一个是enq,一个是deq
  val io = IO(new FifoIO[T](gen))
  assert(depth > 0,"Number of buffer elements needs to be larger than 0")
}



import chisel3._
import chisel3.util._
/**
  * FIFO with memory and read and write pointers.
  * Extra shadow register to handle the one cycle latency of the synchronous memory.
  */
class MemFifo[T <: Data](gen:T,depth:Int) extends Fifo(gen,depth){outer=>
  def counter(depth:Int,incr:Bool): (UInt,UInt) = {
    val cntReg = RegInit(0.U(log2Ceil(depth)))  //depth-1值所需要的bit位数量
    val nextVal = Mux(cntReg === (depth - 1).U,0.U,cntReg + 1.U)
    when(incr) {
      cntReg := nextVal
    }
    (cntReg,nextVal)
  }
  val mem = SyncReadMem(depth,gen) //SyncReadMem同步读/写 上升沿数据有效
  val incrRead = WireInit(false.B)
  val incrWrite = WireInit(false.B)
  val (readPtr,nextRead) = counter(depth,incrRead)
  val (writePtr,nextWrite) = counter(depth,incrWrite)
  val emptyReg = RegInit(true.B)
  val fullReg = RegInit(false.B)
  val idle :: valid :: full :: Nil = Enum(3)  //用Enum定义有几个状态枚举量
  val stateReg = RegInit(idle)
  val shadowReg = Reg(gen)
  when(io.enq.valid && !fullReg) {
    mem.write(writePtr,io.enq.bits) //将io.enq.bits数据按writePtr指针指标写入内存
    emptyReg := false.B
    fullReg := nextWrite === readPtr  //下次写指针等于读指针则表示满
    incrWrite := true.B //写启动  注意:即使写启动了,但如果是full,则cntReg依然不会变,nextVal也不会变
  }
  val data = mem.read(readPtr) //读数据
  // 数据输出延迟一个时钟周期
  switch(stateReg) {
    is(idle) {
      when(!emptyReg) {  //不空
        stateReg := valid  //状态迁移到valid
        fullReg := false.B  //满标志 清
        emptyReg := nextRead === writePtr  //如果下次读指针与写指针相等则表示空
        incrRead := true.B //启动读
      }
    }
    is(valid) {
      when(io.deq.ready) {  //deq收到了ready数据准备好 指示
        when(!emptyReg) { //不空
          stateReg := valid  //继续valid状态  只要不空且一直收到ready指示则一直要发数据
          fullReg := false.B  //清 满标志
          emptyReg := nextRead === writePtr  //下次读指针与写指针相等说明空
          incrRead := true.B //启动读
        } otherwise {
          //说明是空
          stateReg := idle //状态回到idle
        }
      } otherwise {
        //说明io.deq.ready 数据准备好还没有指示
        shadowReg := data  //影子寄存器保存数据
        stateReg := full
      }
    }
    is(full) {
      when(io.deq.ready) {  //io.deq.ready收到数据准备好指示
        when(!emptyReg) {
          stateReg := valid //状态回迁到valid  发完一个数据就回到valid???
          fullReg := false.B //只要是发数据当然满标志就要清空
          emptyReg := nextRead === writePtr //只要是下次读指针与写指针相等就说明空了
          incrRead := true.B //启动读
        } otherwise {
          //说明虽然收到了io.deq.ready数据已准备好可以发了,但因为是空,所以回到idle状态
          stateReg := idle
        }
      }
    }
  }

  io.deq.bits := Mux(stateReg === valid,data,shadowReg) //valid状态数据才有效,其它状态将上次所发的数据shadowReg放到数据总线上
  io.enq.ready := !fullReg //io.enq.ready是output,表示enq端口的数据已经准备好了(只要不满),类似AXI SLAVE的READY
  io.deq.valid := stateReg === valid || stateReg === full //在valid或full状态时发出数据有效指示
}


回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 2021-9-6 09:28:05 | 显示全部楼层
生成的verilog文件内容如下:
module MemFifo(
  input        clock,
  input        reset,
  output       io_enq_ready,
  input        io_enq_valid,
  input  [2:0] io_enq_bits,
  input        io_deq_ready,
  output       io_deq_valid,
  output [2:0] io_deq_bits
);
  reg [2:0] mem [0:2]; // @[MemFifo.scala 18:24]
  wire [2:0] mem_data_data; // @[MemFifo.scala 18:24]
  wire [1:0] mem_data_addr; // @[MemFifo.scala 18:24]
  wire [2:0] mem__T_8_data; // @[MemFifo.scala 18:24]
  wire [1:0] mem__T_8_addr; // @[MemFifo.scala 18:24]
  wire  mem__T_8_mask; // @[MemFifo.scala 18:24]
  wire  mem__T_8_en; // @[MemFifo.scala 18:24]
  reg  mem_data_en_pipe_0;
  reg [1:0] mem_data_addr_pipe_0;
  reg  readPtr; // @[MemFifo.scala 11:25]
  wire [1:0] _GEN_45 = {{1'd0}, readPtr}; // @[MemFifo.scala 12:30]
  wire  _T = _GEN_45 == 2'h2; // @[MemFifo.scala 12:30]
  wire  _T_2 = readPtr + 1'h1; // @[MemFifo.scala 12:59]
  wire  nextRead = _T ? 1'h0 : _T_2; // @[MemFifo.scala 12:22]
  reg [1:0] stateReg; // @[MemFifo.scala 26:25]
  wire  _T_10 = 2'h0 == stateReg; // @[Conditional.scala 37:30]
  reg  emptyReg; // @[MemFifo.scala 23:25]
  wire  _T_11 = ~emptyReg; // @[MemFifo.scala 38:12]
  wire  _T_13 = 2'h1 == stateReg; // @[Conditional.scala 37:30]
  wire  _GEN_21 = io_deq_ready & _T_11; // @[MemFifo.scala 46:26]
  wire  _T_16 = 2'h2 == stateReg; // @[Conditional.scala 37:30]
  wire  _GEN_34 = _T_16 & _GEN_21; // @[Conditional.scala 39:67]
  wire  _GEN_38 = _T_13 ? _GEN_21 : _GEN_34; // @[Conditional.scala 39:67]
  wire  incrRead = _T_10 ? _T_11 : _GEN_38; // @[Conditional.scala 40:58]
  reg  writePtr; // @[MemFifo.scala 11:25]
  wire [1:0] _GEN_46 = {{1'd0}, writePtr}; // @[MemFifo.scala 12:30]
  wire  _T_3 = _GEN_46 == 2'h2; // @[MemFifo.scala 12:30]
  wire  _T_5 = writePtr + 1'h1; // @[MemFifo.scala 12:59]
  wire  nextWrite = _T_3 ? 1'h0 : _T_5; // @[MemFifo.scala 12:22]
  reg  fullReg; // @[MemFifo.scala 24:24]
  wire  _T_6 = ~fullReg; // @[MemFifo.scala 28:24]
  wire  incrWrite = io_enq_valid & _T_6; // @[MemFifo.scala 28:21]
  reg [2:0] shadowReg; // @[MemFifo.scala 27:22]
  wire  _T_9 = nextWrite == readPtr; // @[MemFifo.scala 31:26]
  wire  _GEN_8 = incrWrite ? 1'h0 : emptyReg; // @[MemFifo.scala 28:34]
  wire  _GEN_9 = incrWrite ? _T_9 : fullReg; // @[MemFifo.scala 28:34]
  wire  _T_12 = nextRead == writePtr; // @[MemFifo.scala 41:30]
  wire  _GEN_12 = _T_11 ? _T_12 : _GEN_8; // @[MemFifo.scala 38:23]
  wire  _GEN_20 = io_deq_ready ? _GEN_12 : _GEN_8; // @[MemFifo.scala 46:26]
  wire  _GEN_33 = _T_16 ? _GEN_20 : _GEN_8; // @[Conditional.scala 39:67]
  wire  _GEN_37 = _T_13 ? _GEN_20 : _GEN_33; // @[Conditional.scala 39:67]
  wire  _GEN_42 = _T_10 ? _GEN_12 : _GEN_37; // @[Conditional.scala 40:58]
  wire  _T_19 = stateReg == 2'h1; // @[MemFifo.scala 77:31]
  wire  _T_23 = stateReg == 2'h2; // @[MemFifo.scala 79:50]
  assign mem_data_addr = mem_data_addr_pipe_0;
  `ifndef RANDOMIZE_GARBAGE_ASSIGN
  assign mem_data_data = mem[mem_data_addr]; // @[MemFifo.scala 18:24]
  `else
  assign mem_data_data = mem_data_addr >= 2'h3 ? _RAND_1[2:0] : mem[mem_data_addr]; // @[MemFifo.scala 18:24]
  `endif // RANDOMIZE_GARBAGE_ASSIGN
  assign mem__T_8_data = io_enq_bits;
  assign mem__T_8_addr = {{1'd0}, writePtr};
  assign mem__T_8_mask = 1'h1;
  assign mem__T_8_en = io_enq_valid & _T_6;
  assign io_enq_ready = ~fullReg; // @[MemFifo.scala 78:16]
  assign io_deq_valid = _T_19 | _T_23; // @[MemFifo.scala 79:16]
  assign io_deq_bits = _T_19 ? mem_data_data : shadowReg; // @[MemFifo.scala 77:15]

  always @(posedge clock) begin
    if(mem__T_8_en & mem__T_8_mask) begin
      mem[mem__T_8_addr] <= mem__T_8_data; // @[MemFifo.scala 18:24]
    end
    if (_T_10) begin
      mem_data_en_pipe_0 <= _T_11;
    end else if (_T_13) begin
      mem_data_en_pipe_0 <= _GEN_21;
    end else begin
      mem_data_en_pipe_0 <= _GEN_34;
    end
    if (_T_10 ? _T_11 : _GEN_38) begin
      mem_data_addr_pipe_0 <= {{1'd0}, readPtr};
    end
    if (reset) begin
      readPtr <= 1'h0;
    end else if (incrRead) begin
      if (_T) begin
        readPtr <= 1'h0;
      end else begin
        readPtr <= _T_2;
      end
    end
    if (reset) begin
      stateReg <= 2'h0;
    end else if (_T_10) begin
      if (_T_11) begin
        stateReg <= 2'h1;
      end
    end else if (_T_13) begin
      if (io_deq_ready) begin
        if (_T_11) begin
          stateReg <= 2'h1;
        end else begin
          stateReg <= 2'h0;
        end
      end else begin
        stateReg <= 2'h2;
      end
    end else if (_T_16) begin
      if (io_deq_ready) begin
        if (_T_11) begin
          stateReg <= 2'h1;
        end else begin
          stateReg <= 2'h0;
        end
      end
    end
    emptyReg <= reset | _GEN_42;
    if (reset) begin
      writePtr <= 1'h0;
    end else if (incrWrite) begin
      if (_T_3) begin
        writePtr <= 1'h0;
      end else begin
        writePtr <= _T_5;
      end
    end
    if (reset) begin
      fullReg <= 1'h0;
    end else if (_T_10) begin
      if (_T_11) begin
        fullReg <= 1'h0;
      end else if (incrWrite) begin
        fullReg <= _T_9;
      end
    end else if (_T_13) begin
      if (io_deq_ready) begin
        if (_T_11) begin
          fullReg <= 1'h0;
        end else if (incrWrite) begin
          fullReg <= _T_9;
        end
      end else if (incrWrite) begin
        fullReg <= _T_9;
      end
    end else if (_T_16) begin
      if (io_deq_ready) begin
        if (_T_11) begin
          fullReg <= 1'h0;
        end else if (incrWrite) begin
          fullReg <= _T_9;
        end
      end else begin
        fullReg <= _GEN_9;
      end
    end else begin
      fullReg <= _GEN_9;
    end
    if (!(_T_10)) begin
      if (_T_13) begin
        if (!(io_deq_ready)) begin
          shadowReg <= mem_data_data;
        end
      end
    end
  end
endmodule
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2024-4-29 07:11 , Processed in 0.015405 second(s), 17 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表