mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	
						commit
						77338435ce
					
				@ -2,10 +2,14 @@
 | 
				
			|||||||
// spi_apb.sv
 | 
					// spi_apb.sv
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu 11/16/2022
 | 
					// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu 11/16/2022
 | 
				
			||||||
 | 
					 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Purpose: SPI peripheral
 | 
					// Purpose: SPI peripheral
 | 
				
			||||||
//   See FU540-C000-v1.0 for specifications
 | 
					//
 | 
				
			||||||
 | 
					// SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and recieve FIFOs connected to shift registers. 
 | 
				
			||||||
 | 
					// The FIFOs are connected to WALLY by an apb control register interface, which includes various control registers for modifying the SPI transmission along with registers for writing
 | 
				
			||||||
 | 
					// to the transmit FIFO and reading from the receive FIFO. The transmissions themselves are then controlled by a finite state machine. The SPI module uses 4 tristate pins for SPI input/output, 
 | 
				
			||||||
 | 
					// along with a 4 bit Chip Select signal, a clock signal, and an interrupt signal to WALLY.
 | 
				
			||||||
 | 
					// Current limitations: Flash read sequencer mode not implemented, dual and quad mode not supported
 | 
				
			||||||
// 
 | 
					// 
 | 
				
			||||||
// A component of the Wally configurable RISC-V project.
 | 
					// A component of the Wally configurable RISC-V project.
 | 
				
			||||||
// 
 | 
					// 
 | 
				
			||||||
@ -25,19 +29,6 @@
 | 
				
			|||||||
// and limitations under the License.
 | 
					// and limitations under the License.
 | 
				
			||||||
////////////////////////////////////////////////////////////////////////////////////////////////
 | 
					////////////////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Attempt to move from >= comparisons by initializing in FSM differently
 | 
					 | 
				
			||||||
// Parameterize SynchFIFO
 | 
					 | 
				
			||||||
// look at ReadIncrement/WriteIncrement delay necessity 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and recieve FIFOs connected to shift registers. 
 | 
					 | 
				
			||||||
The FIFOs are connected to WALLY by an apb control register interface, which includes various control registers for modifying the SPI transmission along with registers for writing
 | 
					 | 
				
			||||||
to the transmit FIFO and reading from the receive FIFO. The transmissions themselves are then controlled by a finite state machine. The SPI module uses 4 tristate pins for SPI input/output, 
 | 
					 | 
				
			||||||
along with a 4 bit Chip Select signal, a clock signal, and an interrupt signal to WALLY. 
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
					module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			||||||
    input  logic                PCLK, PRESETn,
 | 
					    input  logic                PCLK, PRESETn,
 | 
				
			||||||
    input  logic                PSEL,
 | 
					    input  logic                PSEL,
 | 
				
			||||||
@ -54,27 +45,27 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
    output logic                SPIIntr
 | 
					    output logic                SPIIntr
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //SPI control registers. Refer to SiFive FU540-C000 manual 
 | 
					    // SPI control registers. Refer to SiFive FU540-C000 manual 
 | 
				
			||||||
    logic [11:0] SckDiv;
 | 
					    logic [11:0] SckDiv;
 | 
				
			||||||
    logic [1:0] SckMode;
 | 
					    logic [1:0]  SckMode;
 | 
				
			||||||
    logic [1:0] ChipSelectID;
 | 
					    logic [1:0]  ChipSelectID;
 | 
				
			||||||
    logic [3:0] ChipSelectDef; 
 | 
					    logic [3:0]  ChipSelectDef; 
 | 
				
			||||||
    logic [1:0] ChipSelectMode;
 | 
					    logic [1:0]  ChipSelectMode;
 | 
				
			||||||
    logic [15:0] Delay0, Delay1;
 | 
					    logic [15:0] Delay0, Delay1;
 | 
				
			||||||
    logic [4:0] Format;
 | 
					    logic [4:0]  Format;
 | 
				
			||||||
    logic [7:0] ReceiveData;
 | 
					    logic [7:0]  ReceiveData;
 | 
				
			||||||
    logic [2:0] TransmitWatermark, ReceiveWatermark;
 | 
					    logic [2:0]  TransmitWatermark, ReceiveWatermark;
 | 
				
			||||||
    logic [8:0] TransmitData;
 | 
					    logic [8:0]  TransmitData;
 | 
				
			||||||
    logic [1:0] InterruptEnable, InterruptPending;
 | 
					    logic [1:0]  InterruptEnable, InterruptPending;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Bus interface signals
 | 
					    // Bus interface signals
 | 
				
			||||||
    logic [7:0] Entry;
 | 
					    logic [7:0] Entry;
 | 
				
			||||||
    logic Memwrite;
 | 
					    logic Memwrite;
 | 
				
			||||||
    logic [31:0] Din, Dout;
 | 
					    logic [31:0] Din, Dout;
 | 
				
			||||||
    logic TransmitInactive;                         //High when there is no transmission, used as hardware interlock signal
 | 
					    logic TransmitInactive;                         // High when there is no transmission, used as hardware interlock signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //FIFO FSM signals
 | 
					    // FIFO FSM signals
 | 
				
			||||||
    //Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
 | 
					    // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
 | 
				
			||||||
    logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; 
 | 
					    logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; 
 | 
				
			||||||
    logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
 | 
					    logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
 | 
				
			||||||
    logic TransmitFIFOReadIncrement;
 | 
					    logic TransmitFIFOReadIncrement;
 | 
				
			||||||
