From 72a854eb075f90fde3fa9bfb6ba653845c2d54f6 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 31 Oct 2024 13:01:25 -0500 Subject: [PATCH] Refactored SPI passes regression save for hardware interlock tests. --- src/uncore/spi_apb.sv | 21 ++++++++++++-- src/uncore/spi_controller.sv | 53 +++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 33978637b..c8084de42 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -86,6 +86,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic EndOfFrameDelay; logic Transmitting; logic InactiveState; + logic [3:0] FrameLength; logic ResetSCLKenable; logic TransmitStart; @@ -213,12 +214,13 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // SPI Controller module ------------------------------------------- // This module controls state and timing signals that drive the rest of this module assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV); + assign FrameLength = Format[4:1]; spi_controller controller(PCLK, PRESETn, // Transmit Signals TransmitStart, TransmitStartD, ResetSCLKenable, // Register Inputs - SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, + SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff TransmitFIFOReadEmpty, // Timing @@ -243,6 +245,19 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; end + // Check whether TransmitReg has been loaded. + // We use this signal to prevent returning to the Ready state for TransmitStart + logic TransmitRegLoaded; + always_ff @(posedge PCLK) begin + if (~PRESETn) begin + TransmitRegLoaded <= 1'b0; + end else if (TransmitLoad) begin + TransmitRegLoaded <= 1'b1; + end else if (ShiftEdge | EndOfFrameDelay) begin + TransmitRegLoaded <= 1'b0; + end + end + // Setup TransmitStart state machine always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -251,14 +266,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( CurrState <= NextState; end end - + // State machine for starting transmissions always_comb begin case (CurrState) READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; - WAIT: if (TransmitFIFOReadEmpty & ~Transmitting) NextState = READY; + WAIT: if (TransmitFIFOReadEmpty & ~Transmitting & ~TransmitRegLoaded) NextState = READY; else NextState = WAIT; endcase end diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 10ff511a6..2b74e79c9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -43,6 +43,7 @@ module spi_controller ( input logic [1:0] CSMode, input logic [15:0] Delay0, input logic [15:0] Delay1, + input logic [3:0] FrameLength, // Is the Transmit FIFO Empty? input logic txFIFOReadEmpty, @@ -146,7 +147,7 @@ module spi_controller ( assign SCLKenable = DivCounter == SckDiv; // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; - assign LastBit = BitNum == 3'd7; + assign LastBit = (BitNum == FrameLength - 4'b1); //assign EndOfFrame = SCLKenable & LastBit & Transmitting; assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay; @@ -161,6 +162,10 @@ module spi_controller ( PreShiftEdge <= 0; PreSampleEdge <= 0; EndOfFrame <= 0; + CSSCKCounter <= 0; + SCKCSCounter <= 0; + INTERCSCounter <= 0; + INTERXFRCounter <= 0; end else begin // TODO: Consolidate into one delay counter since none of the // delays happen at the same time? @@ -172,25 +177,25 @@ module spi_controller ( if ((CurrState == CSSCK) & SCK & SCLKenable) begin CSSCKCounter <= CSSCKCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfCSSCK) begin CSSCKCounter <= 8'd0; end if ((CurrState == SCKCS) & SCK & SCLKenable) begin SCKCSCounter <= SCKCSCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfSCKCS) begin SCKCSCounter <= 8'd0; end if ((CurrState == INTERCS) & SCK & SCLKenable) begin INTERCSCounter <= INTERCSCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfINTERCS) begin INTERCSCounter <= 8'd0; end if ((CurrState == INTERXFR) & SCK & SCLKenable) begin INTERXFRCounter <= INTERXFRCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfINTERXFR) begin INTERXFRCounter <= 8'd0; end @@ -239,7 +244,7 @@ module spi_controller ( EndOfFrameDelay <= 0; end else begin ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; - PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : PhaseOneOffset; + PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; end @@ -251,6 +256,23 @@ module spi_controller ( assign HoldMode = CSMode == HOLDMODE; // assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); + logic ContinueTransmitD; + logic NextEndDelay; + logic CurrentEndDelay; + + assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR; + assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR; + + always_ff @(posedge PCLK) begin + if (~PRESETn) begin + ContinueTransmitD <= 1'b0; + end else if (NextEndDelay & ~CurrentEndDelay) begin + ContinueTransmitD <= ContinueTransmit; + end else if (EndOfSCKCS & SCLKenable) begin + ContinueTransmitD <= 1'b0; + end + end + always_ff @(posedge PCLK) begin if (~PRESETn) begin CurrState <= INACTIVE; @@ -261,17 +283,19 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: if (TransmitStartD) + INACTIVE: if (TransmitStartD) begin if (~HasCSSCK) NextState = TRANSMIT; else NextState = CSSCK; - else NextState = INACTIVE; + end else begin + NextState = INACTIVE; + end CSSCK: if (EndOfCSSCK) NextState = TRANSMIT; else NextState = CSSCK; TRANSMIT: begin // TRANSMIT case -------------------------------- case(CSMode) AUTOMODE: begin if (EndTransmission) NextState = INACTIVE; - else if (ContinueTransmit) NextState = SCKCS; + else if (EndOfFrameDelay) NextState = SCKCS; end HOLDMODE: begin if (EndTransmission) NextState = HOLD; @@ -279,19 +303,22 @@ module spi_controller ( else NextState = TRANSMIT; end OFFMODE: begin - + if (EndTransmission) NextState = INACTIVE; + else if (ContinueTransmit & HasINTERXFR) NextState = INTERXFR; + else NextState = TRANSMIT; end endcase end SCKCS: begin // SCKCS case -------------------------------------- - if (EndOfSCKCS) - if (txFIFOReadEmpty) begin + if (EndOfSCKCS) begin + if (~ContinueTransmitD) begin if (CSMode == AUTOMODE) NextState = INACTIVE; else if (CSMode == HOLDMODE) NextState = HOLD; - end else if (~txFIFOReadEmpty) begin + end else begin if (HasINTERCS) NextState = INTERCS; else NextState = TRANSMIT; end + end end HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin