From a9e6962cd4de508d8d0e60366f4981784f24b89e Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sun, 3 Nov 2024 00:35:40 -0500 Subject: [PATCH 1/3] Removed unused signals and renamed other signals. Removed a bunch of delay counters and simply reuse one counter for all delay types. Tested on FPGA and it also passes regression. --- src/uncore/spi_apb.sv | 90 ++++++++++--------- src/uncore/spi_controller.sv | 163 ++++++++++++----------------------- 2 files changed, 101 insertions(+), 152 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 293c2c2b5..38fa07f42 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -85,11 +85,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // SPI Controller signals logic SCLKenable; logic EndOfFrame; - logic EndOfFrameDelay; logic Transmitting; logic InactiveState; logic [3:0] FrameLength; + // logic ResetSCLKenable; logic TransmitStart; logic TransmitStartD; @@ -100,14 +100,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // FIFO FSM signals // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] - logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; - logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; - logic TransmitFIFOWriteIncrement; - logic [7:0] TransmitFIFOReadData; + logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + logic TransmitFIFOFull, TransmitFIFOEmpty; + logic TransmitFIFOWriteInc; + logic TransmitFIFOReadInc; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + logic [7:0] TransmitReadData; + // logic ReceiveFIFOWriteInc; - logic ReceiveFIFOReadIncrement; - logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; + logic ReceiveFIFOReadInc; + logic ReceiveFIFOFull, ReceiveFIFOEmpty; /* verilator lint_off UNDRIVEN */ logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs @@ -115,16 +117,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission) // Shift reg signals - logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg - logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg - logic [7:0] TransmitReg; // Transmit shift register + logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg + logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg + logic [7:0] TransmitReg; // Transmit shift register logic [7:0] ReceiveShiftReg; // Receive shift register logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB - logic TransmitLoad; // Determines when to load TransmitReg - logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + logic TransmitLoad; // Determines when to load TransmitReg + logic TransmitRegLoaded; // Shift stuff due to Format register? - logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) + logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) logic [3:0] LeftShiftAmount; // Determines left shift amount to left-align data when little endian logic [7:0] ASR; // AlignedReceiveShiftReg @@ -180,14 +182,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if (Memwrite) case(Entry) - SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0]; + SPI_TXDATA: if (~TransmitFIFOFull) TransmitData[7:0] <= Din[7:0]; endcase /* verilator lint_off CASEINCOMPLETE */ // According to FU540 spec: Once interrupt is pending, it will remain set until number // of entries in tx/rx fifo is strictly more/less than tx/rxmark InterruptPending[0] <= TransmitReadMark; - InterruptPending[1] <= RecieveWriteMark; + InterruptPending[1] <= ReceiveWriteMark; case(Entry) // Flop to sample inputs SPI_SCKDIV: Dout <= {20'b0, SckDiv}; @@ -198,8 +200,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( SPI_DELAY0: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]}; SPI_DELAY1: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]}; SPI_FMT: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0}; - SPI_TXDATA: Dout <= {TransmitFIFOWriteFull, 23'b0, 8'b0}; - SPI_RXDATA: Dout <= {ReceiveFIFOReadEmpty, 23'b0, ReceiveData[7:0]}; + SPI_TXDATA: Dout <= {TransmitFIFOFull, 23'b0, 8'b0}; + SPI_RXDATA: Dout <= {ReceiveFIFOEmpty, 23'b0, ReceiveData[7:0]}; SPI_TXMARK: Dout <= {29'b0, TransmitWatermark}; SPI_RXMARK: Dout <= {29'b0, ReceiveWatermark}; SPI_IE: Dout <= {30'b0, InterruptEnable}; @@ -208,11 +210,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase end - // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) - // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv - // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase - // When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). - // SPI Controller module ------------------------------------------- // This module controls state and timing signals that drive the rest of this module assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV); @@ -224,38 +221,40 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Register Inputs SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff - TransmitFIFOReadEmpty, + TransmitFIFOEmpty, // Timing - SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, EndOfFrameDelay, + SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, // State stuff Transmitting, InactiveState, // Outputs SPICLK); // Transmit FIFO --------------------------------------------------- + + // txFIFO write increment logic always_ff @(posedge PCLK) if (~PRESETn) begin - TransmitFIFOWriteIncrement <= 1'b0; + TransmitFIFOWriteInc <= 1'b0; end else begin - TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); + TransmitFIFOWriteInc <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull); end + // txFIFO read increment logic always_ff @(posedge PCLK) if (~PRESETn) begin - TransmitFIFOReadIncrement <= 1'b0; + TransmitFIFOReadInc <= 1'b0; end else if (SCLKenable) begin - TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; + TransmitFIFOReadInc <= TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty) ; 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 + end else if (ShiftEdge | EndOfFrame) begin TransmitRegLoaded <= 1'b0; end end @@ -272,7 +271,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // State machine for starting transmissions always_comb begin case (CurrState) - READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; + READY: if (~TransmitFIFOEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; WAIT: if (~Transmitting & ~TransmitRegLoaded) NextState = READY; @@ -288,42 +287,41 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( else if (SCLKenable) TransmitStartD <= 1'b0; spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, - TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, + TransmitFIFOWriteInc, TransmitFIFOReadInc, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], - TransmitFIFOReadData[7:0], - TransmitFIFOWriteFull, - TransmitFIFOReadEmpty, + TransmitReadData[7:0], + TransmitFIFOFull, + TransmitFIFOEmpty, TransmitWriteMark, TransmitReadMark); - // Receive FIFO ---------------------------------------------------- always_ff @(posedge PCLK) if (~PRESETn) begin - ReceiveFIFOReadIncrement <= 1'b0; + ReceiveFIFOReadInc <= 1'b0; end else begin - ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); + ReceiveFIFOReadInc <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc); end always_ff @(posedge PCLK) if (~PRESETn) begin ReceiveFIFOWriteInc <= 1'b0; end else if (SCLKenable) begin - ReceiveFIFOWriteInc <= EndOfFrameDelay; + ReceiveFIFOWriteInc <= EndOfFrame; end - + spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, - ReceiveFIFOWriteInc, ReceiveFIFOReadIncrement, + ReceiveFIFOWriteInc, ReceiveFIFOReadInc, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], - ReceiveFIFOWriteFull, - ReceiveFIFOReadEmpty, - RecieveWriteMark, RecieveReadMark); + ReceiveFIFOFull, + ReceiveFIFOEmpty, + ReceiveWriteMark, ReceiveReadMark); // Transmit shift register - assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~TransmitFIFOReadEmpty); - assign TransmitDataEndian = Format[0] ? {<<{TransmitFIFOReadData[7:0]}} : TransmitFIFOReadData[7:0]; + assign TransmitLoad = TransmitStart | (EndOfFrame & ~TransmitFIFOEmpty); + assign TransmitDataEndian = Format[0] ? {<<{TransmitReadData[7:0]}} : TransmitReadData[7:0]; always_ff @(posedge PCLK) if(~PRESETn) TransmitReg <= 8'b0; else if (TransmitLoad) TransmitReg <= TransmitDataEndian; diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 19b32cab3..0400d2956 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -51,8 +51,7 @@ module spi_controller ( output logic SCLKenable, output logic ShiftEdge, output logic SampleEdge, - output logic EndOfFrame, - output logic EndOfFrameDelay, + output logic EndOfFrame, output logic Transmitting, output logic InactiveState, output logic SPICLK @@ -63,43 +62,31 @@ module spi_controller ( localparam AUTOMODE = 2'b00; localparam OFFMODE = 2'b11; + // FSM States typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; statetype CurrState, NextState; // SCLKenable stuff logic [11:0] DivCounter; - // logic SCLKenable; - // logic SCLKenableEarly; - logic ZeroDiv; - logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK! - + logic SCK; // Shift and Sample Edges - logic PreShiftEdge; - logic PreSampleEdge; - // logic ShiftEdge; - // logic SampleEdge; + logic EdgePulse; logic ShiftEdgePulse; logic SampleEdgePulse; logic EndOfFramePulse; + logic PhaseOneOffset; // Frame stuff logic [3:0] BitNum; logic LastBit; - //logic EndOfFrame; - //logic EndOfFrameDelay; - logic PhaseOneOffset; // Transmit Stuff logic ContinueTransmit; - - // SPIOUT Stuff - // logic TransmitLoad; - logic [7:0] TransmitReg; - //logic Transmitting; logic EndTransmission; - - logic HoldMode; + logic ContinueTransmitD; // TODO: Could be replaced by TransmitRegLoaded? + logic NextEndDelay; + logic CurrentEndDelay; // Delay Stuff logic [7:0] cssck; @@ -116,13 +103,12 @@ module spi_controller ( logic EndOfSCKCS; logic EndOfINTERCS; logic EndOfINTERXFR; + logic EndOfDelay; - logic [7:0] CSSCKCounter; - logic [7:0] SCKCSCounter; - logic [7:0] INTERCSCounter; - logic [7:0] INTERXFRCounter; + logic [7:0] DelayCounter; logic DelayIsNext; + logic DelayState; // Convenient Delay Reg Names assign cssck = Delay0[7:0]; @@ -137,23 +123,25 @@ module spi_controller ( assign HasINTERXFR = interxfr > 8'b0; // Have we hit full delay for any of the delays? - assign EndOfCSSCK = CSSCKCounter == cssck; - assign EndOfSCKCS = SCKCSCounter == sckcs; - assign EndOfINTERCS = INTERCSCounter == intercs; - assign EndOfINTERXFR = INTERXFRCounter == interxfr; + assign EndOfCSSCK = (DelayCounter == cssck) & (CurrState == CSSCK); + assign EndOfSCKCS = (DelayCounter == sckcs) & (CurrState == SCKCS); + assign EndOfINTERCS = (DelayCounter == intercs) & (CurrState == INTERCS); + assign EndOfINTERXFR = (DelayCounter == interxfr) & (CurrState == INTERXFR); + + assign EndOfDelay = EndOfCSSCK | EndOfSCKCS | EndOfINTERCS | EndOfINTERXFR; // Clock Signal Stuff ----------------------------------------------- // I'm going to handle all clock stuff here, including ShiftEdge and // SampleEdge. This makes sure that SPICLK is an output of a register // and it properly synchronizes signals. - - assign SCLKenable = DivCounter == SckDiv; - // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; - assign LastBit = (BitNum == FrameLength - 4'b1); - //assign EndOfFrame = SCLKenable & LastBit & Transmitting; - assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay; - assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay; + // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) + // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv + // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase + assign SCLKenable = DivCounter == SckDiv; + + assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame; + assign EndTransmission = txFIFOReadEmpty & EndOfFrame; always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -161,13 +149,7 @@ module spi_controller ( SPICLK <= SckMode[1]; SCK <= 0; BitNum <= 4'h0; - PreShiftEdge <= 0; - PreSampleEdge <= 0; - EndOfFrame <= 0; - CSSCKCounter <= 0; - SCKCSCounter <= 0; - INTERCSCounter <= 0; - INTERXFRCounter <= 0; + DelayCounter <= 0; end else begin // TODO: Consolidate into one delay counter since none of the // delays happen at the same time? @@ -176,29 +158,12 @@ module spi_controller ( end else if (SCLKenable) begin SCK <= ~SCK; end - - if ((CurrState == CSSCK) & SCK & SCLKenable) begin - CSSCKCounter <= CSSCKCounter + 8'd1; - end else if (SCLKenable & EndOfCSSCK) begin - CSSCKCounter <= 8'd0; - end - - if ((CurrState == SCKCS) & SCK & SCLKenable) begin - SCKCSCounter <= SCKCSCounter + 8'd1; - end else if (SCLKenable & EndOfSCKCS) begin - SCKCSCounter <= 8'd0; - end - - if ((CurrState == INTERCS) & SCK & SCLKenable) begin - INTERCSCounter <= INTERCSCounter + 8'd1; - end else if (SCLKenable & EndOfINTERCS) begin - INTERCSCounter <= 8'd0; - end - - if ((CurrState == INTERXFR) & SCK & SCLKenable) begin - INTERXFRCounter <= INTERXFRCounter + 8'd1; - end else if (SCLKenable & EndOfINTERXFR) begin - INTERXFRCounter <= 8'd0; + + // Counter for all four delay types + if (DelayState & SCK & SCLKenable) begin + DelayCounter <= DelayCounter + 8'd1; + end else if (SCLKenable & EndOfDelay) begin + DelayCounter <= 8'd0; end // SPICLK Logic @@ -215,85 +180,70 @@ module spi_controller ( DivCounter <= DivCounter + 12'd1; end - // EndOfFrame controller - // if (SckDiv > 0 ? SCLKenableEarly & LastBit & SPICLK : LastBit & ~SPICLK) begin - // EndOfFrame <= 1'b1; - // end else begin - // EndOfFrame <= 1'b0; - // end - - // TODO: Rename EndOfFrameDelay to EndOfFrame and remove this logic - if (~TransmitStart) begin - EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; - end - // Increment BitNum if (ShiftEdge & Transmitting) begin BitNum <= BitNum + 4'd1; - end else if (EndOfFrameDelay) begin + end else if (EndOfFrame) begin BitNum <= 4'b0; end end end + // The very last bit in a frame of any length. + assign LastBit = (BitNum == FrameLength - 4'b1); + + // Any SCLKenable pulse aligns with leading or trailing edge during + // Transmission. We can use this signal as the basis for ShiftEdge + // and SampleEdge. + assign EdgePulse = SCLKenable & Transmitting; + + // Possible pulses for all edge types. Combined with SPICLK to get + // edges for different phase and polarity modes. + assign ShiftEdgePulse = EdgePulse & ~LastBit; + assign SampleEdgePulse = EdgePulse & ~DelayIsNext; + assign EndOfFramePulse = EdgePulse & LastBit; + // Delay ShiftEdge and SampleEdge by a half PCLK period // Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges. // Sweeeeeeeeeet... - - assign ShiftEdgePulse = SCLKenable & ~LastBit & Transmitting; - assign SampleEdgePulse = SCLKenable & Transmitting & ~DelayIsNext; - assign EndOfFramePulse = SCLKenable & LastBit & Transmitting; - always_ff @(posedge ~PCLK) begin if (~PRESETn | TransmitStart) begin ShiftEdge <= 0; PhaseOneOffset <= 0; SampleEdge <= 0; - EndOfFrameDelay <= 0; + EndOfFrame <= 0; end else begin - PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrame; case(SckMode) 2'b00: begin ShiftEdge <= SPICLK & ShiftEdgePulse; SampleEdge <= ~SPICLK & SampleEdgePulse; - EndOfFrameDelay <= SPICLK & EndOfFramePulse; + EndOfFrame <= SPICLK & EndOfFramePulse; end 2'b01: begin ShiftEdge <= ~SPICLK & ShiftEdgePulse & PhaseOneOffset; SampleEdge <= SPICLK & SampleEdgePulse; - EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; + EndOfFrame <= ~SPICLK & EndOfFramePulse; end 2'b10: begin ShiftEdge <= ~SPICLK & ShiftEdgePulse; SampleEdge <= SPICLK & SampleEdgePulse; - EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; + EndOfFrame <= ~SPICLK & EndOfFramePulse; end 2'b11: begin ShiftEdge <= SPICLK & ShiftEdgePulse & PhaseOneOffset; SampleEdge <= ~SPICLK & SampleEdgePulse; - EndOfFrameDelay <= SPICLK & EndOfFramePulse; + EndOfFrame <= SPICLK & EndOfFramePulse; end - // ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & 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; endcase end end - // typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; - // statetype CurrState, NextState; - - assign HoldMode = CSMode == HOLDMODE; - // assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); - - logic ContinueTransmitD; - logic NextEndDelay; - logic CurrentEndDelay; - + // Logic for continuing to transmit through Delay states after end of frame 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; @@ -326,7 +276,7 @@ module spi_controller ( case(CSMode) AUTOMODE: begin if (EndTransmission) NextState = INACTIVE; - else if (EndOfFrameDelay) NextState = SCKCS; + else if (EndOfFrame) NextState = SCKCS; else NextState = TRANSMIT; end HOLDMODE: begin @@ -386,6 +336,7 @@ module spi_controller ( assign Transmitting = CurrState == TRANSMIT; assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR); + assign DelayState = (CurrState == CSSCK | CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR); assign InactiveState = CurrState == INACTIVE | CurrState == INTERCS; endmodule From 120b21d7d5482a3b56a5d7073ff6a21cea8dd2e5 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 4 Nov 2024 15:38:12 -0600 Subject: [PATCH 2/3] More SPI optimizations. --- src/uncore/spi_apb.sv | 85 ++++++++++++++++-------------------- src/uncore/spi_controller.sv | 24 +++------- 2 files changed, 43 insertions(+), 66 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 38fa07f42..9b15839e7 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -48,7 +48,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( output logic SPICLK ); - // register map + // register map localparam SPI_SCKDIV = 8'h00; localparam SPI_SCKMODE = 8'h04; localparam SPI_CSID = 8'h10; @@ -89,7 +89,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic InactiveState; logic [3:0] FrameLength; - // + // Starting Transmission and restarting SCLKenable logic ResetSCLKenable; logic TransmitStart; logic TransmitStartD; @@ -98,15 +98,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( typedef enum logic [1:0] {READY, START, WAIT} txState; txState CurrState, NextState; - // FIFO FSM signals - // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] - logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + // FIFO Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] + logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + + // Transmit FIFO Signals logic TransmitFIFOFull, TransmitFIFOEmpty; logic TransmitFIFOWriteInc; logic TransmitFIFOReadInc; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read logic [7:0] TransmitReadData; - // + // ReceiveFIFO Signals logic ReceiveFIFOWriteInc; logic ReceiveFIFOReadInc; logic ReceiveFIFOFull, ReceiveFIFOEmpty; @@ -137,7 +138,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // APB access assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase - // assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP; assign PREADY = 1'b1; // Account for subword read/write circuitry @@ -164,7 +164,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( InterruptEnable <= 2'b0; InterruptPending <= 2'b0; end else begin // writes - /* verilator lint_off CASEINCOMPLETE */ + /* verilator lint_off CASEINCOMPLETE */ if (Memwrite) case(Entry) // flop to sample inputs SPI_SCKDIV: SckDiv <= Din[11:0]; @@ -217,7 +217,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( spi_controller controller(PCLK, PRESETn, // Transmit Signals - TransmitStart, TransmitStartD, ResetSCLKenable, + TransmitStart, TransmitRegLoaded, ResetSCLKenable, // Register Inputs SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff @@ -230,23 +230,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( SPICLK); // Transmit FIFO --------------------------------------------------- - + // txFIFO write increment logic - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOWriteInc <= 1'b0; - end else begin - TransmitFIFOWriteInc <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull); - end + flopr #(1) txwincreg(PCLK, ~PRESETn, + (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull), + TransmitFIFOWriteInc); // txFIFO read increment logic - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOReadInc <= 1'b0; - end else if (SCLKenable) begin - TransmitFIFOReadInc <= TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty) ; - end - + flopenr #(1) txrincreg(PCLK, ~PRESETn, SCLKenable, + TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty), + TransmitFIFOReadInc); + // Check whether TransmitReg has been loaded. // We use this signal to prevent returning to the Ready state for TransmitStart always_ff @(posedge PCLK) begin @@ -258,15 +252,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( TransmitRegLoaded <= 1'b0; end end - + // Setup TransmitStart state machine - always_ff @(posedge PCLK) begin - if (~PRESETn) begin - CurrState <= READY; - end else begin - CurrState <= NextState; - end - end + always_ff @(posedge PCLK) + if (~PRESETn) CurrState <= READY; + else CurrState <= NextState; // State machine for starting transmissions always_comb begin @@ -280,12 +270,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase end + // Delayed TransmitStart signal for incrementing tx read point. assign TransmitStart = (CurrState == START); always_ff @(posedge PCLK) if (~PRESETn) TransmitStartD <= 1'b0; else if (TransmitStart) TransmitStartD <= 1'b1; else if (SCLKenable) TransmitStartD <= 1'b0; - + + // Transmit FIFO spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteInc, TransmitFIFOReadInc, TransmitData[7:0], @@ -296,20 +288,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( TransmitWriteMark, TransmitReadMark); // Receive FIFO ---------------------------------------------------- - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOReadInc <= 1'b0; - end else begin - ReceiveFIFOReadInc <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc); - end - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOWriteInc <= 1'b0; - end else if (SCLKenable) begin - ReceiveFIFOWriteInc <= EndOfFrame; - end - + // Receive FIFO Read Increment register + flopr #(1) rxfiforincreg(PCLK, ~PRESETn, + ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc), + ReceiveFIFOReadInc); + + // Receive FIFO Write Increment register + flopenr #(1) rxfifowincreg(PCLK, ~PRESETn, SCLKenable, + EndOfFrame, ReceiveFIFOWriteInc); + + // Receive FIFO spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveFIFOWriteInc, ReceiveFIFOReadInc, ReceiveShiftRegEndian, ReceiveWatermark[2:0], @@ -319,6 +308,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( ReceiveFIFOEmpty, ReceiveWriteMark, ReceiveReadMark); + // Shift Registers -------------------------------------------------- // Transmit shift register assign TransmitLoad = TransmitStart | (EndOfFrame & ~TransmitFIFOEmpty); assign TransmitDataEndian = Format[0] ? {<<{TransmitReadData[7:0]}} : TransmitReadData[7:0]; @@ -340,12 +330,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if(~PRESETn) begin ReceiveShiftReg <= 8'b0; end else if (SampleEdge) begin - if (~Transmitting) ReceiveShiftReg <= 8'b0; - else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; + ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; end // Aligns received data and reverses if little-endian - assign LeftShiftAmount = 4'h8 - Format[4:1]; + assign LeftShiftAmount = 4'h8 - FrameLength; assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0]; assign ReceiveShiftRegEndian = Format[0] ? {<<{ASR[7:0]}} : ASR[7:0]; diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 0400d2956..475f9c1c9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -33,7 +33,7 @@ module spi_controller ( // Start Transmission input logic TransmitStart, - input logic TransmitStartD, + input logic TransmitRegLoaded, input logic ResetSCLKenable, // Registers @@ -84,7 +84,7 @@ module spi_controller ( // Transmit Stuff logic ContinueTransmit; logic EndTransmission; - logic ContinueTransmitD; // TODO: Could be replaced by TransmitRegLoaded? + // logic TransmitRegLoaded; // TODO: Could be replaced by TransmitRegLoaded? logic NextEndDelay; logic CurrentEndDelay; @@ -151,8 +151,7 @@ module spi_controller ( BitNum <= 4'h0; DelayCounter <= 0; end else begin - // TODO: Consolidate into one delay counter since none of the - // delays happen at the same time? + // SCK logic for delay times if (TransmitStart) begin SCK <= 0; end else if (SCLKenable) begin @@ -242,17 +241,6 @@ module spi_controller ( // Logic for continuing to transmit through Delay states after end of frame 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 @@ -264,7 +252,7 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: if (TransmitStartD) begin + INACTIVE: if (TransmitRegLoaded) begin if (~HasCSSCK) NextState = TRANSMIT; else NextState = CSSCK; end else begin @@ -294,7 +282,7 @@ module spi_controller ( end SCKCS: begin // SCKCS case -------------------------------------- if (EndOfSCKCS) begin - if (~ContinueTransmitD) begin + if (~TransmitRegLoaded) begin // if (CSMode == AUTOMODE) NextState = INACTIVE; if (CSMode == HOLDMODE) NextState = HOLD; else NextState = INACTIVE; @@ -309,7 +297,7 @@ module spi_controller ( HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin NextState = INACTIVE; - end else if (TransmitStartD) begin // If FIFO is written to, start again. + end else if (TransmitRegLoaded) begin // If FIFO is written to, start again. NextState = TRANSMIT; end else NextState = HOLD; end From 507c1dad1ce614934743776918d9149f2097f7ba Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 4 Nov 2024 16:15:42 -0600 Subject: [PATCH 3/3] Removed impossible condition in receive register logic. --- src/uncore/spi_controller.sv | 6 +++--- src/uncore/spi_fifo.sv | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 475f9c1c9..37c1e3ac9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -45,7 +45,7 @@ module spi_controller ( input logic [3:0] FrameLength, // Is the Transmit FIFO Empty? - input logic txFIFOReadEmpty, + input logic TransmitFIFOEmpty, // Control signals output logic SCLKenable, @@ -140,8 +140,8 @@ module spi_controller ( // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase assign SCLKenable = DivCounter == SckDiv; - assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame; - assign EndTransmission = txFIFOReadEmpty & EndOfFrame; + assign ContinueTransmit = ~TransmitFIFOEmpty & EndOfFrame; + assign EndTransmission = TransmitFIFOEmpty & EndOfFrame; always_ff @(posedge PCLK) begin if (~PRESETn) begin diff --git a/src/uncore/spi_fifo.sv b/src/uncore/spi_fifo.sv index 40c3ca4ff..1e4910faf 100644 --- a/src/uncore/spi_fifo.sv +++ b/src/uncore/spi_fifo.sv @@ -19,6 +19,10 @@ module spi_fifo #(parameter M=3, N=8)( // 2^M entries of N bits logic [M:0] rptrnext, wptrnext; logic [M-1:0] raddr; logic [M-1:0] waddr; + + logic [M-1:0] numVals; + + assign numVals = waddr - raddr; assign rdata = mem[raddr]; always_ff @(posedge PCLK)