Skip to content

Commit

Permalink
first working test
Browse files Browse the repository at this point in the history
  • Loading branch information
hansemandse committed Nov 24, 2020
1 parent 1a2c9b2 commit f6c41fa
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 27 deletions.
4 changes: 1 addition & 3 deletions axi4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
This project focuses on implementation of AXI4 master interface definitions and a small framework providing support for all of the defined transactions from the AXI master's point of view in the protocol.

## TODO
- Implement basic interface tests
- Evaluate functional master
- Use cover groups

### Extras
- Functional AXI slave (like above)
Expand Down Expand Up @@ -66,7 +64,7 @@ Additionally, two global signals are used (see page A2-28)

Channel descriptions are available in `./src/main/scala/axi4/Defs.scala`. DUVs must conform to the signal names and interfaces provided to function correctly - hence, their IO should extend either the available master or slave interfaces. To enable this more easily, an AXI master can simply extend the Master class found in `./src/main/scala/axi4/Master.scala`, and vice-versa for AXI slaves for which the relevant class is found in `./src/main/scala/axi4/Slave.scala`.

An example of a black-boxed block-RAM with AXI interface is provided in `./src/main/scala/AXI4Memory.scala` - note, however, that due to copyright of the IP source code, you will need to generate the appropriate IP block within Xilinx Vivado to use the blackbox.
An example of a black-boxed block-RAM with AXI interface is provided in `./src/main/scala/VivadoAXIMemory.scala` - note, however, that due to copyright of the IP source code, you will need to generate the appropriate IP block within Xilinx Vivado to use the blackbox. A basic tester is provided in `./src/test/scala/VivadoAXIMemoryTester.scala`.

### References
The full public protocol specification is available from ARM [here](https://developer.arm.com/documentation/ihi0022/e/) and in PDF format [here](http://www.gstitt.ece.ufl.edu/courses/fall15/eel4720_5721/labs/refs/AXI4_specification.pdf). A good video introduction is available from [ARM's YouTube channel](https://www.youtube.com/watch?v=7Vl9JrGgNwk).
Expand Down
7 changes: 4 additions & 3 deletions axi4/src/main/scala/VivadoAXIMemory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import axi4._
import chisel3._
import chisel3.util._
import chisel3.experimental._

/** Vivado IP BRAM with full AXI4 interface */
class mymem extends BlackBox with HasBlackBoxResource {
Expand Down Expand Up @@ -68,8 +67,10 @@ class mymem extends BlackBox with HasBlackBoxResource {
val s00_axi_aresetn = Input(Reset())
})

/** Verilog file in /src/main/resources - top file is mymem.v */
/** Verilog files in /src/main/resources - top file is mymem.v */
addResource("/mymem.v")
addResource("/myaximem_v1_0.v")
addResource("/myaximem_v1_0_S00_AXI.v")
}

/** Wrapper for mymem */
Expand Down Expand Up @@ -135,5 +136,5 @@ class VivadoAXIMemory extends Slave(1, 10, 32) {

/** Clock and reset */
mem.io.s00_axi_aclk := clock
mem.io.s00_axi_aresetn := reset
mem.io.s00_axi_aresetn := !reset
}
2 changes: 1 addition & 1 deletion axi4/src/main/scala/axi4/Transaction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ trait Transaction {
* @param size optional beat size, defaults to 1 byte
* @param burst optional burst type, defaults to INCR
*/
class WriteTransaction(addr: BigInt, data: Seq[BigInt], dataW: Int, size: Int = 0, burst: UInt = BurstEncodings.Incr) {
class WriteTransaction(addr: BigInt, data: Seq[BigInt], dataW: Int, size: Int = 0, burst: UInt = BurstEncodings.Incr) extends Transaction {
private[this] val numBytes = 1 << size
private[this] val dtsize = numBytes * data.length
private[this] val lowerBoundary = (addr / dtsize) * dtsize
Expand Down
79 changes: 59 additions & 20 deletions axi4/src/test/scala/VivadoAXIMemoryTester.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,86 @@
import axi4._
import chisel3._
import chiseltest._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.VerilatorBackendAnnotation
import org.scalatest._

class VivadoAXIMemoryTester extends FlatSpec with ChiselScalatestTester with Matchers {
behavior of "AXI4 BRAM"

it should "initialize" in {
test(new VivadoAXIMemory()) {
test(new VivadoAXIMemory()).withAnnotations(Seq(VerilatorBackendAnnotation)) {
dut =>
val master = new AXI4FunctionalMaster(dut)
master.initialize()
master.close()
}
}

it should "write and read" in {
test(new VivadoAXIMemory()) {
it should "write and read manually" in {
test(new VivadoAXIMemory()).withAnnotations(Seq(VerilatorBackendAnnotation)) {
dut =>
val master = new AXI4FunctionalMaster(dut)
master.initialize()
master.createWriteTrx(0, Seq[BigInt](42), size = 2)
var r = master.checkResponse()

def printCheck() = {
println("AWREADY = " + dut.io.aw.ready.peek.litToBoolean)
println("WREADY = " + dut.io.dw.ready.peek.litToBoolean)
println("BVALID = " + dut.io.wr.valid.peek.litToBoolean)
println("ARREADY = " + dut.io.ar.ready.peek.litToBoolean)
println("RVALID = " + dut.io.dr.valid.peek.litToBoolean)
}

// Set some initial values on the necessary signals
dut.io.dw.bits.data.poke(42.U)
dut.io.dw.bits.strb.poke("b1111".U)
dut.io.dw.bits.last.poke(true.B)
printCheck()

// Write address
dut.io.aw.valid.poke(true.B)
do {
dut.clock.step()
r = master.checkResponse()
} while (r == None)
var resp = r match {
case Some(r) => r.resp.litValue
case _ => 0
}
println(s"Got response code $resp")
master.createReadTrx(0, size = 2)
var v = master.checkReadData()
} while (!dut.io.aw.ready.peek.litToBoolean)
printCheck()
dut.clock.step()
dut.io.aw.valid.poke(false.B)

// Write some data
dut.io.dw.valid.poke(true.B)
do {
dut.clock.step()
v = master.checkReadData()
} while (v == None)
var values = v match {
case Some(v) => v
case _ => Seq[BigInt](-1)
} while (!dut.io.dw.ready.peek.litToBoolean)
printCheck()
dut.clock.step()
dut.io.dw.valid.poke(false.B)

// Fetch response
dut.io.wr.ready.poke(true.B)
while (!dut.io.wr.valid.peek.litToBoolean) {
dut.clock.step()
}
println(s"Got read data $values")
printCheck()
val r = dut.io.wr.bits.resp.peek.litValue
println(s"Got response $r")

// Read address
dut.io.ar.valid.poke(true.B)
do {
dut.clock.step()
} while (!dut.io.ar.ready.peek.litToBoolean)
printCheck()
dut.clock.step()
dut.io.ar.valid.poke(false.B)

// Read some data
dut.io.dr.ready.poke(true.B)
while (!dut.io.dr.valid.peek.litToBoolean) {
dut.clock.step()
}
printCheck()
dut.io.dr.bits.data.expect(42.U)

master.close()
}
}
Expand Down

0 comments on commit f6c41fa

Please sign in to comment.