@ -83,75 +74,68 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
    logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
 | 
					    logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
 | 
				
			||||||
    logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
 | 
					    logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
 | 
				
			||||||
    logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
 | 
					    logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
 | 
				
			||||||
    logic [7:0] ReceiveShiftRegEndian;              //reverses ReceiveShiftReg if Format[2] set (little endian transmission)
 | 
					    logic [7:0] ReceiveShiftRegEndian;              // Reverses ReceiveShiftReg if Format[2] set (little endian transmission)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Transmission signals
 | 
					    // Transmission signals
 | 
				
			||||||
    logic sck;
 | 
					    logic sck;
 | 
				
			||||||
    logic [11:0] DivCounter;                        //counter for sck 
 | 
					    logic [11:0] DivCounter;                        // Counter for sck 
 | 
				
			||||||
    logic SCLKenable;                               //flip flop enable high every sclk edge
 | 
					    logic SCLKenable;                               // Flip flop enable high every sclk edge
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Delay signals
 | 
					    // Delay signals
 | 
				
			||||||
    logic [8:0] ImplicitDelay1;                     //Adds implicit delay to cs-sck delay counter based on phase  
 | 
					    logic [8:0] ImplicitDelay1;                     // Adds implicit delay to cs-sck delay counter based on phase  
 | 
				
			||||||
    logic [8:0] ImplicitDelay2;                     //Adds implicit delay to sck-cs delay counter based on phase 
 | 
					    logic [8:0] ImplicitDelay2;                     // Adds implicit delay to sck-cs delay counter based on phase 
 | 
				
			||||||
    logic [8:0] CS_SCKCount;                        //Counter for cs-sck delay
 | 
					    logic [8:0] CS_SCKCount;                        // Counter for cs-sck delay
 | 
				
			||||||
    logic [8:0] SCK_CSCount;                        //Counter for sck-cs delay
 | 
					    logic [8:0] SCK_CSCount;                        // Counter for sck-cs delay
 | 
				
			||||||
    logic [8:0] InterCSCount;                       //Counter for inter cs delay
 | 
					    logic [8:0] InterCSCount;                       // Counter for inter cs delay
 | 
				
			||||||
    logic [8:0] InterXFRCount;                      //Counter for inter xfr delay 
 | 
					    logic [8:0] InterXFRCount;                      // Counter for inter xfr delay 
 | 
				
			||||||
    logic CS_SCKCompare;                            //Boolean comparison signal, high when CS_SCKCount >= cs-sck delay
 | 
					    logic ZeroDelayHoldMode;                        // High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
 | 
				
			||||||
    logic SCK_CSCompare;                            //Boolean comparison signal, high when SCK_CSCount >= sck-cs delay
 | 
					 | 
				
			||||||
    logic InterCSCompare;                           //Boolean comparison signal, high when InterCSCount >= inter cs delay
 | 
					 | 
				
			||||||
    logic InterXFRCompare;                          //Boolean comparison signal, high when InterXFRCount >= inter xfr delay
 | 
					 | 
				
			||||||
    logic ZeroDelayHoldMode;                        //High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Frame counting signals
 | 
					    // Frame counting signals
 | 
				
			||||||
    logic [3:0] FrameCount;                         //Counter for number of frames in transmission
 | 
					    logic [3:0] FrameCount;                         // Counter for number of frames in transmission
 | 
				
			||||||
    logic FrameCompare;                             //Boolean comparison signal, high when FrameCount = Format[7:4]
 | 
					    logic [3:0] ReceivePenultimateFrameCount;       // Counter
 | 
				
			||||||
    logic [3:0] ReceivePenultimateFrame;            //Frame number - 1
 | 
					    logic ReceivePenultimateFrame;                  // High when penultimate frame in transmission has been reached
 | 
				
			||||||
    logic [3:0] ReceivePenultimateFrameCount;       //Counter
 | 
					 | 
				
			||||||
    logic ReceivePenultimateFrameBoolean;           //High when penultimate frame in transmission has been reached
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //State fsm signals
 | 
					    // State fsm signals
 | 
				
			||||||
    logic Active;                                   //High when state is either Active1 or Active0 (during transmission)
 | 
					    logic Active;                                   // High when state is either Active1 or Active0 (during transmission)
 | 
				
			||||||
    logic Active0;                                  //High when state is Active0
 | 
					    logic Active0;                                  // High when state is Active0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Shift reg signals
 | 
					    // Shift reg signals
 | 
				
			||||||
    logic ShiftEdge;                                //Determines which edge of sck to shift from TransmitShiftReg
 | 
					    logic ShiftEdge;                                // Determines which edge of sck to shift from TransmitShiftReg
 | 
				
			||||||
    logic [7:0] TransmitShiftReg;                   //Transmit shift register
 | 
					    logic [7:0] TransmitShiftReg;                   // Transmit shift register
 | 
				
			||||||
    logic [7:0] ReceiveShiftReg;                    //Receive shift register
 | 
					    logic [7:0] ReceiveShiftReg;                    // Receive shift register
 | 
				
			||||||
    logic SampleEdge;                               //Determines which edge of sck to sample from ReceiveShiftReg
 | 
					    logic SampleEdge;                               // Determines which edge of sck to sample from ReceiveShiftReg
 | 
				
			||||||
    logic [7:0] TransmitDataEndian;                 //Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
 | 
					    logic [7:0] TransmitDataEndian;                 // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
 | 
				
			||||||
    logic TransmitShiftRegLoad;                     //Determines when to load TransmitShiftReg
 | 
					    logic TransmitShiftRegLoad;                     // Determines when to load TransmitShiftReg
 | 
				
			||||||
    logic ReceiveShiftFull;                         //High when receive shift register is full
 | 
					    logic ReceiveShiftFull;                         // High when receive shift register is full
 | 
				
			||||||
    logic TransmitShiftEmpty;                       //High when transmit shift register is empty
 | 
					    logic TransmitShiftEmpty;                       // High when transmit shift register is empty
 | 
				
			||||||
    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 [3:0] LeftShiftAmount;                    // Determines left shift amount to left-align data when little endian              
 | 
				
			||||||
    logic [7:0] ASR;                                //AlignedReceiveShiftReg    
 | 
					    logic [7:0] ASR;                                // AlignedReceiveShiftReg    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //CS signals
 | 
					    // CS signals
 | 
				
			||||||
    logic [3:0] ChipSelectAuto;                     //Assigns ChipSelect value to selected CS signal based on CS ID
 | 
					    logic [3:0] ChipSelectAuto;                     // Assigns ChipSelect value to selected CS signal based on CS ID
 | 
				
			||||||
    logic [3:0] ChipSelectInternal;                 //Defines what each ChipSelect signal should be based on transmission status and ChipSelectDef
 | 
					    logic [3:0] ChipSelectInternal;                 // Defines what each ChipSelect signal should be based on transmission status and ChipSelectDef
 | 
				
			||||||
    logic DelayMode;                                //Determines where to place implicit half cycle delay based on sck phase for CS assertion
 | 
					    logic DelayMode;                                // Determines where to place implicit half cycle delay based on sck phase for CS assertion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Miscellaneous signals delayed/early by 1 PCLK cycle
 | 
					    // Miscellaneous signals delayed/early by 1 PCLK cycle
 | 
				
			||||||
    logic ReceiveShiftFullDelay;                    //Delays ReceiveShiftFull signal by 1 PCLK cycle
 | 
					    logic ReceiveShiftFullDelay;                    // Delays ReceiveShiftFull signal by 1 PCLK cycle
 | 
				
			||||||
    logic TransmitFIFOWriteIncrementDelay;          //TransmitFIFOWriteIncrement delayed by 1 PCLK cycle
 | 
					    logic ReceiveShiftFullDelayPCLK;                // ReceiveShiftFull delayed by 1 PCLK cycle
 | 
				
			||||||
    logic ReceiveShiftFullDelayPCLK;                //ReceiveShiftFull delayed by 1 PCLK cycle
 | 
					 | 
				
			||||||
    logic TransmitFIFOReadEmptyDelay;
 | 
					    logic TransmitFIFOReadEmptyDelay;
 | 
				
			||||||
    logic SCLKenableEarly;                          //SCLKenable 1 PCLK cycle early, needed for on time register changes when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
 | 
					    logic SCLKenableEarly;                          // SCLKenable 1 PCLK cycle early, needed for on time register changes when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //APB access
 | 
					    // APB access
 | 
				
			||||||
    assign Entry = {PADDR[7:2],2'b00};  // 32-bit word-aligned accesses
 | 
					    assign Entry = {PADDR[7:2],2'b00};  //  32-bit word-aligned accesses
 | 
				
			||||||
    assign Memwrite = PWRITE & PENABLE & PSEL;  // only write in access phase
 | 
					    assign Memwrite = PWRITE & PENABLE & PSEL;  // Only write in access phase
 | 
				
			||||||
    assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock
 | 
					    assign PREADY = TransmitInactive; // Tie PREADY to transmission for hardware interlock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Account for subword read/write circuitry
 | 
					    // Account for subword read/write circuitry
 | 
				
			||||||
    // -- Note SPI registers are 32 bits no matter what; access them with LW SW.
 | 
					    // -- Note SPI registers are 32 bits no matter what; access them with LW SW.
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
    assign Din = PWDATA[31:0]; 
 | 
					    assign Din = PWDATA[31:0]; 
 | 
				
			||||||
    if (P.XLEN == 64) assign PRDATA = {Dout, Dout}; 
 | 
					    if (P.XLEN == 64) assign PRDATA = {Dout, Dout}; 
 | 
				
			||||||
    else              assign PRDATA = Dout;  
 | 
					    else              assign PRDATA = Dout;  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Register access  
 | 
					    // Register access  
 | 
				
			||||||
    always_ff@(posedge PCLK, negedge PRESETn)
 | 
					    always_ff@(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) begin 
 | 
					        if (~PRESETn) begin 
 | 
				
			||||||
            SckDiv <= #1 12'd3;
 | 
					            SckDiv <= #1 12'd3;
 | 
				
			||||||
@ -167,13 +151,12 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
            ReceiveWatermark <= #1 3'b0;
 | 
					            ReceiveWatermark <= #1 3'b0;
 | 
				
			||||||
            InterruptEnable <= #1 2'b0;
 | 
					            InterruptEnable <= #1 2'b0;
 | 
				
			||||||
            InterruptPending <= #1 2'b0;
 | 
					            InterruptPending <= #1 2'b0;
 | 
				
			||||||
        end else begin //writes
 | 
					        end else begin // writes
 | 
				
			||||||
            //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
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* verilator lint_off CASEINCOMPLETE */
 | 
					            /* verilator lint_off CASEINCOMPLETE */
 | 
				
			||||||
            if (Memwrite & TransmitInactive)
 | 
					            if (Memwrite & TransmitInactive)
 | 
				
			||||||
                case(Entry) //flop to sample inputs
 | 
					                case(Entry) // flop to sample inputs
 | 
				
			||||||
                    8'h00: SckDiv <= Din[11:0];
 | 
					                    8'h00: SckDiv <= Din[11:0];
 | 
				
			||||||
                    8'h04: SckMode <= Din[1:0];
 | 
					                    8'h04: SckMode <= Din[1:0];
 | 
				
			||||||
                    8'h10: ChipSelectID <= Din[1:0];
 | 
					                    8'h10: ChipSelectID <= Din[1:0];
 | 
				
			||||||
@ -188,18 +171,21 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
                    8'h70: InterruptEnable <= Din[1:0];
 | 
					                    8'h70: InterruptEnable <= Din[1:0];
 | 
				
			||||||
                endcase
 | 
					                endcase
 | 
				
			||||||
            /* verilator lint_off CASEINCOMPLETE */
 | 
					            /* verilator lint_off CASEINCOMPLETE */
 | 
				
			||||||
            //interrupt clearance
 | 
					
 | 
				
			||||||
 | 
					            // 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[0] <= TransmitReadMark;
 | 
				
			||||||
            InterruptPending[1] <= RecieveWriteMark;  
 | 
					            InterruptPending[1] <= RecieveWriteMark;  
 | 
				
			||||||
            case(Entry) // flop to sample inputs
 | 
					
 | 
				
			||||||
 | 
					            case(Entry) // Flop to sample inputs
 | 
				
			||||||
                8'h00: Dout <= #1 {20'b0, SckDiv};
 | 
					                8'h00: Dout <= #1 {20'b0, SckDiv};
 | 
				
			||||||
                8'h04: Dout <= #1 {30'b0, SckMode};
 | 
					                8'h04: Dout <= #1 {30'b0, SckMode};
 | 
				
			||||||
                8'h10: Dout <= #1 {30'b0, ChipSelectID};
 | 
					                8'h10: Dout <= #1 {30'b0, ChipSelectID};
 | 
				
			||||||
                8'h14: Dout <= #1 {28'b0, ChipSelectDef};
 | 
					                8'h14: Dout <= #1 {28'b0, ChipSelectDef};
 | 
				
			||||||
                8'h18: Dout <= #1 {30'b0, ChipSelectMode};
 | 
					                8'h18: Dout <= #1 {30'b0, ChipSelectMode};
 | 
				
			||||||
                8'h28: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]};
 | 
					                8'h28: Dout <= #1 {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]};
 | 
				
			||||||
                8'h2C: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]};
 | 
					                8'h2C: Dout <= #1 {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]};
 | 
				
			||||||
                8'h40: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0};
 | 
					                8'h40: Dout <= #1 {12'b0, Format[4:1], 13'b0, Format[0], 2'b0};
 | 
				
			||||||
                8'h48: Dout <= #1 {23'b0, TransmitFIFOWriteFull, 8'b0};
 | 
					                8'h48: Dout <= #1 {23'b0, TransmitFIFOWriteFull, 8'b0};
 | 
				
			||||||
                8'h4C: Dout <= #1 {23'b0, ReceiveFIFOReadEmpty, ReceiveData[7:0]};
 | 
					                8'h4C: Dout <= #1 {23'b0, ReceiveFIFOReadEmpty, ReceiveData[7:0]};
 | 
				
			||||||
                8'h50: Dout <= #1 {29'b0, TransmitWatermark};
 | 
					                8'h50: Dout <= #1 {29'b0, TransmitWatermark};
 | 
				
			||||||
