joe 发表于 2021-9-6 17:03:20

DoubleBufferFifo

import chisel3._
import chisel3.util._
class FifoIO(private val gen:T) extends Bundle {
val enq = Flipped(new DecoupledIO(gen))   //DecoupledIO-->>ReadyValidIO-->>Bundle是带有valid和ready的复杂信号Flipped则将bits,ready和valid信号切换方向
val deq = new DecoupledIO(gen) //deq是正常的bits,ready,valid方向
}
abstract class Fifo(gen:T,depth:Int) extends Module {//带有valid和ready的FIFO,并且有二个“group”,一个是enq,一个是deq
val io = IO(new FifoIO(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(gen:T,depth:Int) extends Fifo(gen,depth) {
private class DoubleBuffer(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
}


joe 发表于 2021-9-6 17:04:09

生成的verilog文件内容如下:
module DoubleBuffer(
input      clock,
input      reset,
output       io_enq_ready,
input      io_enq_valid,
input io_enq_bits,
input      io_deq_ready,
output       io_deq_valid,
output io_deq_bits
);
reg stateReg; // @
reg _RAND_0;
reg dataReg; // @
reg _RAND_1;
reg shadowReg; // @
reg _RAND_2;
wire_T = 2'h0 == stateReg; // @
wire_T_1 = 2'h1 == stateReg; // @
wire_T_2 = ~io_enq_valid; // @
wire_T_3 = io_deq_ready & _T_2; // @
wire_T_4 = io_deq_ready & io_enq_valid; // @
wire_T_5 = ~io_deq_ready; // @
wire_T_6 = _T_5 & io_enq_valid; // @
wire_T_7 = 2'h2 == stateReg; // @
wire_T_8 = stateReg == 2'h0; // @
wire_T_9 = stateReg == 2'h1; // @
wire_T_12 = stateReg == 2'h2; // @
assign io_enq_ready = _T_8 | _T_9; // @
assign io_deq_valid = _T_9 | _T_12; // @
assign io_deq_bits = dataReg; // @
`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;
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_1 = {1{`RANDOM}};
dataReg = _RAND_1;
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_2 = {1{`RANDOM}};
shadowReg = _RAND_2;
`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 io_enq_bits,
input      io_deq_ready,
output       io_deq_valid,
output io_deq_bits
);
wireDoubleBuffer_clock; // @
wireDoubleBuffer_reset; // @
wireDoubleBuffer_io_enq_ready; // @
wireDoubleBuffer_io_enq_valid; // @
wire DoubleBuffer_io_enq_bits; // @
wireDoubleBuffer_io_deq_ready; // @
wireDoubleBuffer_io_deq_valid; // @
wire DoubleBuffer_io_deq_bits; // @
wireDoubleBuffer_1_clock; // @
wireDoubleBuffer_1_reset; // @
wireDoubleBuffer_1_io_enq_ready; // @
wireDoubleBuffer_1_io_enq_valid; // @
wire DoubleBuffer_1_io_enq_bits; // @
wireDoubleBuffer_1_io_deq_ready; // @
wireDoubleBuffer_1_io_deq_valid; // @
wire DoubleBuffer_1_io_deq_bits; // @
DoubleBuffer DoubleBuffer ( // @
    .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 ( // @
    .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; // @
assign io_deq_valid = DoubleBuffer_1_io_deq_valid; // @
assign io_deq_bits = DoubleBuffer_1_io_deq_bits; // @
assign DoubleBuffer_clock = clock;
assign DoubleBuffer_reset = reset;
assign DoubleBuffer_io_enq_valid = io_enq_valid; // @
assign DoubleBuffer_io_enq_bits = io_enq_bits; // @
assign DoubleBuffer_io_deq_ready = DoubleBuffer_1_io_enq_ready; // @
assign DoubleBuffer_1_clock = clock;
assign DoubleBuffer_1_reset = reset;
assign DoubleBuffer_1_io_enq_valid = DoubleBuffer_io_deq_valid; // @
assign DoubleBuffer_1_io_enq_bits = DoubleBuffer_io_deq_bits; // @
assign DoubleBuffer_1_io_deq_ready = io_deq_ready; // @
endmodule
页: [1]
查看完整版本: DoubleBufferFifo