joe 发表于 2021-9-6 09:24:51

MemFifo

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._
/**
* FIFO with memory and read and write pointers.
* Extra shadow register to handle the one cycle latency of the synchronous memory.
*/
class MemFifo(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状态时发出数据有效指示
}


joe 发表于 2021-9-6 09:28:05

生成的verilog文件内容如下:
module MemFifo(
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 mem ; // @
wire mem_data_data; // @
wire mem_data_addr; // @
wire mem__T_8_data; // @
wire mem__T_8_addr; // @
wiremem__T_8_mask; // @
wiremem__T_8_en; // @
regmem_data_en_pipe_0;
reg mem_data_addr_pipe_0;
regreadPtr; // @
wire _GEN_45 = {{1'd0}, readPtr}; // @
wire_T = _GEN_45 == 2'h2; // @
wire_T_2 = readPtr + 1'h1; // @
wirenextRead = _T ? 1'h0 : _T_2; // @
reg stateReg; // @
wire_T_10 = 2'h0 == stateReg; // @
regemptyReg; // @
wire_T_11 = ~emptyReg; // @
wire_T_13 = 2'h1 == stateReg; // @
wire_GEN_21 = io_deq_ready & _T_11; // @
wire_T_16 = 2'h2 == stateReg; // @
wire_GEN_34 = _T_16 & _GEN_21; // @
wire_GEN_38 = _T_13 ? _GEN_21 : _GEN_34; // @
wireincrRead = _T_10 ? _T_11 : _GEN_38; // @
regwritePtr; // @
wire _GEN_46 = {{1'd0}, writePtr}; // @
wire_T_3 = _GEN_46 == 2'h2; // @
wire_T_5 = writePtr + 1'h1; // @
wirenextWrite = _T_3 ? 1'h0 : _T_5; // @
regfullReg; // @
wire_T_6 = ~fullReg; // @
wireincrWrite = io_enq_valid & _T_6; // @
reg shadowReg; // @
wire_T_9 = nextWrite == readPtr; // @
wire_GEN_8 = incrWrite ? 1'h0 : emptyReg; // @
wire_GEN_9 = incrWrite ? _T_9 : fullReg; // @
wire_T_12 = nextRead == writePtr; // @
wire_GEN_12 = _T_11 ? _T_12 : _GEN_8; // @
wire_GEN_20 = io_deq_ready ? _GEN_12 : _GEN_8; // @
wire_GEN_33 = _T_16 ? _GEN_20 : _GEN_8; // @
wire_GEN_37 = _T_13 ? _GEN_20 : _GEN_33; // @
wire_GEN_42 = _T_10 ? _GEN_12 : _GEN_37; // @
wire_T_19 = stateReg == 2'h1; // @
wire_T_23 = stateReg == 2'h2; // @
assign mem_data_addr = mem_data_addr_pipe_0;
`ifndef RANDOMIZE_GARBAGE_ASSIGN
assign mem_data_data = mem; // @
`else
assign mem_data_data = mem_data_addr >= 2'h3 ? _RAND_1 : mem; // @
`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; // @
assign io_deq_valid = _T_19 | _T_23; // @
assign io_deq_bits = _T_19 ? mem_data_data : shadowReg; // @

always @(posedge clock) begin
    if(mem__T_8_en & mem__T_8_mask) begin
      mem <= mem__T_8_data; // @
    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
页: [1]
查看完整版本: MemFifo