risc-v中文社区

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

[原创] DoubleBufferFifo

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-9-6 17:03:20 | 显示全部楼层 |阅读模式
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._
/**
  * Double buffer FIFO.
  * Maximum throughput is one word per clock cycle.
  * Each stage has a shadow buffer to handle the downstream full.
  */
class DoubleBufferFifo[T <: Data](gen:T,depth:Int) extends Fifo(gen,depth) {
  private class DoubleBuffer[T <: Data](gen:T) extends Module {
    val io = IO(new FifoIO(gen)) //带enq/deq接口(有valid/ready)且有bits收发一个数据gen:T的Bundle
    val empty :: one :: two :: Nil = Enum(3)  //用Enum定义三个状态
    val stateReg = RegInit(empty)
    val dataReg = Reg(gen) //数据寄存器,连接到gen;T ,复位影响这个寄存器,除非用":="重新连到其它信号
    val shadowReg = Reg(gen)
    switch(stateReg) {
      is(empty) { //空
        when(io.enq.valid) { //enq端口的对方发过来的valid指示数据有效,本enq端口方可以接收了
          stateReg := one //迁移到下一个状态one
          dataReg := io.enq.bits  //enq端口发来的数据保存在dataReg寄存器中
        }
      }
      is(one) {
        when(io.deq.ready && !io.enq.valid) { //本deq端口收到ready(数据已准备好)且enq端口没有收到对方(MASTER)发来的valid
          stateReg := empty
        }
        when(io.deq.ready && io.enq.valid) {//本deq收到了ready且enq的对方已发valid
          stateReg := one  //继续保存one状态 也就是说继续发数据
          shadowReg := io.enq.bits //将enq的对方发来的数据放入shadowReg影子寄存器
        }
        when(!io.deq.ready && io.enq.valid) {//本deq没有收到ready但enq的对方发来了valid
          stateReg := two //状态迁移到two
          shadowReg := io.enq.bits //将enq的对方发来的数据放入shadowReg寄存器
        }
      }
      is(two) {
        when(io.deq.ready) { //如果deq端口收到ready(数据已准备好)
          dataReg := shadowReg //将影子寄存器中的数据放入dataReg
          stateReg := one
        }
      }
    }
    io.enq.ready := (stateReg === empty || stateReg === one) //empty或one状态的时候就给enq的对方发ready信号
    io.deq.valid := (stateReg === one || stateReg === two) //one或two状态时deq端口发valid给对方
    io.deq.bits := dataReg  //deq端口要发的数据是dataReg
  }

  private val buffers = Array.fill((depth + 1)/2){ Module(new DoubleBuffer(gen))} //一半深度的缓冲区
  for(i <- 0 until (depth +1)/2 - 1) {
    //<>整体连接:先要看是同级连还是父子级连,如果是同级连则input连output,output连input
    //如果是父子级连,则input连input,output连output
    //很显然是同级连,只能是assign input类型=output类型
    //  buffers(i+1).io.enq.valid(input类型) := buffers(i).io.deq.valid(output类型)
    //  buffers(i).io.deq.ready(input类型) := buffers(i+1).io.enq.ready(output类型)
    //  buffers(i+1).io.enq.bits(input类型) := buffers(i).io.deq.bits(output类型)
    buffers(i+1).io.enq <> buffers(i).io.deq
  }
  //父子级连,只能是input连input,output连output
  //io.enq.redy(父output类型) := buffers(0).io.enq.ready(子output类型)
  //buffers(0).io.enq.valid(子input类型) := io.enq.valid(父input类型)
  // buffers(0).io.enq.bits(子input) := io.enq.bits(父input)
  io.enq <> buffers(0).io.enq
  //父子级连
  //io.deq.valid := buffers_x.io.deq.valid  父output = 子output
  //buffers_x.io.deq.ready := io.deq.ready 子input = 父input
  //io.deq.bits := buffers_x.io.deq.bits 父output = 子output
  io.deq <> buffers((depth + 1)/2 - 1).io.deq
}