@ -210,8 +196,9 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
            endcase
 | 
					            endcase
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
 | 
					    // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
 | 
				
			||||||
    //Generates a high signal at the rising and falling edge of SCLK by counting from 0 to SckDiv
 | 
					    // 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 SCLKenable = (DivCounter == SckDiv);
 | 
				
			||||||
    assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
 | 
					    assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
@ -219,44 +206,38 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
        else if (SCLKenable) DivCounter <= 0;
 | 
					        else if (SCLKenable) DivCounter <= 0;
 | 
				
			||||||
        else DivCounter <= DivCounter + 12'b1;
 | 
					        else DivCounter <= DivCounter + 12'b1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Boolean logic that tracks frame progression
 | 
					    // Asserts when transmission is one frame before complete
 | 
				
			||||||
    assign FrameCompare = (FrameCount < Format[4:1]);    
 | 
					    assign ReceivePenultimateFrame = ((FrameCount + 4'b0001) == Format[4:1]);
 | 
				
			||||||
    assign ReceivePenultimateFrameBoolean = ((FrameCount + 4'b0001) == Format[4:1]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Computing delays
 | 
					    // Computing delays
 | 
				
			||||||
    // When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs
 | 
					    // When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs
 | 
				
			||||||
    assign ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1;
 | 
					    assign ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1;
 | 
				
			||||||
    assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0;
 | 
					    assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assign CS_SCKCompare = CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1);
 | 
					    // Calculate when tx/rx shift registers are full/empty
 | 
				
			||||||
    assign SCK_CSCompare = SCK_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2);
 | 
					    TransmitShiftFSM TransmitShiftFSM(PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrame, Active0, TransmitShiftEmpty);
 | 
				
			||||||
    assign InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0}));
 | 
					    ReceiveShiftFSM ReceiveShiftFSM(PCLK, PRESETn, SCLKenable, ReceivePenultimateFrame, SampleEdge, SckMode[0], ReceiveShiftFull);
 | 
				
			||||||
    assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 1'b0}));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Calculate when tx/rx shift registers are full/empty
 | 
					    // Calculate tx/rx fifo write and recieve increment signals 
 | 
				
			||||||
    TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty);
 | 
					 | 
				
			||||||
    ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKenable, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //Calculate tx/rx fifo write and recieve increment signals 
 | 
					 | 
				
			||||||
    assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0;
 | 
					        if (~PRESETn) TransmitFIFOWriteIncrement <= 0;
 | 
				
			||||||
        else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement;
 | 
					        else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
 | 
					        if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
 | 
				
			||||||
        else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
 | 
					        else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    //Tx/Rx FIFOs
 | 
					    // Tx/Rx FIFOs
 | 
				
			||||||
    SynchFIFO #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
 | 
					    SynchFIFO #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0],
 | 
				
			||||||
    SynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
 | 
					                            TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
 | 
				
			||||||
 | 
					    SynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, 
 | 
				
			||||||
 | 
					                            ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
 | 
					        if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
 | 
				
			||||||
        else  if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
 | 
					        else  if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) ReceiveShiftFullDelay <= 0;
 | 
					        if (~PRESETn) ReceiveShiftFullDelay <= 0;
 | 
				
			||||||
        else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
 | 
					        else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
 | 
				
			||||||
