diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 293c2c2b5..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; @@ -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; + // Starting Transmission and restarting SCLKenable logic ResetSCLKenable; logic TransmitStart; logic TransmitStartD; @@ -98,16 +98,19 @@ 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, RecieveWriteMark, RecieveReadMark; - logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; - logic TransmitFIFOWriteIncrement; - logic [7:0] TransmitFIFOReadData; + // 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 ReceiveFIFOReadIncrement; - logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; + logic ReceiveFIFOReadInc; + logic ReceiveFIFOFull, ReceiveFIFOEmpty; /* verilator lint_off UNDRIVEN */ logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs @@ -115,16 +118,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 @@ -135,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 @@ -162,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]; @@ -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); @@ -220,59 +217,51 @@ 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 - TransmitFIFOReadEmpty, + TransmitFIFOEmpty, // Timing - SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, EndOfFrameDelay, + SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, // State stuff Transmitting, InactiveState, // Outputs SPICLK); // Transmit FIFO --------------------------------------------------- - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOWriteIncrement <= 1'b0; - end else begin - TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); - end - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOReadIncrement <= 1'b0; - end else if (SCLKenable) begin - TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; - end + // txFIFO write increment logic + flopr #(1) txwincreg(PCLK, ~PRESETn, + (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull), + TransmitFIFOWriteInc); + // txFIFO read increment logic + 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 - 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 - + // 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 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; @@ -281,49 +270,48 @@ 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, - 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; - end else begin - ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); - end - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOWriteInc <= 1'b0; - end else if (SCLKenable) begin - ReceiveFIFOWriteInc <= EndOfFrameDelay; - 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, ReceiveFIFOReadIncrement, + ReceiveFIFOWriteInc, ReceiveFIFOReadInc, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], - ReceiveFIFOWriteFull, - ReceiveFIFOReadEmpty, - RecieveWriteMark, RecieveReadMark); + ReceiveFIFOFull, + ReceiveFIFOEmpty, + ReceiveWriteMark, ReceiveReadMark); + // Shift Registers -------------------------------------------------- // 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; @@ -342,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 19b32cab3..37c1e3ac9 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 @@ -45,14 +45,13 @@ module spi_controller ( input logic [3:0] FrameLength, // Is the Transmit FIFO Empty? - input logic txFIFOReadEmpty, + input logic TransmitFIFOEmpty, // Control signals 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 TransmitRegLoaded; // 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 = ~TransmitFIFOEmpty & EndOfFrame; + assign EndTransmission = TransmitFIFOEmpty & EndOfFrame; always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -161,44 +149,20 @@ 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? + // SCK logic for delay times if (TransmitStart) begin SCK <= 0; 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,95 +179,69 @@ 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; - 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; @@ -314,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 @@ -326,7 +264,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 @@ -344,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; @@ -359,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 @@ -386,6 +324,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 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)