与xilin或alter的fifo相连的chisel BubbleFIFO源码及注释
import chisel3._import chisel3.util._
/**
* 本代码可以与xilinx或alter的FPGA FIFO结合使用
* Alter's FIFO component:
* data - data in, q - data out, wrreq and rdreq
* state: full and empty
*
* Xilinx's FIFO component:
* din and dout, wr_en, rd_en
* state: full and empty
*/
class WriterIO(size:Int) extends Bundle {//定义写FIFO的端口Bundle,有三个信号此WriterIO就是用于接收Master给本模块发数据
val write = Input(Bool()) //写指示
val full = Output(Bool()) //写满
val din = Input(UInt(size.W)) //写的数据size是指数据位宽
}
class ReaderIO(size:Int) extends Bundle { //定义读FIFO的端口Bundle,也是三个信号 此ReaderIO用于给下游Slave发数据
val read = Input(Bool()) //读指示
val empty = Output(Bool()) //空标志
val dout = Output(UInt(size.W))
}
class FifoRegister(size:Int) extends Module {
val io = IO(new Bundle {
val enq = new WriterIO(size) //因为enq用来给本模块写入数据,所以enq的对面相当于是Master
val deq = new ReaderIO(size)
})
val empty :: full :: Nil = Enum(2)
val stateReg = RegInit(empty)
val dataReg = RegInit(0.U(size.W))
when(stateReg === empty) { //如果空
when(io.enq.write) { //指示写
stateReg := full //进入满状态 ?????怎么一次写就进入满状态??? 只要deq的对方即slave将read指示始终发出则不会满
dataReg := io.enq.din
}
}.elsewhen(stateReg === full) {
when(io.deq.read) { //收到读指示
stateReg := empty //进入empty状态
dataReg := dataReg//0.U just to better see empty slots in the waveform
}
}.otherwise{
// There should not be an otherwise state
}
io.enq.full := (stateReg === full)
io.deq.empty := (stateReg === empty)
io.deq.dout := dataReg
}
class BubbleFifoWithXILINXALTER(size:Int,depth:Int) extends Module { //主模块
val io = IO(new Bundle { //主模块也需要有enq和deq接口,用于和上下游模块通信
val enq = new WriterIO(size)
val deq = new ReaderIO(size)
})
assert(depth>=2,"depth>=2")
val buffers = Array.fill(depth)(Module(new FifoRegister(size))) //缓冲区,深度为depth,元素类型为FifoRegister,实质是位宽为size的数据
for(i <- 0 until depth-1) {
buffers(i+1).io.enq.din := buffers(i).io.deq.dout //缓冲区中下一个元素的输入的数据来自前一个元素的输出 线成一个链条
buffers(i+1).io.enq.write := ~buffers(i).io.deq.empty //前一个元素不空则下一个元素就可以启动写指示
buffers(i).io.deq.read := ~buffers(i+1).io.enq.full //下一个元素的enq不满则前一个元素的读指示启动
}
//父子级连,只能是input连input,output连output,生成的verilog伪代码如下:
//buffers(0).io.enq.write := io.enq.write
//buffers(0).io.enq.din := io.enq.din
//io.enq.full := buffers(0).io.enq.full
io.enq <> buffers(0).io.enq
//父子级连 生成的verilog伪代码如下
//buffers(depth-1).io.deq.read := io.deq.read
//io.deq.empty := buffers(depth-1).io.deq.empty
//io.deq.dout := buffers(depth-1).io.deq.dout
io.deq <> buffers(depth-1).io.deq
}
可产生波形测试文件的iotesters测试代码:
import chisel3._
import chisel3.iotesters.PeekPokeTester
/**
* Test the design.
*/
class FifoTester(dut: BubbleFifo) extends PeekPokeTester(dut) {
// some defaults for all signals
poke(dut.io.enq.din, 0xab)
poke(dut.io.enq.write, 0)
poke(dut.io.deq.read, 0)
step(1)
var full = peek(dut.io.enq.full)
var empty = peek(dut.io.deq.empty)
// write into the buffer
poke(dut.io.enq.din, 0x12)
poke(dut.io.enq.write, 1)
step(1)
full = peek(dut.io.enq.full)
poke(dut.io.enq.din, 0xff)
poke(dut.io.enq.write, 0)
step(1)
full = peek(dut.io.enq.full)
step(3) // see the bubbling of the first element
// Fill the whole buffer with a check for full condition
// Only every second cycle a write can happen.
for (i <- 0 until 7) {
full = peek(dut.io.enq.full)
poke(dut.io.enq.din, 0x80 + i)
if (full == 0) {
poke(dut.io.enq.write, 1)
} else {
poke(dut.io.enq.write, 0)
}
step(1)
}
// Now we know it is full, so do a single read and watch
// how this empty slot bubble up to the FIFO input.
poke(dut.io.deq.read, 1)
step(1)
poke(dut.io.deq.read, 0)
step(6)
// New read out the whole buffer.
// Also watch that maximum read out is every second clock cycle
for (i <- 0 until 7) {
empty = peek(dut.io.deq.empty)
if (empty == 0) {
poke(dut.io.deq.read, 1)
} else {
poke(dut.io.deq.read, 0)
}
step(1)
}
// Now write and read at maximum speed for some time
for (i <- 1 until 16) {
full = peek(dut.io.enq.full)
poke(dut.io.enq.din, i)
if (full == 0) {
poke(dut.io.enq.write, 1)
} else {
poke(dut.io.enq.write, 0)
}
empty = peek(dut.io.deq.empty)
if (empty == 0) {
poke(dut.io.deq.read, 1)
} else {
poke(dut.io.deq.read, 0)
}
step(1)
}
}
object FifoTester extends App {
iotesters.Driver.execute(Array("--target-dir", "generated", "--generate-vcd-output", "on"), () => new BubbleFifoWithXILINXALTER(8, 4)) {
// iotesters.Driver.execute(Array("--target-dir", "generated", "--fint-write-vcd", "--wave-form-file-name", "generated/BubbleFifoWithXILINXALTER.vcd"), () => new BubbleFifoWithXILINXALTER(8, 4)) {
c => new FifoTester(c)
}
}
页:
[1]