mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
实验报告检查
This commit is contained in:
362
lab4/朱梓涵24325356/bus/AXI4Lite.scala
Normal file
362
lab4/朱梓涵24325356/bus/AXI4Lite.scala
Normal file
@@ -0,0 +1,362 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
40
lab4/朱梓涵24325356/bus/BusArbiter.scala
Normal file
40
lab4/朱梓涵24325356/bus/BusArbiter.scala
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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 riscv.Parameters
|
||||
|
||||
class BusArbiter extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val bus_request = Input(Vec(Parameters.MasterDeviceCount, Bool()))
|
||||
val bus_granted = Output(Vec(Parameters.MasterDeviceCount, Bool()))
|
||||
|
||||
val ctrl_stall_flag = Output(Bool())
|
||||
})
|
||||
val granted = Wire(UInt())
|
||||
// Static Priority Arbitration
|
||||
// Higher number = Higher priority
|
||||
granted := 0.U
|
||||
for (i <- 0 until Parameters.MasterDeviceCount) {
|
||||
when(io.bus_request(i.U)) {
|
||||
granted := i.U
|
||||
}
|
||||
}
|
||||
for (i <- 0 until Parameters.MasterDeviceCount) {
|
||||
io.bus_granted(i.U) := i.U === granted
|
||||
}
|
||||
io.ctrl_stall_flag := !io.bus_granted(0.U)
|
||||
}
|
||||
33
lab4/朱梓涵24325356/bus/BusSwitch.scala
Normal file
33
lab4/朱梓涵24325356/bus/BusSwitch.scala
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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 peripheral.DummyMaster
|
||||
import riscv.Parameters
|
||||
|
||||
class BusSwitch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val address = Input(UInt(Parameters.AddrWidth))
|
||||
val slaves = Vec(Parameters.SlaveDeviceCount, new AXI4LiteChannels(Parameters.AddrBits, Parameters.DataBits))
|
||||
val master = Flipped(new AXI4LiteChannels(Parameters.AddrBits, Parameters.DataBits))
|
||||
})
|
||||
val dummy = Module(new DummyMaster)
|
||||
val index = io.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
for (i <- 0 until Parameters.SlaveDeviceCount) {
|
||||
io.slaves(i) <> dummy.io.channels
|
||||
}
|
||||
io.master <> io.slaves(index)
|
||||
}
|
||||
Reference in New Issue
Block a user