Livt packages

Livt.Net

Version 1.4.1

Ethernet, IPv4, TCP, UDP, ARP, TFTP, and Telnet networking components for Livt hardware.

Published files (163)

src/drivers/ethernetlite/EthernetLiteTransactions.lvt

namespace Livt.Net.Drivers.EthernetLite

enum EthernetLiteBusOperation
{
	Read
	Write
}

/**
 * Serialized AXI4-Lite word transactions with independent AW/W acceptance.
 * One driver calls the scheduled methods; hardware signals remain live through
 * explicit live pins. Stalls retain requests until handshake.
 * Reset must also reset the external slave; no local abort of an AXI transfer.
 */
component EthernetLiteTransactions : IEthernetLiteRegisterAccess
{
	public awready: in logic
	public wready: in logic
	public bresp: in logic[2]
	public bvalid: in logic
	public arready: in logic
	public rdata: in logic[32]
	public rresp: in logic[2]
	public rvalid: in logic
	public awaddr: out logic[13]
	public awvalid: out logic
	public wdata: out logic[32]
	public wstrb: out logic[4]
	public wvalid: out logic
	public bready: out logic
	public araddr: out logic[13]
	public arvalid: out logic
	public rready: out logic

	// Live AXI signals, sampled by the transaction state machine.
	busAwready: logic
	busAwaddr: logic[13]
	busAwvalid: logic
	busWready: logic
	busWdata: logic[32]
	busWstrb: logic[4]
	busWvalid: logic
	busBresp: logic[2]
	busBvalid: logic
	busBready: logic
	busArready: logic
	busAraddr: logic[13]
	busArvalid: logic
	busRdata: logic[32]
	busRresp: logic[2]
	busRvalid: logic
	busRready: logic

	// Single-owner command mailbox; completion is published after response capture.
	operation: EthernetLiteBusOperation
	address: logic[13]
	writeData: logic[32]
	readData: logic[32]
	response: logic[2]
	requested: bool
	completed: bool

	/**
	 * Starts all channels inactive; the owner connects live pins to the device bus.
	 */
	new()
	{
	}

	/**
	 * Waits for a read response; only OKAY returns true. Output is zero on failure.
	 */
	override fn Read(address: logic[13], value: out logic[32]) bool
	{
		this.address = address
		this.operation = EthernetLiteBusOperation.Read
		this.requested = !this.requested

		while (this.completed != this.requested) {
			state {
			}
		}

		value = 0x00000000

		if (this.response != 0b00) {
			return false
		}

		value = this.readData
		return true
	}

	/**
	 * Waits for both channel acceptances and B response; only OKAY returns true.
	 */
	override fn Write(address: logic[13], value: logic[32]) bool
	{
		this.address = address
		this.writeData = value
		this.operation = EthernetLiteBusOperation.Write
		this.requested = !this.requested

		while (this.completed != this.requested) {
			state {
			}
		}

		return this.response == 0b00
	}

	/**
	 * Publishes and samples live pins without implicit stored-field boundary stages.
	 */
	process Pins[]()
	{
		this.busAwready = this.awready
		this.busWready = this.wready
		this.busBresp = this.bresp
		this.busBvalid = this.bvalid
		this.busArready = this.arready
		this.busRdata = this.rdata
		this.busRresp = this.rresp
		this.busRvalid = this.rvalid
		this.awaddr = this.busAwaddr
		this.awvalid = this.busAwvalid
		this.wdata = this.busWdata
		this.wstrb = this.busWstrb
		this.wvalid = this.busWvalid
		this.bready = this.busBready
		this.araddr = this.busAraddr
		this.arvalid = this.busArvalid
		this.rready = this.busRready
	}

	/**
	 * Completes one command at a time; response data is latched at handshake.
	 */
	process Transactions()
	{
		var addressDone = false
		var dataDone = false

		state Idle {
			if (this.requested == this.completed) {
				goto Idle
			}
			elif (this.operation == EthernetLiteBusOperation.Read) {
				this.busAraddr = this.address
				this.busArvalid = 0b1
				goto ReadAddress
			} else {
				this.busAwaddr = this.address
				this.busWdata = this.writeData
				this.busWstrb = 0b1111
				this.busAwvalid = 0b1
				this.busWvalid = 0b1
				addressDone = false
				dataDone = false
				goto WriteChannels
			}
		}

		state ReadAddress {
			if (this.busArready == 0b1) {
				this.busArvalid = 0b0
				this.busRready = 0b1
				goto ReadResponse
			} else { goto ReadAddress }
		}

		state ReadResponse {
			if (this.busRvalid == 0b1) {
				this.readData = this.busRdata
				this.response = this.busRresp
				this.busRready = 0b0
				goto Complete
			} else { goto ReadResponse }
		}

		state WriteChannels {
			if (!addressDone && this.busAwready == 0b1) {
				addressDone = true
				this.busAwvalid = 0b0
			}

			if (!dataDone && this.busWready == 0b1) {
				dataDone = true
				this.busWvalid = 0b0
			}

			if (addressDone && dataDone) {
				this.busWstrb = 0b0000
				this.busBready = 0b1
				goto WriteResponse
			} else { goto WriteChannels }
		}

		state WriteResponse {
			if (this.busBvalid == 0b1) {
				this.response = this.busBresp
				this.busBready = 0b0
				goto Complete
			} else { goto WriteResponse }
		}

		state Complete {
			this.completed = this.requested
			goto Idle
		}
	}
}