未验证 提交 8a03da04 编写于 作者: Z Zihao Yu 提交者: GitHub

Merge pull request #7 from sashimi-yzh/axi

Axi
......@@ -16,6 +16,7 @@ libdevice:
$(TOP_V): $(SCALA_FILE)
mkdir -p $(@D)
sbt 'runMain top.$(TOP) -td $(@D) --output-file $@'
sed -i -e 's/_\(aw\|ar\|w\|r\|b\)_\(\|bits_\)/_\1/g' $@
verilog: $(TOP_V)
......
module addr_mapper (
`axi_slave_if(s_axi, 32, 1),
`axi_master_if(m_axi, 32, 1)
`axi_slave_if(s_axi, 32, 8),
`axi_master_if(m_axi, 32, 8)
);
assign m_axi_awaddr = {4'b0001, s_axi_awaddr[27:0]};
......
......@@ -25,9 +25,9 @@ module system_top (
inout FIXED_IO_ps_srstb
);
`axi_wire(AXI_MEM_MAPPED, 32, 1);
`axi_wire(AXI_MEM, 32, 1);
`axi_wire(AXI_MMIO, 32, 1);
`axi_wire(AXI_MEM_MAPPED, 32, 8);
`axi_wire(AXI_MEM, 32, 8);
`axi_wire(AXI_MMIO, 32, 8);
wire coreclk;
wire corerstn;
......
......@@ -131,7 +131,6 @@ set bCheckIPsPassed 1
set bCheckIPs 1
if { $bCheckIPs == 1 } {
set list_check_ips "\
xilinx.com:ip:ahblite_axi_bridge:3.0\
xilinx.com:ip:axi_clock_converter:2.1\
xilinx.com:ip:axi_crossbar:2.1\
xilinx.com:ip:util_vector_logic:2.0\
......@@ -272,19 +271,19 @@ proc create_root_design { parentCell } {
return 1
}
# Create instance: ahblite_axi_bridge_0, and set properties
set ahblite_axi_bridge_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:ahblite_axi_bridge:3.0 ahblite_axi_bridge_0 ]
set_property -dict [ list \
CONFIG.C_M_AXI_NON_SECURE {0} \
CONFIG.C_M_AXI_THREAD_ID_WIDTH {0} \
] $ahblite_axi_bridge_0
CONFIG.SUPPORTS_NARROW_BURST {1} \
CONFIG.NUM_READ_OUTSTANDING {2} \
CONFIG.NUM_WRITE_OUTSTANDING {2} \
CONFIG.MAX_BURST_LENGTH {256} \
] [get_bd_intf_pins /NOOPFPGA_0/io_dmem]
# Create instance: ahblite_axi_bridge_1, and set properties
set ahblite_axi_bridge_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:ahblite_axi_bridge:3.0 ahblite_axi_bridge_1 ]
set_property -dict [ list \
CONFIG.C_M_AXI_NON_SECURE {0} \
CONFIG.C_M_AXI_THREAD_ID_WIDTH {0} \
] $ahblite_axi_bridge_1
CONFIG.SUPPORTS_NARROW_BURST {1} \
CONFIG.NUM_READ_OUTSTANDING {2} \
CONFIG.NUM_WRITE_OUTSTANDING {2} \
CONFIG.MAX_BURST_LENGTH {256} \
] [get_bd_intf_pins /NOOPFPGA_0/io_imem]
# Create instance: axi_clock_converter_0, and set properties
set axi_clock_converter_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_clock_converter:2.1 axi_clock_converter_0 ]
......@@ -292,20 +291,12 @@ proc create_root_design { parentCell } {
# Create instance: axi_crossbar_0, and set properties
set axi_crossbar_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_crossbar:2.1 axi_crossbar_0 ]
set_property -dict [ list \
CONFIG.M00_A00_ADDR_WIDTH {32} \
CONFIG.M00_A00_BASE_ADDR {0x0000000000000000} \
CONFIG.NUM_MI {1} \
CONFIG.NUM_SI {2} \
] $axi_crossbar_0
# Create instance: axi_crossbar_1, and set properties
set axi_crossbar_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_crossbar:2.1 axi_crossbar_1 ]
set_property -dict [ list \
CONFIG.M00_A00_ADDR_WIDTH {31} \
CONFIG.M00_A00_BASE_ADDR {0x0000000080000000} \
CONFIG.M01_A00_ADDR_WIDTH {30} \
CONFIG.M01_A00_BASE_ADDR {0x0000000040000000} \
] $axi_crossbar_1
# Create instance: util_vector_logic_0, and set properties
set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ]
......@@ -316,23 +307,29 @@ proc create_root_design { parentCell } {
] $util_vector_logic_0
# Create interface connections
connect_bd_intf_net -intf_net NOOPFPGA_0_io_dmem [get_bd_intf_pins NOOPFPGA_0/io_dmem] [get_bd_intf_pins ahblite_axi_bridge_0/AHB_INTERFACE]
connect_bd_intf_net -intf_net NOOPFPGA_0_io_imem [get_bd_intf_pins NOOPFPGA_0/io_imem] [get_bd_intf_pins ahblite_axi_bridge_1/AHB_INTERFACE]
connect_bd_intf_net -intf_net ahblite_axi_bridge_0_M_AXI [get_bd_intf_pins ahblite_axi_bridge_0/M_AXI] [get_bd_intf_pins axi_crossbar_0/S00_AXI]
connect_bd_intf_net -intf_net ahblite_axi_bridge_1_M_AXI [get_bd_intf_pins ahblite_axi_bridge_1/M_AXI] [get_bd_intf_pins axi_crossbar_0/S01_AXI]
connect_bd_intf_net -intf_net NOOPFPGA_0_io_dmem [get_bd_intf_pins NOOPFPGA_0/io_dmem] [get_bd_intf_pins axi_crossbar_0/S00_AXI]
connect_bd_intf_net -intf_net NOOPFPGA_0_io_imem [get_bd_intf_pins NOOPFPGA_0/io_imem] [get_bd_intf_pins axi_crossbar_0/S01_AXI]
connect_bd_intf_net -intf_net axi_clock_converter_0_M_AXI [get_bd_intf_pins axi_clock_converter_0/M_AXI] [get_bd_intf_pins axi_crossbar_1/S00_AXI]
connect_bd_intf_net -intf_net axi_crossbar_0_M00_AXI [get_bd_intf_pins axi_clock_converter_0/S_AXI] [get_bd_intf_pins axi_crossbar_0/M00_AXI]
connect_bd_intf_net -intf_net axi_crossbar_1_M00_AXI [get_bd_intf_ports AXI_MEM] [get_bd_intf_pins axi_crossbar_1/M00_AXI]
connect_bd_intf_net -intf_net axi_crossbar_1_M01_AXI [get_bd_intf_ports AXI_MMIO] [get_bd_intf_pins axi_crossbar_1/M01_AXI]
# Create port connections
connect_bd_net -net coreclk_1 [get_bd_ports coreclk] [get_bd_pins NOOPFPGA_0/clock] [get_bd_pins ahblite_axi_bridge_0/s_ahb_hclk] [get_bd_pins ahblite_axi_bridge_1/s_ahb_hclk] [get_bd_pins axi_clock_converter_0/s_axi_aclk] [get_bd_pins axi_crossbar_0/aclk]
connect_bd_net -net coreclk_1 [get_bd_ports coreclk] [get_bd_pins NOOPFPGA_0/clock] [get_bd_pins axi_clock_converter_0/s_axi_aclk] [get_bd_pins axi_crossbar_0/aclk]
connect_bd_net -net uncoreclk_1 [get_bd_ports uncoreclk] [get_bd_pins axi_clock_converter_0/m_axi_aclk] [get_bd_pins axi_crossbar_1/aclk]
connect_bd_net -net uncorerstn_1 [get_bd_ports corerstn] [get_bd_pins ahblite_axi_bridge_0/s_ahb_hresetn] [get_bd_pins ahblite_axi_bridge_1/s_ahb_hresetn] [get_bd_pins axi_clock_converter_0/s_axi_aresetn] [get_bd_pins axi_crossbar_0/aresetn] [get_bd_pins util_vector_logic_0/Op1]
connect_bd_net -net uncorerstn_1 [get_bd_ports corerstn] [get_bd_pins axi_clock_converter_0/s_axi_aresetn] [get_bd_pins axi_crossbar_0/aresetn] [get_bd_pins util_vector_logic_0/Op1]
connect_bd_net -net uncorerstn_2 [get_bd_ports uncorerstn] [get_bd_pins axi_clock_converter_0/m_axi_aresetn] [get_bd_pins axi_crossbar_1/aresetn]
connect_bd_net -net util_vector_logic_0_Res [get_bd_pins NOOPFPGA_0/reset] [get_bd_pins util_vector_logic_0/Res]
# Create address segments
create_bd_addr_seg -range 0x80000000 -offset 0x80000000 [get_bd_addr_spaces NOOPFPGA_0/io_dmem] [get_bd_addr_segs AXI_MEM/Reg] SEG_AXI_MEM_Reg
create_bd_addr_seg -range 0x80000000 -offset 0x80000000 [get_bd_addr_spaces NOOPFPGA_0/io_imem] [get_bd_addr_segs AXI_MEM/Reg] SEG_AXI_MEM_Reg
create_bd_addr_seg -range 0x40000000 -offset 0x40000000 [get_bd_addr_spaces NOOPFPGA_0/io_dmem] [get_bd_addr_segs AXI_MMIO/Reg] SEG_AXI_MMIO_Reg
# Exclude Address Segments
create_bd_addr_seg -range 0x00010000 -offset 0x44A10000 [get_bd_addr_spaces NOOPFPGA_0/io_imem] [get_bd_addr_segs AXI_MMIO/Reg] SEG_AXI_MMIO_Reg
exclude_bd_addr_seg [get_bd_addr_segs NOOPFPGA_0/io_imem/SEG_AXI_MMIO_Reg]
# Restore current instance
......
......@@ -3,8 +3,7 @@ package memory
import chisel3._
import chisel3.util._
object AHBParameters
{
object AHBParameters {
// These are all fixed by the AHB standard:
val transBits = 2
val burstBits = 3
......
// See LICENSE.SiFive for license details.
package memory
import chisel3._
import chisel3.util._
object AXI4Parameters {
// These are all fixed by the AXI4 standard:
val lenBits = 8
val sizeBits = 3
val burstBits = 2
val cacheBits = 4
val protBits = 3
val qosBits = 4
val respBits = 2
// These are not fixed:
val idBits = 1
val addrBits = 32
val dataBits = 32
val userBits = 1
def CACHE_RALLOCATE = 8.U(cacheBits.W)
def CACHE_WALLOCATE = 4.U(cacheBits.W)
def CACHE_MODIFIABLE = 2.U(cacheBits.W)
def CACHE_BUFFERABLE = 1.U(cacheBits.W)
def PROT_PRIVILEDGED = 1.U(protBits.W)
def PROT_INSECURE = 2.U(protBits.W)
def PROT_INSTRUCTION = 4.U(protBits.W)
def BURST_FIXED = 0.U(burstBits.W)
def BURST_INCR = 1.U(burstBits.W)
def BURST_WRAP = 2.U(burstBits.W)
def RESP_OKAY = 0.U(respBits.W)
def RESP_EXOKAY = 1.U(respBits.W)
def RESP_SLVERR = 2.U(respBits.W)
def RESP_DECERR = 3.U(respBits.W)
}
abstract class AXI4BundleA extends Bundle {
val id = Output(UInt(AXI4Parameters.idBits.W))
val addr = Output(UInt(AXI4Parameters.addrBits.W))
val len = Output(UInt(AXI4Parameters.lenBits.W)) // number of beats - 1
val size = Output(UInt(AXI4Parameters.sizeBits.W)) // bytes in beat = 2^size
val burst = Output(UInt(AXI4Parameters.burstBits.W))
val lock = Output(Bool())
val cache = Output(UInt(AXI4Parameters.cacheBits.W))
val prot = Output(UInt(AXI4Parameters.protBits.W))
val qos = Output(UInt(AXI4Parameters.qosBits.W)) // 0=no QoS, bigger = higher priority
val user = Output(UInt(AXI4Parameters.userBits.W))
// val region = UInt(width = 4) // optional
}
class AXI4BundleAW extends AXI4BundleA
class AXI4BundleAR extends AXI4BundleA
class AXI4BundleW extends Bundle {
// id ... removed in AXI4
val data = Output(UInt(AXI4Parameters.dataBits.W))
val strb = Output(UInt((AXI4Parameters.dataBits/8).W))
val last = Output(Bool())
}
class AXI4BundleB extends Bundle {
val id = Output(UInt(AXI4Parameters.idBits.W))
val resp = Output(UInt(AXI4Parameters.respBits.W))
val user = Output(UInt(AXI4Parameters.userBits.W))
}
class AXI4BundleR extends AXI4BundleB {
val data = Output(UInt(AXI4Parameters.dataBits.W))
val last = Output(Bool())
}
class AXI4 extends Bundle {
val aw = Decoupled(new AXI4BundleAW)
val w = Decoupled(new AXI4BundleW)
val b = Flipped(Decoupled(new AXI4BundleB))
val ar = Decoupled(new AXI4BundleAR)
val r = Flipped(Decoupled(new AXI4BundleR))
}
class MemIO2AXI4Converter extends Module {
val io = IO(new Bundle {
val in = Flipped(new MemIO)
val out = new AXI4
})
val mem = io.in
val axi = io.out
val ar = axi.ar.bits
val aw = axi.aw.bits
val w = axi.w.bits
val r = axi.r.bits
val b = axi.b.bits
ar.id := 0.U
ar.addr := mem.a.bits.addr
ar.len := 0.U // single beat
ar.size := mem.a.bits.size
ar.burst := AXI4Parameters.BURST_INCR
ar.lock := false.B
ar.cache := 0.U
ar.prot := AXI4Parameters.PROT_PRIVILEDGED
ar.qos := 0.U
ar.user := 0.U
aw := ar
w.data := mem.w.bits.data
w.strb := mem.w.bits.mask
w.last := true.B
mem.r.bits.data := r.data
val awAck = RegInit(false.B)
val wAck = RegInit(false.B)
val wSend = (axi.aw.fire() && axi.w.fire()) || (awAck && wAck)
when (wSend) {
awAck := false.B
wAck := false.B
}
.elsewhen (axi.aw.fire()) { awAck := true.B }
.elsewhen (axi. w.fire()) { wAck := true.B }
axi.ar.valid := mem.isRead()
axi.aw.valid := mem.isWrite() && !awAck
axi.w .valid := mem.isWrite() && !wAck
mem.a.ready := Mux(mem.w.valid, wSend, axi.ar.ready)
axi.r.ready := mem.r.ready
mem.r.valid := axi.r.valid
axi.b.ready := true.B
}
// See LICENSE.SiFive for license details.
package memory
import chisel3._
import chisel3.util._
import chisel3.util.experimental.loadMemoryFromFile
class AXI4RAM(memByte: Int, beatBytes: Int = 4, dataFile: String = "") extends Module {
val io = IO(new Bundle{
val in = Flipped(new AXI4)
})
val in = io.in
val mem = SeqMem(memByte, Vec(beatBytes, UInt(8.W)))
if (dataFile != "") loadMemoryFromFile(mem, dataFile)
val r_addr = in.ar.bits.addr >> log2Ceil(beatBytes)
val w_addr = in.aw.bits.addr >> log2Ceil(beatBytes)
val w_full = RegInit(false.B)
val w_id = Reg(UInt())
val w_user = Reg(UInt())
when (in. b.fire()) { w_full := false.B }
when (in.aw.fire()) { w_full := true.B }
when (in.aw.fire()) {
w_id := in.aw.bits.id
w_user := in.aw.bits.user
}
val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8*(i+1)-1, 8*i) }
when (in.aw.fire()) {
mem.write(w_addr, wdata, in.w.bits.strb.toBools)
}
in. b.valid := w_full
in.aw.ready := in. w.valid && (in.b.ready || !w_full)
in. w.ready := in.aw.valid && (in.b.ready || !w_full)
in.b.bits.id := w_id
in.b.bits.resp := AXI4Parameters.RESP_OKAY
in.b.bits.user := w_user
val r_full = RegInit(false.B)
val r_id = Reg(UInt())
val r_user = Reg(UInt())
when (in. r.fire()) { r_full := false.B }
when (in.ar.fire()) { r_full := true.B }
when (in.ar.fire()) {
r_id := in.ar.bits.id
r_user := in.ar.bits.user
}
def holdUnless[T <: Data](x: T, enable: Bool): T = Mux(enable, x, RegEnable(x, enable))
val ren = in.ar.fire()
val rdata = holdUnless(mem.read(r_addr, ren), RegNext(ren))
in. r.valid := r_full
in.ar.ready := in.r.ready || !r_full
in.r.bits.id := r_id
in.r.bits.resp := AXI4Parameters.RESP_OKAY
in.r.bits.data := Cat(rdata.reverse)
in.r.bits.user := r_user
in.r.bits.last := true.B
}
......@@ -21,9 +21,18 @@ class MemIO(val dataBits: Int = 32) extends Bundle {
val r = Flipped(Decoupled(new MemDataBundle(dataBits)))
val w = Valid(new MemMaskDataBundle(dataBits))
def isRead (): Bool = a.valid && !w.valid
def isWrite(): Bool = a.valid && w.valid
def toAHBLite(): AHBLiteIO = {
val mem2ahb = Module(new MemIO2AHBLiteConverter)
mem2ahb.io.in <> this
mem2ahb.io.out
}
def toAXI4(): AXI4 = {
val mem2axi = Module(new MemIO2AXI4Converter)
mem2axi.io.in <> this
mem2axi.io.out
}
}
// See LICENSE.SiFive for license details.
package memory
import chisel3._
import chisel3.util._
object LFSR64 {
def apply(increment: Bool = true.B): UInt = {
val wide = 64
val lfsr = Reg(UInt(wide.W)) // random initial value based on simulation seed
val xor = lfsr(0) ^ lfsr(1) ^ lfsr(3) ^ lfsr(4)
when (increment) {
lfsr := Mux(lfsr === 0.U, 1.U, Cat(xor, lfsr(wide-1,1)))
}
lfsr
}
}
// q is the probability to delay a request
class AXI4Delayer(q: Double) extends Module {
val io = IO(new Bundle{
val in = Flipped(new AXI4)
val out = new AXI4
})
require (0.0 <= q && q < 1)
def feed[T <: Data](sink: DecoupledIO[T], source: DecoupledIO[T]) {
// irrevocable requires that we not lower valid
val hold = RegInit(false.B)
when (sink.valid) { hold := true.B }
when (sink.fire()) { hold := false.B }
val allow = hold || ((q * 65535.0).toInt).U <= LFSR64(source.valid)(15, 0)
sink.valid := source.valid && allow
source.ready := sink.ready && allow
sink.bits := source.bits
}
feed(io.out.ar, io.in.ar)
feed(io.out.aw, io.in.aw)
feed(io.out.w, io.in.w )
feed(io.in.b, io.out.b)
feed(io.in.r, io.out.r)
}
......@@ -18,7 +18,7 @@ class DistributedMem(memByte: Int, dualPort: Boolean, delayCycles: Int = 0, data
val rwIdx = Index(io.rw.a.bits.addr)
val roIdx = Index(io.ro.a.bits.addr)
val wen = io.rw.a.valid && io.rw.w.valid
val wen = io.rw.isWrite()
val wdataVec = VecInit.tabulate(4) { i => io.rw.w.bits.data(8 * (i + 1) - 1, 8 * i) }
val wmask = VecInit.tabulate(4) { i => io.rw.w.bits.mask(i).toBool }
......
package top
import noop.NOOP
import memory.AHBLiteIO
import memory.AXI4
import chisel3._
class NOOPFPGA extends Module {
val io = IO(new Bundle{
val imem = new AHBLiteIO
val dmem = new AHBLiteIO
val imem = new AXI4
val dmem = new AXI4
})
val noop = Module(new NOOP)
io.imem <> noop.io.imem.toAHBLite()
io.dmem <> noop.io.dmem.toAHBLite()
io.imem <> noop.io.imem.toAXI4()
io.dmem <> noop.io.dmem.toAXI4()
noop.io.gmem := DontCare
noop.io.gpuStart := DontCare
......
......@@ -7,6 +7,7 @@ import chisel3.util._
import memory.DistributedMem
import memory.{AHBRAM, AHBParameters, MemIO2AHBLiteConverter}
import memory.{AXI4RAM, AXI4Parameters, MemIO2AXI4Converter, AXI4Delayer}
class NOOPSimTop(memInitFile: String = "") extends Module {
val io = IO(new Bundle{
......@@ -19,23 +20,25 @@ class NOOPSimTop(memInitFile: String = "") extends Module {
val noop = Module(new NOOP)
val mem = Module(new DistributedMem(memByte = 128 * 1024 * 1024, dualPort = true, dataFile = memInitFile))
val mem2ahb = Module(new MemIO2AHBLiteConverter)
val ahbmem = Module(new AHBRAM(memByte = 128 * 1024 * 1024, dataFile = memInitFile))
val mem2axi = Module(new MemIO2AXI4Converter)
val delay = Module(new AXI4Delayer(0))
val aximem = Module(new AXI4RAM(memByte = 128 * 1024 * 1024, dataFile = memInitFile))
val mmio = Module(new SimMMIO)
noop.io.imem <> mem.io.ro
mem2ahb.io.in <> noop.io.dmem
ahbmem.io.in <> mem2ahb.io.out
mem2axi.io.in <> noop.io.dmem
delay.io.in <> mem2axi.io.out
aximem.io.in <> delay.io.out
mem.io.rw := DontCare
io.trap := Cat(mmio.io.mmioTrap.cmd, mmio.io.mmioTrap.valid, noop.io.dmem.w.bits.mask,
noop.io.dmem.a.bits.addr, noop.io.dmem.w.bits.data, noop.io.trap)
noop.io.dmem.a.ready := Mux(mmio.io.mmioTrap.valid, mmio.io.rw.a.ready, mem2ahb.io.in.a.ready)
noop.io.dmem.r.bits.data := Mux(mmio.io.mmioTrap.valid, io.mmioRdata, mem2ahb.io.in.r.bits.data)
noop.io.dmem.r.valid := Mux(mmio.io.mmioTrap.valid, mmio.io.rw.r.valid, mem2ahb.io.in.r.valid)
mem2ahb.io.in.a.valid := Mux(mmio.io.mmioTrap.valid, false.B, noop.io.dmem.a.valid)
mem2ahb.io.in.w.valid := Mux(mmio.io.mmioTrap.valid, false.B, noop.io.dmem.w.valid)
noop.io.dmem.a.ready := Mux(mmio.io.mmioTrap.valid, mmio.io.rw.a.ready, mem2axi.io.in.a.ready)
noop.io.dmem.r.bits.data := Mux(mmio.io.mmioTrap.valid, io.mmioRdata, mem2axi.io.in.r.bits.data)
noop.io.dmem.r.valid := Mux(mmio.io.mmioTrap.valid, mmio.io.rw.r.valid, mem2axi.io.in.r.valid)
mem2axi.io.in.a.valid := Mux(mmio.io.mmioTrap.valid, false.B, noop.io.dmem.a.valid)
mem2axi.io.in.w.valid := Mux(mmio.io.mmioTrap.valid, false.B, noop.io.dmem.w.valid)
mmio.io.rw.a.bits := noop.io.dmem.a.bits
mmio.io.rw.a.valid := noop.io.dmem.a.valid
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册