回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 2021-9-6 17:04:09 | 显示全部楼层
生成的verilog文件内容如下:
module DoubleBuffer(
  input        clock,
  input        reset,
  output       io_enq_ready,
  input        io_enq_valid,
  input  [1:0] io_enq_bits,
  input        io_deq_ready,
  output       io_deq_valid,
  output [1:0] io_deq_bits
);
  reg [1:0] stateReg; // @[DoubleBufferFifo.scala 14:27]
  reg [31:0] _RAND_0;
  reg [1:0] dataReg; // @[DoubleBufferFifo.scala 15:22]
  reg [31:0] _RAND_1;
  reg [1:0] shadowReg; // @[DoubleBufferFifo.scala 16:24]
  reg [31:0] _RAND_2;
  wire  _T = 2'h0 == stateReg; // @[Conditional.scala 37:30]
  wire  _T_1 = 2'h1 == stateReg; // @[Conditional.scala 37:30]
  wire  _T_2 = ~io_enq_valid; // @[DoubleBufferFifo.scala 25:30]
  wire  _T_3 = io_deq_ready & _T_2; // @[DoubleBufferFifo.scala 25:27]
  wire  _T_4 = io_deq_ready & io_enq_valid; // @[DoubleBufferFifo.scala 28:27]
  wire  _T_5 = ~io_deq_ready; // @[DoubleBufferFifo.scala 32:14]
  wire  _T_6 = _T_5 & io_enq_valid; // @[DoubleBufferFifo.scala 32:28]
  wire  _T_7 = 2'h2 == stateReg; // @[Conditional.scala 37:30]
  wire  _T_8 = stateReg == 2'h0; // @[DoubleBufferFifo.scala 44:31]
  wire  _T_9 = stateReg == 2'h1; // @[DoubleBufferFifo.scala 44:53]
  wire  _T_12 = stateReg == 2'h2; // @[DoubleBufferFifo.scala 45:51]
  assign io_enq_ready = _T_8 | _T_9; // @[DoubleBufferFifo.scala 44:18]
  assign io_deq_valid = _T_9 | _T_12; // @[DoubleBufferFifo.scala 45:18]
  assign io_deq_bits = dataReg; // @[DoubleBufferFifo.scala 46:17]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
  integer initvar;
