Files
2025-yatcpu/lab4/朱梓涵24325356/bus/AXI4Lite.scala
2025-12-21 23:11:21 +08:00

363 lines
12 KiB
Scala
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2021 Howard Lau
//
// Licensed 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 bus
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.util._
import riscv.Parameters
object AXI4Lite {
val protWidth = 3
val respWidth = 2
}
class AXI4LiteWriteAddressChannel(addrWidth: Int) extends Bundle {
val AWVALID = Output(Bool())
val AWREADY = Input(Bool())
val AWADDR = Output(UInt(addrWidth.W))
val AWPROT = Output(UInt(AXI4Lite.protWidth.W))
}
class AXI4LiteWriteDataChannel(dataWidth: Int) extends Bundle {
val WVALID = Output(Bool())
val WREADY = Input(Bool())
val WDATA = Output(UInt(dataWidth.W))
val WSTRB = Output(UInt((dataWidth / 8).W))
}
class AXI4LiteWriteResponseChannel extends Bundle {
val BVALID = Input(Bool())
val BREADY = Output(Bool())
val BRESP = Input(UInt(AXI4Lite.respWidth.W))
}
class AXI4LiteReadAddressChannel(addrWidth: Int) extends Bundle {
val ARVALID = Output(Bool())
val ARREADY = Input(Bool())
val ARADDR = Output(UInt(addrWidth.W))
val ARPROT = Output(UInt(AXI4Lite.protWidth.W))
}
class AXI4LiteReadDataChannel(dataWidth: Int) extends Bundle {
val RVALID = Input(Bool())
val RREADY = Output(Bool())
val RDATA = Input(UInt(dataWidth.W))
val RRESP = Input(UInt(AXI4Lite.respWidth.W))
}
class AXI4LiteInterface(addrWidth: Int, dataWidth: Int) extends Bundle {
val AWVALID = Output(Bool())
val AWREADY = Input(Bool())
val AWADDR = Output(UInt(addrWidth.W))
val AWPROT = Output(UInt(AXI4Lite.protWidth.W))
val WVALID = Output(Bool())
val WREADY = Input(Bool())
val WDATA = Output(UInt(dataWidth.W))
val WSTRB = Output(UInt((dataWidth / 8).W))
val BVALID = Input(Bool())
val BREADY = Output(Bool())
val BRESP = Input(UInt(AXI4Lite.respWidth.W))
val ARVALID = Output(Bool())
val ARREADY = Input(Bool())
val ARADDR = Output(UInt(addrWidth.W))
val ARPROT = Output(UInt(AXI4Lite.protWidth.W))
val RVALID = Input(Bool())
val RREADY = Output(Bool())
val RDATA = Input(UInt(dataWidth.W))
val RRESP = Input(UInt(AXI4Lite.respWidth.W))
}
class AXI4LiteChannels(addrWidth: Int, dataWidth: Int) extends Bundle {
val write_address_channel = new AXI4LiteWriteAddressChannel(addrWidth)
val write_data_channel = new AXI4LiteWriteDataChannel(dataWidth)
val write_response_channel = new AXI4LiteWriteResponseChannel()
val read_address_channel = new AXI4LiteReadAddressChannel(addrWidth)
val read_data_channel = new AXI4LiteReadDataChannel(dataWidth)
}
class AXI4LiteSlaveBundle(addrWidth: Int, dataWidth: Int) extends Bundle {
val read = Output(Bool()) // tell slave device to read
val write = Output(Bool()) // tell slave device to write
val read_data = Input(UInt(dataWidth.W)) // data read from slave device
val read_valid = Input(Bool()) // indicates if read_data is valid
val write_data = Output(UInt(dataWidth.W))
val write_strobe = Output(Vec(Parameters.WordSize, Bool()))
val address = Output(UInt(addrWidth.W))
}
class AXI4LiteMasterBundle(addrWidth: Int, dataWidth: Int) extends Bundle {
val read = Input(Bool()) // request a read transaction
val write = Input(Bool()) // request a write transaction
val read_data = Output(UInt(dataWidth.W))
val write_data = Input(UInt(dataWidth.W))
val write_strobe = Input(Vec(Parameters.WordSize, Bool()))
val address = Input(UInt(addrWidth.W))
val busy = Output(Bool()) // if busy, master is not ready to accept new transactions
val read_valid = Output(Bool()) // indicates read transaction done successfully and asserts for ONLY 1 cycle.
val write_valid = Output(Bool()) // indicates write transaction done successfully and asserts for ONLY 1 cycle.
}
object AXI4LiteStates extends ChiselEnum {
val Idle, ReadAddr, ReadDataWait, ReadData, WriteAddr, WriteData, WriteResp = Value
}
class AXI4LiteSlave(addrWidth: Int, dataWidth: Int) extends Module {
val io = IO(new Bundle {
val channels = Flipped(new AXI4LiteChannels(addrWidth, dataWidth))
val bundle = new AXI4LiteSlaveBundle(addrWidth, dataWidth)
})
val state = RegInit(AXI4LiteStates.Idle)
val addr = RegInit(0.U(dataWidth.W))
io.bundle.address := addr
val read = RegInit(false.B)
io.bundle.read := read
val write = RegInit(false.B)
io.bundle.write := write
val write_data = RegInit(0.U(dataWidth.W))
io.bundle.write_data := write_data
val write_strobe = RegInit(VecInit(Seq.fill(Parameters.WordSize)(false.B)))
io.bundle.write_strobe := write_strobe
val ARREADY = RegInit(false.B)
io.channels.read_address_channel.ARREADY := ARREADY
val RVALID = RegInit(false.B)
io.channels.read_data_channel.RVALID := RVALID
val RRESP = RegInit(0.U(AXI4Lite.respWidth))
io.channels.read_data_channel.RRESP := RRESP
val AWREADY = RegInit(false.B)
io.channels.write_address_channel.AWREADY := AWREADY
val WREADY = RegInit(false.B)
io.channels.write_data_channel.WREADY := WREADY
write_data := io.channels.write_data_channel.WDATA
val BVALID = RegInit(false.B)
io.channels.write_response_channel.BVALID := BVALID
val BRESP = WireInit(0.U(AXI4Lite.respWidth))
io.channels.write_response_channel.BRESP := BRESP
//lab4(BUS)
// 读数据寄存器,保证 RDATA 在 RVALID 为高时稳定
val rdataReg = RegInit(0.U(dataWidth.W))
io.channels.read_data_channel.RDATA := rdataReg
switch(state) {
is(AXI4LiteStates.Idle) {
// 默认信号
ARREADY := false.B
RVALID := false.B
AWREADY := false.B
WREADY := false.B
BVALID := false.B
read := false.B
write := false.B
when(io.channels.read_address_channel.ARVALID) {
addr := io.channels.read_address_channel.ARADDR
ARREADY := true.B
state := AXI4LiteStates.ReadAddr
}.elsewhen(io.channels.write_address_channel.AWVALID) {
addr := io.channels.write_address_channel.AWADDR
AWREADY := true.B
state := AXI4LiteStates.WriteAddr
}
}
is(AXI4LiteStates.ReadAddr) {
// 已经完成 ARVALID/ARREADY 握手,将地址送给从设备并发起一次读
ARREADY := false.B
read := true.B
state := AXI4LiteStates.ReadData
}
is(AXI4LiteStates.ReadData) {
// 保持对设备的读请求,等待设备返回 read_valid
read := true.B
when(io.bundle.read_valid && !RVALID) {
// 设备已经准备好数据将其锁存并让RVALID为1
rdataReg := io.bundle.read_data
RVALID := true.B
}.elsewhen(RVALID && io.channels.read_data_channel.RREADY) {
// 主机已经接收数据,完成一次读事务
RVALID := false.B
read := false.B
state := AXI4LiteStates.Idle
}
}
is(AXI4LiteStates.WriteAddr) {
// 写地址握手结束,等待写数据
AWREADY := false.B
when(io.channels.write_data_channel.WVALID) {
// 收到写数据,锁存写数据及写选通
write_data := io.channels.write_data_channel.WDATA
val wstrb = io.channels.write_data_channel.WSTRB
when(wstrb === 0.U) {
write_strobe := VecInit(Seq.fill(Parameters.WordSize)(true.B))
}.otherwise {
write_strobe := VecInit(wstrb.asBools)
}
WREADY := true.B
write := true.B
state := AXI4LiteStates.WriteData
}
}
is(AXI4LiteStates.WriteData) {
// 向设备发出一次写请求WREADY 在一个周期后拉低
WREADY := false.B
write := false.B
BVALID := true.B
state := AXI4LiteStates.WriteResp
}
is(AXI4LiteStates.WriteResp) {
// 等待主机对写响应握手
when(io.channels.write_response_channel.BREADY) {
BVALID := false.B
state := AXI4LiteStates.Idle
}
}
}
}
class AXI4LiteMaster(addrWidth: Int, dataWidth: Int) extends Module {
val io = IO(new Bundle {
val channels = new AXI4LiteChannels(addrWidth, dataWidth)
val bundle = new AXI4LiteMasterBundle(addrWidth, dataWidth)
})
val state = RegInit(AXI4LiteStates.Idle)
io.bundle.busy := state =/= AXI4LiteStates.Idle
val addr = RegInit(0.U(dataWidth.W))
val read_valid = RegInit(false.B)
io.bundle.read_valid := read_valid
val write_valid = RegInit(false.B)
io.bundle.write_valid := write_valid
val write_data = RegInit(0.U(dataWidth.W))
val write_strobe = RegInit(VecInit(Seq.fill(Parameters.WordSize)(false.B)))
val read_data = RegInit(0.U(dataWidth.W))
io.channels.read_address_channel.ARADDR := 0.U
val ARVALID = RegInit(false.B)
io.channels.read_address_channel.ARVALID := ARVALID
io.channels.read_address_channel.ARPROT := 0.U
val RREADY = RegInit(false.B)
io.channels.read_data_channel.RREADY := RREADY
io.bundle.read_data := read_data
val AWVALID = RegInit(false.B)
io.channels.write_address_channel.AWADDR := 0.U
io.channels.write_address_channel.AWVALID := AWVALID
val WVALID = RegInit(false.B)
io.channels.write_data_channel.WVALID := WVALID
io.channels.write_data_channel.WDATA := write_data
io.channels.write_address_channel.AWPROT := 0.U
io.channels.write_data_channel.WSTRB := write_strobe.asUInt
val BREADY = RegInit(false.B)
io.channels.write_response_channel.BREADY := BREADY
//lab4(BUS)
// read_valid / write_valid 只拉高一个周期在switch之前清零以便switch可以覆盖
when(read_valid) { read_valid := false.B }
when(write_valid) { write_valid := false.B }
switch(state) {
is(AXI4LiteStates.Idle) {
ARVALID := false.B
RREADY := false.B
AWVALID := false.B
WVALID := false.B
BREADY := false.B
when(io.bundle.read) {
// 发起读事务
addr := io.bundle.address
state := AXI4LiteStates.ReadAddr
ARVALID := true.B
}.elsewhen(io.bundle.write) {
// 发起写事务
addr := io.bundle.address
write_data := io.bundle.write_data
write_strobe := io.bundle.write_strobe
state := AXI4LiteStates.WriteAddr
AWVALID := true.B
}
}
is(AXI4LiteStates.ReadAddr) {
// 发送读地址,直到从机准备好
ARVALID := true.B
io.channels.read_address_channel.ARADDR := addr
when(io.channels.read_address_channel.ARREADY) {
ARVALID := false.B
RREADY := true.B
state := AXI4LiteStates.ReadData
}
}
is(AXI4LiteStates.ReadData) {
// 保持 RREADY 高,等待从机 RVALID
RREADY := true.B
when(io.channels.read_data_channel.RVALID) {
read_data := io.channels.read_data_channel.RDATA
RREADY := false.B
read_valid := true.B
state := AXI4LiteStates.Idle
}
}
is(AXI4LiteStates.WriteAddr) {
// 发送写地址,直到从机准备好
AWVALID := true.B
io.channels.write_address_channel.AWADDR := addr
when(io.channels.write_address_channel.AWREADY) {
AWVALID := false.B
WVALID := true.B
state := AXI4LiteStates.WriteData
}
}
is(AXI4LiteStates.WriteData) {
// 发送写数据,直到从机接受
WVALID := true.B
io.channels.write_data_channel.WDATA := write_data
io.channels.write_data_channel.WSTRB := write_strobe.asUInt
when(io.channels.write_data_channel.WREADY) {
WVALID := false.B
BREADY := true.B
state := AXI4LiteStates.WriteResp
}
}
is(AXI4LiteStates.WriteResp) {
// 等待从机写响应
BREADY := true.B
when(io.channels.write_response_channel.BVALID) {
BREADY := false.B
write_valid := true.B
state := AXI4LiteStates.Idle
}
}
}
}