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状态时发出数据有效指示
}
生成的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]