mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									674d008f23
								
							
						
					
					
						commit
						a9e6962cd4
					
				| @ -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; | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user