blob: aded8ce41f9324d9eb072da9280350c4012fb1a5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package vta.shell
import chisel3._
import chisel3.util._
import vta.util.config._
import vta.util.genericbundle._
import vta.interface.axi._
/** VTA Memory Engine (VME).
*
* This unit multiplexes the memory controller interface for the Core. Currently,
* it supports single-writer and multiple-reader mode and it is also based on AXI.
*/
class VMESimple(implicit p: Parameters) extends Module {
val io = IO(new Bundle {
val mem = new AXIMaster(p(ShellKey).memParams)
val vme = new VMEClient
})
val nReadClients = p(ShellKey).vmeParams.nReadClients
val rd_arb = Module(new Arbiter(new VMECmd, nReadClients))
val rd_arb_chosen = RegEnable(rd_arb.io.chosen, rd_arb.io.out.fire)
for (i <- 0 until nReadClients) { rd_arb.io.in(i) <> io.vme.rd(i).cmd }
val sReadIdle :: sReadAddr :: sReadData :: Nil = Enum(3)
val rstate = RegInit(sReadIdle)
switch(rstate) {
is(sReadIdle) {
when(rd_arb.io.out.valid) {
rstate := sReadAddr
}
}
is(sReadAddr) {
when(io.mem.ar.ready) {
rstate := sReadData
}
}
is(sReadData) {
when(io.mem.r.fire && io.mem.r.bits.last) {
rstate := sReadIdle
}
}
}
val sWriteIdle :: sWriteAddr :: sWriteData :: sWriteResp :: Nil = Enum(4)
val wstate = RegInit(sWriteIdle)
val addrBits = p(ShellKey).memParams.addrBits
val lenBits = p(ShellKey).memParams.lenBits
val wr_cnt = RegInit(0.U(lenBits.W))
when(wstate === sWriteIdle) {
wr_cnt := 0.U
}.elsewhen(io.mem.w.fire) {
wr_cnt := wr_cnt + 1.U
}
switch(wstate) {
is(sWriteIdle) {
when(io.vme.wr(0).cmd.valid) {
wstate := sWriteAddr
}
}
is(sWriteAddr) {
when(io.mem.aw.ready) {
wstate := sWriteData
}
}
is(sWriteData) {
when(
io.vme
.wr(0)
.data
.valid && io.mem.w.ready && wr_cnt === io.vme.wr(0).cmd.bits.len) {
wstate := sWriteResp
}
}
is(sWriteResp) {
when(io.mem.b.valid) {
wstate := sWriteIdle
}
}
}
// registers storing read/write cmds
val rd_len = RegInit(0.U(lenBits.W))
val wr_len = RegInit(0.U(lenBits.W))
val rd_addr = RegInit(0.U(addrBits.W))
val wr_addr = RegInit(0.U(addrBits.W))
when(rd_arb.io.out.fire) {
rd_len := rd_arb.io.out.bits.len
rd_addr := rd_arb.io.out.bits.addr
}
when(io.vme.wr(0).cmd.fire) {
wr_len := io.vme.wr(0).cmd.bits.len
wr_addr := io.vme.wr(0).cmd.bits.addr
}
// rd arb
rd_arb.io.out.ready := rstate === sReadIdle
val localTag = Reg(Vec(nReadClients, UInt(p(ShellKey).vmeParams.clientTagBitWidth.W)))
// vme
for (i <- 0 until nReadClients) {
io.vme.rd(i).data.valid := rd_arb_chosen === i.asUInt & io.mem.r.valid
io.vme.rd(i).data.bits.data := io.mem.r.bits.data
io.vme.rd(i).data.bits.last := io.mem.r.bits.last
io.vme.rd(i).data.bits.tag := localTag(i)
when (io.vme.rd(i).cmd.fire) {
localTag(i) := io.vme.rd(i).cmd.bits.tag
}
}
io.vme.wr(0).cmd.ready := wstate === sWriteIdle
io.vme.wr(0).ack := io.mem.b.fire
io.vme.wr(0).data.ready := wstate === sWriteData & io.mem.w.ready
// mem
io.mem.aw.valid := wstate === sWriteAddr
io.mem.aw.bits.addr := wr_addr
io.mem.aw.bits.len := wr_len
io.mem.w.valid := wstate === sWriteData & io.vme.wr(0).data.valid
io.mem.w.bits.data := io.vme.wr(0).data.bits.data
io.mem.w.bits.last := wr_cnt === io.vme.wr(0).cmd.bits.len
io.mem.w.bits.strb := Fill(p(ShellKey).memParams.strbBits, true.B)
io.mem.b.ready := wstate === sWriteResp
io.mem.ar.valid := rstate === sReadAddr
io.mem.ar.bits.addr := rd_addr
io.mem.ar.bits.len := rd_len
io.mem.ar.bits.id := 0.U
io.mem.r.ready := rstate === sReadData & io.vme.rd(rd_arb_chosen).data.ready
// AXI constants - statically defined
io.mem.setConst()
}