`endif
`ifndef SYNTHESIS
initial begin
  `ifdef RANDOMIZE
    `ifdef INIT_RANDOM
      `INIT_RANDOM
    `endif
    `ifndef VERILATOR
      `ifdef RANDOMIZE_DELAY
        #`RANDOMIZE_DELAY begin end
      `else
        #0.002 begin end
      `endif
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{`RANDOM}};
  stateReg = _RAND_0[1:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_1 = {1{`RANDOM}};
  dataReg = _RAND_1[1:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_2 = {1{`RANDOM}};
  shadowReg = _RAND_2[1:0];
  `endif // RANDOMIZE_REG_INIT
  `endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
  always @(posedge clock) begin
    if (reset) begin
      stateReg <= 2'h0;
    end else if (_T) begin
      if (io_enq_valid) begin
        stateReg <= 2'h1;
      end
    end else if (_T_1) begin
      if (_T_6) begin
        stateReg <= 2'h2;
      end else if (_T_4) begin
        stateReg <= 2'h1;
      end else if (_T_3) begin
        stateReg <= 2'h0;
      end
    end else if (_T_7) begin
      if (io_deq_ready) begin
        stateReg <= 2'h1;
      end
    end
    if (_T) begin
      if (io_enq_valid) begin
        dataReg <= io_enq_bits;
      end
    end else if (!(_T_1)) begin
      if (_T_7) begin
        if (io_deq_ready) begin
          dataReg <= shadowReg;
        end
      end
    end
    if (!(_T)) begin
      if (_T_1) begin
        if (_T_6) begin
          shadowReg <= io_enq_bits;
        end else if (_T_4) begin
          shadowReg <= io_enq_bits;
        end
      end
    end
  end
endmodule
module DoubleBufferFifo(
  input        clock,
  input        reset,
  output       io_enq_ready,
  input        io_enq_valid,
  input  [1:0] io_enq_bits,
  input        io_deq_ready,
  output       io_deq_valid,
  output [1:0] io_deq_bits
);
  wire  DoubleBuffer_clock; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_reset; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_io_enq_ready; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_io_enq_valid; // @[DoubleBufferFifo.scala 49:58]
  wire [1:0] DoubleBuffer_io_enq_bits; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_io_deq_ready; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_io_deq_valid; // @[DoubleBufferFifo.scala 49:58]
  wire [1:0] DoubleBuffer_io_deq_bits; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_1_clock; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_1_reset; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_1_io_enq_ready; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_1_io_enq_valid; // @[DoubleBufferFifo.scala 49:58]
  wire [1:0] DoubleBuffer_1_io_enq_bits; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_1_io_deq_ready; // @[DoubleBufferFifo.scala 49:58]
  wire  DoubleBuffer_1_io_deq_valid; // @[DoubleBufferFifo.scala 49:58]
  wire [1:0] DoubleBuffer_1_io_deq_bits; // @[DoubleBufferFifo.scala 49:58]
  DoubleBuffer DoubleBuffer ( // @[DoubleBufferFifo.scala 49:58]
    .clock(DoubleBuffer_clock),
    .reset(DoubleBuffer_reset),
    .io_enq_ready(DoubleBuffer_io_enq_ready),
    .io_enq_valid(DoubleBuffer_io_enq_valid),
    .io_enq_bits(DoubleBuffer_io_enq_bits),
    .io_deq_ready(DoubleBuffer_io_deq_ready),
    .io_deq_valid(DoubleBuffer_io_deq_valid),
    .io_deq_bits(DoubleBuffer_io_deq_bits)
  );
  DoubleBuffer DoubleBuffer_1 ( // @[DoubleBufferFifo.scala 49:58]
    .clock(DoubleBuffer_1_clock),
    .reset(DoubleBuffer_1_reset),
    .io_enq_ready(DoubleBuffer_1_io_enq_ready),
    .io_enq_valid(DoubleBuffer_1_io_enq_valid),
    .io_enq_bits(DoubleBuffer_1_io_enq_bits),
    .io_deq_ready(DoubleBuffer_1_io_deq_ready),
    .io_deq_valid(DoubleBuffer_1_io_deq_valid),
    .io_deq_bits(DoubleBuffer_1_io_deq_bits)
  );
  assign io_enq_ready = DoubleBuffer_io_enq_ready; // @[DoubleBufferFifo.scala 63:10]
  assign io_deq_valid = DoubleBuffer_1_io_deq_valid; // @[DoubleBufferFifo.scala 68:10]
  assign io_deq_bits = DoubleBuffer_1_io_deq_bits; // @[DoubleBufferFifo.scala 68:10]
  assign DoubleBuffer_clock = clock;
  assign DoubleBuffer_reset = reset;
  assign DoubleBuffer_io_enq_valid = io_enq_valid; // @[DoubleBufferFifo.scala 63:10]
  assign DoubleBuffer_io_enq_bits = io_enq_bits; // @[DoubleBufferFifo.scala 63:10]
  assign DoubleBuffer_io_deq_ready = DoubleBuffer_1_io_enq_ready; // @[DoubleBufferFifo.scala 57:25]
  assign DoubleBuffer_1_clock = clock;
  assign DoubleBuffer_1_reset = reset;
  assign DoubleBuffer_1_io_enq_valid = DoubleBuffer_io_deq_valid; // @[DoubleBufferFifo.scala 57:25]
  assign DoubleBuffer_1_io_enq_bits = DoubleBuffer_io_deq_bits; // @[DoubleBufferFifo.scala 57:25]
  assign DoubleBuffer_1_io_deq_ready = io_deq_ready; // @[DoubleBufferFifo.scala 68:10]
endmodule
回复

使用道具 举报

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

本版积分规则



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

GMT+8, 2024-5-3 06:37 , Processed in 0.014604 second(s), 17 queries .

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

Copyright © 2018-2021, risc-v open source

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