From 1b2f88998fd0499e2cc37e0719f8d29b380ac3b5 Mon Sep 17 00:00:00 2001 From: Sina Karvandi Date: Thu, 18 Apr 2024 20:21:53 +0900 Subject: [PATCH] add implementation of sender receiver synchronizer module --- .../scala/hwdbg/communication/receiver.scala | 13 +- .../send_receive_synchronizer.scala | 206 +++++++++++++++++- .../scala/hwdbg/communication/sender.scala | 8 +- 3 files changed, 213 insertions(+), 14 deletions(-) diff --git a/src/main/scala/hwdbg/communication/receiver.scala b/src/main/scala/hwdbg/communication/receiver.scala index d6adf9a..852be85 100644 --- a/src/main/scala/hwdbg/communication/receiver.scala +++ b/src/main/scala/hwdbg/communication/receiver.scala @@ -68,10 +68,11 @@ class DebuggerPacketReceiver( // val requestedActionOfThePacketOutput = Output(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action val requestedActionOfThePacketOutputValid = Output(Bool()) // whether data on the requested action is valid or not - val noNewData = Input(Bool()) // receive done or not? + val noNewDataReceiver = Input(Bool()) // receive done or not? - // (this contains and edge-detection mechanism, which means reader should make it low after reading the data) + // this contains and edge-detection mechanism, which means reader should make it low after reading the data val readNextData = Input(Bool()) // whether the next data should be read or not? + val dataValidOutput = Output(Bool()) // whether data on the receiving data line is valid or not? val receivingData = Output(UInt(bramDataWidth.W)) // data to be sent to the reader @@ -141,7 +142,7 @@ class DebuggerPacketReceiver( regRequestedActionOfThePacketOutputValid := false.B regDataValidOutput := false.B regReceivingData := 0.U - regFinishedIReceivingBuffer := false.B + regFinishedReceivingBuffer := false.B } is(sReadChecksum) { @@ -254,7 +255,7 @@ class DebuggerPacketReceiver( // state := sReadActionBuffer - }.elsewhen(io.noNewData === true.B && io.readNextData === false.B) { + }.elsewhen(io.noNewDataReceiver === true.B && io.readNextData === false.B) { // // No new data, the receiving is done @@ -330,7 +331,7 @@ object DebuggerPacketReceiver { en: Bool, plInSignal: Bool, rdData: UInt, - noNewData: Bool, + noNewDataReceiver: Bool, readNextData: Bool ): (UInt, UInt, Bool, Bool, UInt, Bool) = { @@ -355,7 +356,7 @@ object DebuggerPacketReceiver { debuggerPacketReceiver.io.en := en debuggerPacketReceiver.io.plInSignal := plInSignal debuggerPacketReceiver.io.rdData := rdData - debuggerPacketReceiver.io.noNewData := noNewData + debuggerPacketReceiver.io.noNewDataReceiver := noNewDataReceiver debuggerPacketReceiver.io.readNextData := readNextData // diff --git a/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala b/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala index 853c6c3..60eebde 100644 --- a/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala +++ b/src/main/scala/hwdbg/communication/send_receive_synchronizer.scala @@ -16,17 +16,30 @@ package hwdbg.communication import chisel3._ +import chisel3.util.{switch, is} import circt.stage.ChiselStage import hwdbg.configs._ import hwdbg.types._ +object SendReceiveSynchronizerEnums { + object State extends ChiselEnum { + val sIdle, sReceiver, sSender = Value + } +} + class SendReceiveSynchronizer( debug: Boolean = DebuggerConfigurations.ENABLE_DEBUG, bramAddrWidth: Int = DebuggerConfigurations.BLOCK_RAM_ADDR_WIDTH, bramDataWidth: Int = DebuggerConfigurations.BLOCK_RAM_DATA_WIDTH ) extends Module { + // + // Import state enum + // + import SendReceiveSynchronizerEnums.State + import SendReceiveSynchronizerEnums.State._ + val io = IO(new Bundle { // @@ -49,19 +62,24 @@ class SendReceiveSynchronizer( val wrData = Output(UInt(bramDataWidth.W)) // write data // - // Receiver ports + // Receiver signals // val requestedActionOfThePacketOutput = Output(UInt(new DebuggerRemotePacket().RequestedActionOfThePacket.getWidth.W)) // the requested action val requestedActionOfThePacketOutputValid = Output(Bool()) // whether data on the requested action is valid or not + + val noNewDataReceiver = Input(Bool()) // receive done or not? + val readNextData = Input(Bool()) // whether the next data should be read or not? + val dataValidOutput = Output(Bool()) // whether data on the receiving data line is valid or not? val receivingData = Output(UInt(bramDataWidth.W)) // data to be sent to the reader - val finishedReceivingBuffer = Output(Bool()) // receiving is done or not? + + val finishedReceivingBuffer = Output(Bool()) // Receiving is done or not? // // Sender ports // val beginSendingBuffer = Input(Bool()) // should sender start sending buffers or not? - val noNewData = Input(Bool()) // should sender finish sending buffers or not? + val noNewDataSender = Input(Bool()) // should sender finish sending buffers or not? val dataValidInput = Input(Bool()) // should sender send next buffer or not? val sendWaitForBuffer = Output(Bool()) // should the external module send next buffer or not? @@ -73,9 +91,189 @@ class SendReceiveSynchronizer( }) // - // To be implemented + // State registers + // + val state = RegInit(sIdle) + + // + // Saving state of the controlling pins + // + val regPlInSignal = RegInit(false.B) + val regBeginSendingBuffer = RegInit(false.B) + // + // Shared BRAM pins + // + val sharedRdWrAddr = WireInit(0.U(bramAddrWidth.W)) // read/write address + val sharedRdData = WireInit(0.U(bramDataWidth.W)) // read data + val sharedWrEna = WireInit(false.B) // enable writing + val sharedWrData = WireInit(0.U(bramDataWidth.W)) // write data + + // + // Instantiate the packet receiver module + // + val ( + receiverRdWrAddr, + requestedActionOfThePacketOutput, + requestedActionOfThePacketOutputValid, + dataValidOutput, + receivingData, + finishedReceivingBuffer + ) = + DebuggerPacketReceiver( + debug, + bramAddrWidth, + bramDataWidth + )( + io.en, + regPlInSignal, + io.rdData, + io.noNewDataReceiver, + io.readNextData + ) + + // + // Instantiate the packet sender module + // + val ( + psOutInterrupt, + senderRdWrAddr, + wrEna, + wrData, + sendWaitForBuffer, + finishedSendingBuffer + ) = + DebuggerPacketSender( + debug, + bramAddrWidth, + bramDataWidth + )( + io.en, + regBeginSendingBuffer, + io.noNewDataSender, + io.dataValidInput, + io.requestedActionOfThePacketInput, + io.sendingData + ) + + // + // Apply the chip enable signal + // + when(io.en === true.B) { + + switch(state) { + is(sIdle) { + + // + // Peform the resource sepration of shared BRAM + // and apply priority to receive over send + // + when(io.plInSignal === true.B) { + + // + // Activate the receiver module + // + regPlInSignal := true.B + + // + // Go to the receiver state + // + state := sReceiver + + }.elsewhen(io.beginSendingBuffer === true.B && io.plInSignal === false.B) { + + // + // Activate the sender module + // + regBeginSendingBuffer := true.B + + // + // Go to the sender state + // + state := sReceiver + + }.otherwise { + + // + // Stay at the same state as there is no communication + // + state := sIdle + + } + + } + is(sReceiver) { + + // + // Check whether the receiving is finished + // + when(finishedReceivingBuffer === true.B) { + + // + // No longer in the receiver state + // + regPlInSignal := false.B + + // + // Go to the idle state + // + state := sIdle + + }.otherwise { + + // + // Connect the address of BRAM reader to the receiver address + // + sharedRdWrAddr := receiverRdWrAddr + + // + // On the receiver, writing is not allowed + // + sharedWrEna := false.B + + // + // Stay at the same state + // + state := sReceiver + + } + } + is(sSender) { + + // + // Check whether sending data is finished + // + when(finishedSendingBuffer === true.B) { + + // + // No longer in the sender state + // + regBeginSendingBuffer := false.B + + // + // Go to the idle state + // + state := sIdle + + }.otherwise { + + // + // Connect shared BRAM signals to the sender + // + sharedRdWrAddr := senderRdWrAddr + sharedWrEna := wrEna + sharedWrData := wrData + + // + // Stay at the same state + // + state := sSender + + } + } + } + } } object SendReceiveSynchronizer { diff --git a/src/main/scala/hwdbg/communication/sender.scala b/src/main/scala/hwdbg/communication/sender.scala index c8db584..6f49b94 100644 --- a/src/main/scala/hwdbg/communication/sender.scala +++ b/src/main/scala/hwdbg/communication/sender.scala @@ -66,7 +66,7 @@ class DebuggerPacketSender( // Sending signals // val beginSendingBuffer = Input(Bool()) // should sender start sending buffers or not? - val noNewData = Input(Bool()) // should sender finish sending buffers or not? + val noNewDataSender = Input(Bool()) // should sender finish sending buffers or not? val dataValidInput = Input(Bool()) // should sender send next buffer or not? val sendWaitForBuffer = Output(Bool()) // should the external module send next buffer or not? @@ -257,7 +257,7 @@ class DebuggerPacketSender( // state := sSendData - }.elsewhen(io.noNewData === true.B && io.dataValidInput === true.B) { + }.elsewhen(io.noNewDataSender === true.B && io.dataValidInput === true.B) { // // Sending data was done @@ -344,7 +344,7 @@ object DebuggerPacketSender { )( en: Bool, beginSendingBuffer: Bool, - noNewData: Bool, + noNewDataSender: Bool, dataValidInput: Bool, requestedActionOfThePacketInput: UInt, sendingData: UInt @@ -370,7 +370,7 @@ object DebuggerPacketSender { // debuggerPacketSender.io.en := en debuggerPacketSender.io.beginSendingBuffer := beginSendingBuffer - debuggerPacketSender.io.noNewData := noNewData + debuggerPacketSender.io.noNewDataSender := noNewDataSender debuggerPacketSender.io.dataValidInput := dataValidInput debuggerPacketSender.io.requestedActionOfThePacketInput := requestedActionOfThePacketInput debuggerPacketSender.io.sendingData := sendingData