@ -266,16 +247,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
 | 
					    assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Main FSM which controls SPI transmission
 | 
					    // Main FSM which controls SPI transmission
 | 
				
			||||||
    typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype;
 | 
					    typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype;
 | 
				
			||||||
    statetype state;
 | 
					    statetype state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) begin state <= CS_INACTIVE;
 | 
					        if (~PRESETn) begin 
 | 
				
			||||||
 | 
					                        state <= CS_INACTIVE;
 | 
				
			||||||
                        FrameCount <= 4'b0;                      
 | 
					                        FrameCount <= 4'b0;                      
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* verilator lint_off CASEINCOMPLETE */
 | 
					 | 
				
			||||||
        end else if (SCLKenable) begin
 | 
					        end else if (SCLKenable) begin
 | 
				
			||||||
 | 
					            /* verilator lint_off CASEINCOMPLETE */
 | 
				
			||||||
            case (state)
 | 
					            case (state)
 | 
				
			||||||
                CS_INACTIVE: begin
 | 
					                CS_INACTIVE: begin
 | 
				
			||||||
                        CS_SCKCount <= 9'b1;
 | 
					                        CS_SCKCount <= 9'b1;
 | 
				
			||||||
@ -288,7 +269,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
                        end
 | 
					                        end
 | 
				
			||||||
                DELAY_0: begin
 | 
					                DELAY_0: begin
 | 
				
			||||||
                        CS_SCKCount <= CS_SCKCount + 9'b1;
 | 
					                        CS_SCKCount <= CS_SCKCount + 9'b1;
 | 
				
			||||||
                        if (CS_SCKCompare) state <= ACTIVE_0;
 | 
					                        if (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1)) state <= ACTIVE_0;
 | 
				
			||||||
                        end
 | 
					                        end
 | 
				
			||||||
                ACTIVE_0: begin 
 | 
					                ACTIVE_0: begin 
 | 
				
			||||||
                        FrameCount <= FrameCount + 4'b1;
 | 
					                        FrameCount <= FrameCount + 4'b1;
 | 
				
			||||||
