risc-v中文社区

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

[原创] RegFifo

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-9-5 22:19:34 | 显示全部楼层 |阅读模式
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._
class RegFifo[T <: Data](gen:T,depth:Int) extends Fifo(gen,depth) {
  def counter(depth:Int,incr:Bool): (UInt,UInt) = {
    val cntReg = RegInit(0.U(log2Ceil(depth).W)) //log2Ceil(n:BigInt)求log2的值且向上取整 log2Ceil(1)->0,log2Ceil(2)->1,log2Ceil(3)->2,log2Ceil(4)->2,log2Ceil(5)->3
    //要想获取n值所对应的bit数量则log2Ceil(n+1)  4-->0100->3bit  log2Ceil(4+1)=3
    //cntReg表示深度depth-1值所需要的bit位数
    val nextVal = Mux(cntReg === (depth - 1).U,0.U,cntReg + 1.U) //达到最大深度则复位,否则下次值为cntReg加1
    when (incr) {
      cntReg := nextVal  //只要没有达到最大深度,每次加1
    }
    (cntReg,nextVal) //以元组类型返回计数器值以下一次值
  }
  val memReg = Reg(Vec(depth,gen)) //深度为depth的向量
  val incrRead = WireInit(false.B)
  val incrWrite = WireInit(false.B)
  val (readPtr,nextRead) = counter(depth,incrRead) //返回的元组中的readPtr和nextRead都是Reg硬件类型???
  val (writePtr,nextWrite) = counter(depth,incrWrite)

  val emptyReg = RegInit(true.B) //FIFO空标志
  val fullReg = RegInit(false.B) //FIFO满标志

  when(io.enq.valid && !fullReg) { //收到MASTER发来的valid,且FIFO不满
    memReg(writePtr) := io.enq.bits //writePtr指针所指的FIFO缓冲区的数据被设置为MASTER发来的数据
    emptyReg := false.B  //需要清空 空标志位
    fullReg := nextWrite === readPtr //写指针和读指针相同时则置 满标志
    incrWrite := true.B  //启动写计数
  }
  when(io.deq.ready && !emptyReg) { //返回数据给MASTER的控制相关逻辑
    fullReg := false.B //清满标志位
    emptyReg := nextRead === writePtr //读写指针相等时则为空
    incrRead := true.B //启动读计数
  }
  io.deq.bits := memReg(readPtr) //根据读指针将缓冲区对应位置的数据返回
  io.enq.ready := !fullReg  //output出准备好信号 只要不满
  io.deq.valid := !emptyReg //只要不空 output类型的deq.valid就发出指标
}

回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 2021-9-5 22:20:53 | 显示全部楼层
Driver.execute(Array("--target-dir","generated"),()=>new RegFifo(UInt(4.W),5))
产生的verilog文件内容如下:
module RegFifo(
  input        clock,
  input        reset,
  output       io_enq_ready,
  input        io_enq_valid,
  input  [3:0] io_enq_bits,
  input        io_deq_ready,
  output       io_deq_valid,
  output [3:0] io_deq_bits
);
  reg [3:0] memReg_0; // @[RegFifo.scala 16:19]
  reg [3:0] memReg_1; // @[RegFifo.scala 16:19]
  reg [3:0] memReg_2; // @[RegFifo.scala 16:19]
  reg [3:0] memReg_3; // @[RegFifo.scala 16:19]
  reg [3:0] memReg_4; // @[RegFifo.scala 16:19]
  reg [2:0] readPtr; // @[RegFifo.scala 7:25]
  wire  _T = readPtr == 3'h4; // @[RegFifo.scala 10:30]
  wire [2:0] _T_2 = readPtr + 3'h1; // @[RegFifo.scala 10:59]
  wire [2:0] nextRead = _T ? 3'h0 : _T_2; // @[RegFifo.scala 10:22]
  reg  emptyReg; // @[RegFifo.scala 22:25]
  reg [31:0] _RAND_6;
  wire  _T_9 = ~emptyReg; // @[RegFifo.scala 31:24]
  wire  incrRead = io_deq_ready & _T_9; // @[RegFifo.scala 31:21]
  reg [2:0] writePtr; // @[RegFifo.scala 7:25]
  reg [31:0] _RAND_7;
  wire  _T_3 = writePtr == 3'h4; // @[RegFifo.scala 10:30]
  wire [2:0] _T_5 = writePtr + 3'h1; // @[RegFifo.scala 10:59]
  wire [2:0] nextWrite = _T_3 ? 3'h0 : _T_5; // @[RegFifo.scala 10:22]
  reg  fullReg; // @[RegFifo.scala 23:24]
  reg [31:0] _RAND_8;
  wire  _T_6 = ~fullReg; // @[RegFifo.scala 25:24]
  wire  incrWrite = io_enq_valid & _T_6; // @[RegFifo.scala 25:21]
  wire  _T_8 = nextWrite == readPtr; // @[RegFifo.scala 28:26]
  wire  _GEN_12 = incrWrite ? 1'h0 : emptyReg; // @[RegFifo.scala 25:34]
  wire  _T_11 = nextRead == writePtr; // @[RegFifo.scala 33:26]
  wire  _GEN_16 = incrRead ? _T_11 : _GEN_12; // @[RegFifo.scala 31:35]
  wire [3:0] _GEN_19 = 3'h1 == readPtr ? memReg_1 : memReg_0; // @[RegFifo.scala 36:15]
  wire [3:0] _GEN_20 = 3'h2 == readPtr ? memReg_2 : _GEN_19; // @[RegFifo.scala 36:15]
  wire [3:0] _GEN_21 = 3'h3 == readPtr ? memReg_3 : _GEN_20; // @[RegFifo.scala 36:15]
  assign io_enq_ready = ~fullReg; // @[RegFifo.scala 37:16]
  assign io_deq_valid = ~emptyReg; // @[RegFifo.scala 38:16]
  assign io_deq_bits = 3'h4 == readPtr ? memReg_4 : _GEN_21; // @[RegFifo.scala 36:15]

  always @(posedge clock) begin
    if (incrWrite) begin
      if (3'h0 == writePtr) begin
        memReg_0 <= io_enq_bits;
      end
    end
    if (incrWrite) begin
      if (3'h1 == writePtr) begin
        memReg_1 <= io_enq_bits;
      end
    end
    if (incrWrite) begin
      if (3'h2 == writePtr) begin
        memReg_2 <= io_enq_bits;
      end
    end
    if (incrWrite) begin
      if (3'h3 == writePtr) begin
        memReg_3 <= io_enq_bits;
      end
    end
    if (incrWrite) begin
      if (3'h4 == writePtr) begin
        memReg_4 <= io_enq_bits;
      end
    end
    if (reset) begin
      readPtr <= 3'h0;
    end else if (incrRead) begin
      if (_T) begin
        readPtr <= 3'h0;
      end else begin
        readPtr <= _T_2;
      end
    end
    emptyReg <= reset | _GEN_16;
    if (reset) begin
      writePtr <= 3'h0;
    end else if (incrWrite) begin
      if (_T_3) begin
        writePtr <= 3'h0;
      end else begin
        writePtr <= _T_5;
      end
    end
    if (reset) begin
      fullReg <= 1'h0;
    end else if (incrRead) begin
      fullReg <= 1'h0;
    end else if (incrWrite) begin
      fullReg <= _T_8;
    end
  end
endmodule
回复

使用道具 举报

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

本版积分规则



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

GMT+8, 2024-4-29 08:52 , Processed in 0.021504 second(s), 17 queries .

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

Copyright © 2018-2021, risc-v open source

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