@ -296,7 +277,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
                        end
 | 
					                        end
 | 
				
			||||||
                ACTIVE_1: begin
 | 
					                ACTIVE_1: begin
 | 
				
			||||||
                        InterXFRCount <= 9'b1;
 | 
					                        InterXFRCount <= 9'b1;
 | 
				
			||||||
                        if (FrameCompare) state <= ACTIVE_0;
 | 
					                        if (FrameCount < Format[4:1]) state <= ACTIVE_0;
 | 
				
			||||||
                        else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
 | 
					                        else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
 | 
				
			||||||
                            state <= ACTIVE_0;
 | 
					                            state <= ACTIVE_0;
 | 
				
			||||||
                            CS_SCKCount <= 9'b1;
 | 
					                            CS_SCKCount <= 9'b1;
 | 
				
			||||||
@ -310,11 +291,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
                        end
 | 
					                        end
 | 
				
			||||||
                DELAY_1: begin
 | 
					                DELAY_1: begin
 | 
				
			||||||
                        SCK_CSCount <= SCK_CSCount + 9'b1;
 | 
					                        SCK_CSCount <= SCK_CSCount + 9'b1;
 | 
				
			||||||
                        if (SCK_CSCompare) state <= INTER_CS;
 | 
					                        if (SCK_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2)) state <= INTER_CS;
 | 
				
			||||||
                        end
 | 
					                        end
 | 
				
			||||||
                INTER_CS: begin
 | 
					                INTER_CS: begin
 | 
				
			||||||
                        InterCSCount <= InterCSCount + 9'b1;
 | 
					                        InterCSCount <= InterCSCount + 9'b1;
 | 
				
			||||||
                        if (InterCSCompare ) state <= CS_INACTIVE;
 | 
					                        if (InterCSCount >= ({Delay1[7:0],1'b0})) state <= CS_INACTIVE;
 | 
				
			||||||
                        end
 | 
					                        end
 | 
				
			||||||
                INTER_XFR: begin
 | 
					                INTER_XFR: begin
 | 
				
			||||||
                        CS_SCKCount <= 9'b1;
 | 
					                        CS_SCKCount <= 9'b1;
 | 
				
			||||||
@ -322,13 +303,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
                        FrameCount <= 4'b0;
 | 
					                        FrameCount <= 4'b0;
 | 
				
			||||||
                        InterCSCount <= 9'b10;
 | 
					                        InterCSCount <= 9'b10;
 | 
				
			||||||
                        InterXFRCount <= InterXFRCount + 9'b1;
 | 
					                        InterXFRCount <= InterXFRCount + 9'b1;
 | 
				
			||||||
                        if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
 | 
					                        if ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
 | 
				
			||||||
                        else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
 | 
					                        else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
 | 
				
			||||||
                        end
 | 
					                        end
 | 
				
			||||||
            endcase
 | 
					            endcase
 | 
				
			||||||
 | 
					            /* verilator lint_off CASEINCOMPLETE */
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* verilator lint_off CASEINCOMPLETE */
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
 | 
					    assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
 | 
				
			||||||
    assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
 | 
					    assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
 | 
				
			||||||
@ -339,7 +321,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
    assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
 | 
					    assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
 | 
				
			||||||
    assign Active0 = (state == ACTIVE_0);
 | 
					    assign Active0 = (state == ACTIVE_0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Signal tracks which edge of sck to shift data
 | 
					    // Signal tracks which edge of sck to shift data
 | 
				
			||||||
    always_comb
 | 
					    always_comb
 | 
				
			||||||
        case(SckMode[1:0])
 | 
					        case(SckMode[1:0])
 | 
				
			||||||
            2'b00: ShiftEdge = ~sck & SCLKenable;
 | 
					            2'b00: ShiftEdge = ~sck & SCLKenable;
 | 
				
			||||||
@ -349,36 +331,36 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
            default: ShiftEdge = sck & SCLKenable;
 | 
					            default: ShiftEdge = sck & SCLKenable;
 | 
				
			||||||
        endcase
 | 
					        endcase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Transmit shift register
 | 
					    // Transmit shift register
 | 
				
			||||||
    assign TransmitDataEndian =  Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0];
 | 
					    assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0];
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if(~PRESETn)                        TransmitShiftReg <= 8'b0; 
 | 
					        if(~PRESETn)                        TransmitShiftReg <= 8'b0; 
 | 
				
			||||||
        else if (TransmitShiftRegLoad)      TransmitShiftReg <= TransmitDataEndian;
 | 
					        else if (TransmitShiftRegLoad)      TransmitShiftReg <= TransmitDataEndian;
 | 
				
			||||||
        else if (ShiftEdge & Active)   TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
 | 
					        else if (ShiftEdge & Active)        TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    assign SPIOut = TransmitShiftReg[7];
 | 
					    assign SPIOut = TransmitShiftReg[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn
 | 
					    // If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn
 | 
				
			||||||
    //There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges
 | 
					    // There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges
 | 
				
			||||||
    assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
 | 
					    assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Receive shift register
 | 
					    // Receive shift register
 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if(~PRESETn)  ReceiveShiftReg <= 8'b0;
 | 
					        if(~PRESETn)  ReceiveShiftReg <= 8'b0;
 | 
				
			||||||
        else if (SampleEdge & SCLKenable) begin
 | 
					        else if (SampleEdge & SCLKenable) begin
 | 
				
			||||||
            if (~Active) ReceiveShiftReg <= 8'b0;
 | 
					            if (~Active)    ReceiveShiftReg <= 8'b0;
 | 
				
			||||||
            else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
 | 
					            else            ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Aligns received data and reverses if little-endian
 | 
					    // Aligns received data and reverses if little-endian
 | 
				
			||||||
    assign LeftShiftAmount = 4'h8 - Format[4:1];
 | 
					    assign LeftShiftAmount = 4'h8 - Format[4:1];
 | 
				
			||||||
    assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
 | 
					    assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
 | 
				
			||||||
    assign ReceiveShiftRegEndian = Format[0] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0];
 | 
					    assign ReceiveShiftRegEndian = Format[0] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Interrupt logic: raise interrupt if any enabled interrupts are pending
 | 
					    // Interrupt logic: raise interrupt if any enabled interrupts are pending
 | 
				
			||||||
    assign SPIIntr = |(InterruptPending & InterruptEnable);
 | 
					    assign SPIIntr = |(InterruptPending & InterruptEnable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Chip select logic
 | 
					    // Chip select logic
 | 
				
			||||||
    always_comb
 | 
					    always_comb
 | 
				
			||||||
        case(ChipSelectID[1:0])
 | 
					        case(ChipSelectID[1:0])
 | 
				
			||||||
            2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
 | 
					            2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
 | 
				
			||||||
@ -390,14 +372,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
				
			|||||||
    assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
 | 
					    assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module SynchFIFO #(parameter M =3 , N= 8)(
 | 
					module SynchFIFO #(parameter M=3, N=8)(                 // 2^M entries of N bits each
 | 
				
			||||||
    input logic PCLK, wen, ren, PRESETn,
 | 
					    input  logic         PCLK, wen, ren, PRESETn,
 | 
				
			||||||
    input logic winc,rinc,
 | 
					    input  logic         winc, rinc,
 | 
				
			||||||
    input logic [N-1:0] wdata,
 | 
					    input  logic [N-1:0] wdata,
 | 
				
			||||||
    input logic [M-1:0] wwatermarklevel, rwatermarklevel,
 | 
					    input  logic [M-1:0] wwatermarklevel, rwatermarklevel,
 | 
				
			||||||
    output logic [N-1:0] rdata,
 | 
					    output logic [N-1:0] rdata,
 | 
				
			||||||
    output logic wfull, rempty,
 | 
					    output logic         wfull, rempty,
 | 
				
			||||||
    output logic wwatermark, rwatermark);
 | 
					    output logic         wwatermark, rwatermark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Pointer FIFO using design elements from "Simulation and Synthesis Techniques
 | 
					    /* Pointer FIFO using design elements from "Simulation and Synthesis Techniques
 | 
				
			||||||
       for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers
 | 
					       for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers
 | 
				
			||||||
@ -409,8 +391,6 @@ module SynchFIFO #(parameter M =3 , N= 8)(
 | 
				
			|||||||
    logic [N-1:0] mem[2**M];
 | 
					    logic [N-1:0] mem[2**M];
 | 
				
			||||||
    logic [M:0] rptr, wptr;
 | 
					    logic [M:0] rptr, wptr;
 | 
				
			||||||
    logic [M:0] rptrnext, wptrnext;
 | 
					    logic [M:0] rptrnext, wptrnext;
 | 
				
			||||||
    logic rempty_val;
 | 
					 | 
				
			||||||
    logic wfull_val;
 | 
					 | 
				
			||||||
    logic [M-1:0] raddr;
 | 
					    logic [M-1:0] raddr;
 | 
				
			||||||
    logic [M-1:0] waddr;
 | 
					    logic [M-1:0] waddr;
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
@ -428,53 +408,43 @@ module SynchFIFO #(parameter M =3 , N= 8)(
 | 
				
			|||||||
        end
 | 
					        end
 | 
				
			||||||
        else begin 
 | 
					        else begin 
 | 
				
			||||||
            if (wen) begin
 | 
					            if (wen) begin
 | 
				
			||||||
                wfull <= wfull_val;
 | 
					                wfull <= ({~wptrnext[M], wptrnext[M-1:0]} == rptr);
 | 
				
			||||||
                wptr  <= wptrnext;
 | 
					                wptr  <= wptrnext;
 | 
				
			||||||
            end
 | 
					            end
 | 
				
			||||||
            if (ren) begin 
 | 
					            if (ren) begin 
 | 
				
			||||||
                rptr <= rptrnext;
 | 
					                rptr <= rptrnext;
 | 
				
			||||||
                rempty <= rempty_val;
 | 
					                rempty <= (wptr == rptrnext);
 | 
				
			||||||
            end
 | 
					            end
 | 
				
			||||||
        end 
 | 
					        end 
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    assign raddr = rptr[M-1:0];
 | 
					    assign raddr = rptr[M-1:0];
 | 
				
			||||||
    assign rptrnext = rptr + {3'b0, (rinc & ~rempty)};      
 | 
					    assign rptrnext = rptr + {{(M){1'b0}}, (rinc & ~rempty)};      
 | 
				
			||||||
    assign rempty_val = (wptr == rptrnext);
 | 
					 | 
				
			||||||
    assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull;
 | 
					    assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull;
 | 
				
			||||||
    assign waddr = wptr[M-1:0];
 | 
					    assign waddr = wptr[M-1:0];
 | 
				
			||||||
    assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull;
 | 
					    assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull;
 | 
				
			||||||
    assign wptrnext = wptr + {3'b0, (winc & ~wfull)};
 | 
					    assign wptrnext = wptr + {{(M){1'b0}}, (winc & ~wfull)};
 | 
				
			||||||
    assign wfull_val = ({~wptrnext[M], wptrnext[M-1:0]} == rptr);
 | 
					 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module TransmitShiftFSM(
 | 
					module TransmitShiftFSM(
 | 
				
			||||||
    input logic PCLK, PRESETn,
 | 
					    input  logic PCLK, PRESETn,
 | 
				
			||||||
    input logic TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0,
 | 
					    input  logic TransmitFIFOReadEmpty, ReceivePenultimateFrame, Active0,
 | 
				
			||||||
    output logic TransmitShiftEmpty);
 | 
					    output logic TransmitShiftEmpty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef enum logic [1:0] {TransmitShiftEmptyState, TransmitShiftHoldState, TransmitShiftNotEmptyState} statetype;
 | 
					 | 
				
			||||||
    statetype TransmitState, TransmitNextState;
 | 
					 | 
				
			||||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
					    always_ff @(posedge PCLK, negedge PRESETn)
 | 
				
			||||||
        if (~PRESETn) TransmitState <= TransmitShiftEmptyState;
 | 
					        if (~PRESETn) TransmitShiftEmpty <= 1;
 | 
				
			||||||
        else          TransmitState <= TransmitNextState;
 | 
					        else if (TransmitShiftEmpty) begin        
 | 
				
			||||||
 | 
					            if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrame & Active0))) TransmitShiftEmpty <= 1;
 | 
				
			||||||
 | 
					            else if (~TransmitFIFOReadEmpty) TransmitShiftEmpty <= 0;
 | 
				
			||||||
 | 
					        end else begin
 | 
				
			||||||
 | 
					            if (ReceivePenultimateFrame & Active0) TransmitShiftEmpty <= 1;
 | 
				
			||||||
 | 
					            else TransmitShiftEmpty <= 0;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        always_comb
 | 
					 | 
				
			||||||
            case(TransmitState)
 | 
					 | 
				
			||||||
                TransmitShiftEmptyState: begin
 | 
					 | 
				
			||||||
                    if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrameBoolean & Active0))) TransmitNextState = TransmitShiftEmptyState;
 | 
					 | 
				
			||||||
                    else if (~TransmitFIFOReadEmpty) TransmitNextState = TransmitShiftNotEmptyState;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
                TransmitShiftNotEmptyState: begin
 | 
					 | 
				
			||||||
                    if (ReceivePenultimateFrameBoolean & Active0) TransmitNextState = TransmitShiftEmptyState;
 | 
					 | 
				
			||||||
                    else TransmitNextState = TransmitShiftNotEmptyState;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            endcase
 | 
					 | 
				
			||||||
        assign TransmitShiftEmpty = (TransmitNextState == TransmitShiftEmptyState);
 | 
					 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module ReceiveShiftFSM(
 | 
					module ReceiveShiftFSM(
 | 
				
			||||||
    input logic PCLK, PRESETn, SCLKenable,
 | 
					    input  logic PCLK, PRESETn, SCLKenable,
 | 
				
			||||||
    input logic ReceivePenultimateFrameBoolean, SampleEdge, SckMode,
 | 
					    input  logic ReceivePenultimateFrame, SampleEdge, SckMode,
 | 
				
			||||||
    output logic ReceiveShiftFull
 | 
					    output logic ReceiveShiftFull
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
    typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} statetype;
 | 
					    typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} statetype;
 | 
				
			||||||
@ -484,17 +454,12 @@ module ReceiveShiftFSM(
 | 
				
			|||||||
        else if (SCLKenable) begin
 | 
					        else if (SCLKenable) begin
 | 
				
			||||||
            case (ReceiveState)
 | 
					            case (ReceiveState)
 | 
				
			||||||
                ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState;
 | 
					                ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState;
 | 
				
			||||||
                ReceiveShiftNotFullState: if (ReceivePenultimateFrameBoolean & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState;
 | 
					                ReceiveShiftNotFullState: if (ReceivePenultimateFrame & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState;
 | 
				
			||||||
                                          else ReceiveState <= ReceiveShiftNotFullState;
 | 
					                                          else ReceiveState <= ReceiveShiftNotFullState;
 | 
				
			||||||
                ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState;
 | 
					                ReceiveShiftDelayState:   ReceiveState <= ReceiveShiftFullState;
 | 
				
			||||||
            endcase
 | 
					            endcase
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assign ReceiveShiftFull = SckMode ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState);
 | 
					    assign ReceiveShiftFull = SckMode ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState);
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user