mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge branch 'main' of https://github.com/openhwgroup/cvw into dev
This commit is contained in:
		
						commit
						c5b12b7331
					
				@ -27,10 +27,8 @@
 | 
			
		||||
 | 
			
		||||
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
 | 
			
		||||
 | 
			
		||||
// Comment on FIFOs: watermark calculations
 | 
			
		||||
// Comment all interface and internal signals on the lines they are declared
 | 
			
		||||
// Get tabs correct so things line up
 | 
			
		||||
// Relook at frame compare/ Delay count logic w/o multibit 
 | 
			
		||||
// Attempt to move from >= comparisons by initializing in FSM differently
 | 
			
		||||
// Parameterize SynchFIFO
 | 
			
		||||
// look at ReadIncrement/WriteIncrement delay necessity 
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
@ -56,8 +54,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
    output logic                SPIIntr
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
    //SPI registers
 | 
			
		||||
 | 
			
		||||
    //SPI control registers. Refer to SiFive FU540-C000 manual 
 | 
			
		||||
    logic [11:0] SckDiv;
 | 
			
		||||
    logic [1:0] SckMode;
 | 
			
		||||
    logic [1:0] ChipSelectID;
 | 
			
		||||
@ -65,102 +62,96 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
    logic [1:0] ChipSelectMode;
 | 
			
		||||
    logic [15:0] Delay0, Delay1;
 | 
			
		||||
    logic [4:0] Format;
 | 
			
		||||
    logic [8:0] ReceiveData;
 | 
			
		||||
    logic [8:0] ReceiveDataPlaceholder;
 | 
			
		||||
    logic [7:0] ReceiveData;
 | 
			
		||||
    logic [2:0] TransmitWatermark, ReceiveWatermark;
 | 
			
		||||
    logic [8:0] TransmitData;
 | 
			
		||||
    logic [1:0] InterruptEnable, InterruptPending;
 | 
			
		||||
 | 
			
		||||
    //bus interface signals
 | 
			
		||||
    //Bus interface signals
 | 
			
		||||
    logic [7:0] Entry;
 | 
			
		||||
    logic Memwrite;
 | 
			
		||||
    logic [31:0] Din, Dout;
 | 
			
		||||
    logic TransmitInactive;                         //High when there is no transmission, used as hardware interlock signal
 | 
			
		||||
 | 
			
		||||
    //FIFO FSM signals
 | 
			
		||||
    //Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
 | 
			
		||||
    logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; 
 | 
			
		||||
    logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
 | 
			
		||||
    logic TransmitFIFOReadIncrement;
 | 
			
		||||
    logic TransmitFIFOWriteIncrement;
 | 
			
		||||
    logic ReceiveFIFOReadIncrement;
 | 
			
		||||
 | 
			
		||||
    logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
 | 
			
		||||
    logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
 | 
			
		||||
    logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
 | 
			
		||||
    logic [7:0] ReceiveShiftRegEndian;              //reverses ReceiveShiftReg if Format[2] set (little endian transmission)
 | 
			
		||||
 | 
			
		||||
    logic TransmitFIFOReadEmptyDelay;
 | 
			
		||||
    logic [7:0] ReceiveShiftRegEndian;
 | 
			
		||||
 | 
			
		||||
    //transmission signals
 | 
			
		||||
    //Transmission signals
 | 
			
		||||
    logic sck;
 | 
			
		||||
    logic [11:0] DivCounter;
 | 
			
		||||
    logic SCLKenable;
 | 
			
		||||
    logic [8:0] Delay0Count;
 | 
			
		||||
    logic [8:0] Delay1Count;
 | 
			
		||||
    logic Delay0Compare;
 | 
			
		||||
    logic Delay1Compare;
 | 
			
		||||
    logic InterCSCompare;
 | 
			
		||||
    logic [8:0] InterCSCount;
 | 
			
		||||
    logic InterXFRCompare;
 | 
			
		||||
    logic [8:0] InterXFRCount;
 | 
			
		||||
    logic [3:0] ChipSelectInternal;
 | 
			
		||||
    logic [4:0] FrameCount;
 | 
			
		||||
    logic [4:0] FrameCompare;
 | 
			
		||||
    logic [11:0] DivCounter;                        //counter for sck 
 | 
			
		||||
    logic SCLKenable;                               //flip flop enable high every sclk edge
 | 
			
		||||
 | 
			
		||||
    logic FrameCompareBoolean;
 | 
			
		||||
    logic [4:0] ReceivePenultimateFrame;
 | 
			
		||||
    logic [4:0] ReceivePenultimateFrameCount;
 | 
			
		||||
    logic ReceivePenultimateFrameBoolean;
 | 
			
		||||
    logic [4:0] FrameCompareProtocol;
 | 
			
		||||
    logic ReceiveShiftFull;
 | 
			
		||||
    logic TransmitShiftEmpty;
 | 
			
		||||
    logic HoldModeDeassert;
 | 
			
		||||
    //Delay signals
 | 
			
		||||
    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] CS_SCKCount;                        //Counter for cs-sck delay
 | 
			
		||||
    logic [8:0] SCK_CSCount;                        //Counter for sck-cs delay
 | 
			
		||||
    logic [8:0] InterCSCount;                       //Counter for inter cs delay
 | 
			
		||||
    logic [8:0] InterXFRCount;                      //Counter for inter xfr delay 
 | 
			
		||||
    logic CS_SCKCompare;                            //Boolean comparison signal, high when CS_SCKCount >= cs-sck delay
 | 
			
		||||
    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
 | 
			
		||||
    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] ReceivePenultimateFrame;            //Frame number - 1
 | 
			
		||||
    logic [3:0] ReceivePenultimateFrameCount;       //Counter
 | 
			
		||||
    logic ReceivePenultimateFrameBoolean;           //High when penultimate frame in transmission has been reached
 | 
			
		||||
 | 
			
		||||
    //state fsm signals
 | 
			
		||||
    logic Active;
 | 
			
		||||
    logic Active0;
 | 
			
		||||
    logic Inactive;
 | 
			
		||||
    //State fsm signals
 | 
			
		||||
    logic Active;                                   //High when state is either Active1 or Active0 (during transmission)
 | 
			
		||||
    logic Active0;                                  //High when state is Active0
 | 
			
		||||
 | 
			
		||||
    //shift reg signals
 | 
			
		||||
    logic TransmitFIFOWriteIncrementDelay;
 | 
			
		||||
    logic sckPhaseSelect;
 | 
			
		||||
    logic [7:0] TransmitShiftReg;
 | 
			
		||||
    logic [7:0] ReceiveShiftReg;
 | 
			
		||||
    logic SampleEdge;
 | 
			
		||||
    logic [7:0] TransmitDataEndian;
 | 
			
		||||
    logic TransmitShiftRegLoad;
 | 
			
		||||
    //Shift reg signals
 | 
			
		||||
    logic ShiftEdge;                                //Determines which edge of sck to shift from TransmitShiftReg
 | 
			
		||||
    logic [7:0] TransmitShiftReg;                   //Transmit shift register
 | 
			
		||||
    logic [7:0] ReceiveShiftReg;                    //Receive shift register
 | 
			
		||||
    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 TransmitShiftRegLoad;                     //Determines when to load TransmitShiftReg
 | 
			
		||||
    logic ReceiveShiftFull;                         //High when receive shift register is full
 | 
			
		||||
    logic TransmitShiftEmpty;                       //High when transmit shift register is empty
 | 
			
		||||
    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    
 | 
			
		||||
 | 
			
		||||
    //CS signals
 | 
			
		||||
    logic [3:0] ChipSelectAuto, ChipSelectHold, CSoff;
 | 
			
		||||
    logic ChipSelectHoldSingle;
 | 
			
		||||
    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 DelayMode;                                //Determines where to place implicit half cycle delay based on sck phase for CS assertion
 | 
			
		||||
 | 
			
		||||
    logic ReceiveShiftFullDelay;
 | 
			
		||||
    //Miscellaneous signals delayed/early 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 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 SCLKenableDelay;
 | 
			
		||||
    logic shiftin;
 | 
			
		||||
    logic [7:0] ReceiveShiftRegInvert;
 | 
			
		||||
    logic ZeroDelayHoldMode;
 | 
			
		||||
    logic TransmitInactive;
 | 
			
		||||
    logic SCLKenableEarly;
 | 
			
		||||
    logic ReceiveShiftFullDelayPCLK;
 | 
			
		||||
    logic [3:0] LeftShiftAmount;
 | 
			
		||||
    logic [7:0] ASR; // AlignedReceiveShiftReg
 | 
			
		||||
    logic DelayMode;
 | 
			
		||||
    logic [3:0] PWChipSelect;
 | 
			
		||||
 | 
			
		||||
    // APB access
 | 
			
		||||
    //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 = 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.
 | 
			
		||||
   
 | 
			
		||||
    assign Din = PWDATA[31:0]; 
 | 
			
		||||
    if (P.XLEN == 64) assign PRDATA = {Dout, Dout}; 
 | 
			
		||||
    else              assign PRDATA = Dout;  
 | 
			
		||||
 | 
			
		||||
    // register access  *** clean this up
 | 
			
		||||
    //Register access  
 | 
			
		||||
    always_ff@(posedge PCLK, negedge PRESETn)
 | 
			
		||||
        if (~PRESETn) begin 
 | 
			
		||||
            SckDiv <= #1 12'd3;
 | 
			
		||||
@ -219,8 +210,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
            endcase
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
    //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
 | 
			
		||||
    assign SCLKenable = (DivCounter == SckDiv);
 | 
			
		||||
    assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
 | 
			
		||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
			
		||||
@ -229,23 +220,24 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
        else DivCounter <= DivCounter + 12'b1;
 | 
			
		||||
 | 
			
		||||
    //Boolean logic that tracks frame progression
 | 
			
		||||
    assign FrameCompare = {1'b0,Format[4:1]};
 | 
			
		||||
    assign FrameCompareBoolean = (FrameCount < FrameCompare);
 | 
			
		||||
    assign ReceivePenultimateFrameCount = FrameCount + 5'b00001;
 | 
			
		||||
    assign ReceivePenultimateFrameBoolean = (ReceivePenultimateFrameCount >= FrameCompare);
 | 
			
		||||
    assign FrameCompare = (FrameCount < 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
 | 
			
		||||
    assign Delay0Compare = SckMode[0] ? (Delay0Count >= ({Delay0[7:0], 1'b0})) : (Delay0Count >= ({Delay0[7:0], 1'b0} + 9'b1));
 | 
			
		||||
    assign Delay1Compare = SckMode[0] ? (Delay1Count >= (({Delay0[15:8], 1'b0}) + 9'b1)) : (Delay1Count >= ({Delay0[15:8], 1'b0}));
 | 
			
		||||
    assign ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1;
 | 
			
		||||
    assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0;
 | 
			
		||||
 | 
			
		||||
    assign CS_SCKCompare = CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1);
 | 
			
		||||
    assign SCK_CSCompare = SCK_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2);
 | 
			
		||||
    assign InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0}));
 | 
			
		||||
    assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 1'b0}));
 | 
			
		||||
 | 
			
		||||
    //calculate when tx/rx shift registers are full/empty
 | 
			
		||||
    //Calculate when tx/rx shift registers are full/empty
 | 
			
		||||
    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 
 | 
			
		||||
    //Calculate tx/rx fifo write and recieve increment signals 
 | 
			
		||||
    assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
 | 
			
		||||
 | 
			
		||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
			
		||||
@ -256,7 +248,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
        if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
 | 
			
		||||
        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) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
 | 
			
		||||
 | 
			
		||||
@ -280,36 +272,36 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
 | 
			
		||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
			
		||||
        if (~PRESETn) begin state <= CS_INACTIVE;
 | 
			
		||||
                            FrameCount <= 5'b0;                      
 | 
			
		||||
                        FrameCount <= 4'b0;                      
 | 
			
		||||
 | 
			
		||||
        /* verilator lint_off CASEINCOMPLETE */
 | 
			
		||||
        end else if (SCLKenable) begin
 | 
			
		||||
            case (state)
 | 
			
		||||
                CS_INACTIVE: begin
 | 
			
		||||
                        Delay0Count <= 9'b1;
 | 
			
		||||
                        Delay1Count <= 9'b10;
 | 
			
		||||
                        FrameCount <= 5'b0;
 | 
			
		||||
                        CS_SCKCount <= 9'b1;
 | 
			
		||||
                        SCK_CSCount <= 9'b10;
 | 
			
		||||
                        FrameCount <= 4'b0;
 | 
			
		||||
                        InterCSCount <= 9'b10;
 | 
			
		||||
                        InterXFRCount <= 9'b1;
 | 
			
		||||
                        if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0;
 | 
			
		||||
                        else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) state <= ACTIVE_0;
 | 
			
		||||
                        end
 | 
			
		||||
                DELAY_0: begin
 | 
			
		||||
                        Delay0Count <= Delay0Count + 9'b1;
 | 
			
		||||
                        if (Delay0Compare) state <= ACTIVE_0;
 | 
			
		||||
                        CS_SCKCount <= CS_SCKCount + 9'b1;
 | 
			
		||||
                        if (CS_SCKCompare) state <= ACTIVE_0;
 | 
			
		||||
                        end
 | 
			
		||||
                ACTIVE_0: begin 
 | 
			
		||||
                        FrameCount <= FrameCount + 5'b1;
 | 
			
		||||
                        FrameCount <= FrameCount + 4'b1;
 | 
			
		||||
                        state <= ACTIVE_1;
 | 
			
		||||
                        end
 | 
			
		||||
                ACTIVE_1: begin
 | 
			
		||||
                        InterXFRCount <= 9'b1;
 | 
			
		||||
                        if (FrameCompareBoolean) state <= ACTIVE_0;
 | 
			
		||||
                        if (FrameCompare) state <= ACTIVE_0;
 | 
			
		||||
                        else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
 | 
			
		||||
                            state <= ACTIVE_0;
 | 
			
		||||
                            Delay0Count <= 9'b1;
 | 
			
		||||
                            Delay1Count <= 9'b10;
 | 
			
		||||
                            FrameCount <= 5'b0;
 | 
			
		||||
                            CS_SCKCount <= 9'b1;
 | 
			
		||||
                            SCK_CSCount <= 9'b10;
 | 
			
		||||
                            FrameCount <= 4'b0;
 | 
			
		||||
                            InterCSCount <= 9'b10;
 | 
			
		||||
                        end
 | 
			
		||||
                        else if (ChipSelectMode[1:0] == 2'b10) state <= INTER_XFR;
 | 
			
		||||
@ -317,17 +309,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
                        else state <= DELAY_1;
 | 
			
		||||
                        end
 | 
			
		||||
                DELAY_1: begin
 | 
			
		||||
                        Delay1Count <= Delay1Count + 9'b1;
 | 
			
		||||
                        if (Delay1Compare) state <= INTER_CS;
 | 
			
		||||
                        SCK_CSCount <= SCK_CSCount + 9'b1;
 | 
			
		||||
                        if (SCK_CSCompare) state <= INTER_CS;
 | 
			
		||||
                        end
 | 
			
		||||
                INTER_CS: begin
 | 
			
		||||
                        InterCSCount <= InterCSCount + 9'b1;
 | 
			
		||||
                        if (InterCSCompare ) state <= CS_INACTIVE;
 | 
			
		||||
                        end
 | 
			
		||||
                INTER_XFR: begin
 | 
			
		||||
                        Delay0Count <= 9'b1;
 | 
			
		||||
                        Delay1Count <= 9'b10;
 | 
			
		||||
                        FrameCount <= 5'b0;
 | 
			
		||||
                        CS_SCKCount <= 9'b1;
 | 
			
		||||
                        SCK_CSCount <= 9'b10;
 | 
			
		||||
                        FrameCount <= 4'b0;
 | 
			
		||||
                        InterCSCount <= 9'b10;
 | 
			
		||||
                        InterXFRCount <= InterXFRCount + 9'b1;
 | 
			
		||||
                        if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
 | 
			
		||||
@ -346,16 +338,15 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
    assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
 | 
			
		||||
    assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
 | 
			
		||||
    assign Active0 = (state == ACTIVE_0);
 | 
			
		||||
    assign Inactive = (state == CS_INACTIVE);
 | 
			
		||||
 | 
			
		||||
    // Signal tracks which edge of sck to shift data
 | 
			
		||||
    //Signal tracks which edge of sck to shift data
 | 
			
		||||
    always_comb
 | 
			
		||||
        case(SckMode[1:0])
 | 
			
		||||
            2'b00: sckPhaseSelect = ~sck & SCLKenable;
 | 
			
		||||
            2'b01: sckPhaseSelect = (sck & |(FrameCount) & SCLKenable);
 | 
			
		||||
            2'b10: sckPhaseSelect = sck & SCLKenable;
 | 
			
		||||
            2'b11: sckPhaseSelect = (~sck & |(FrameCount) & SCLKenable);
 | 
			
		||||
            default: sckPhaseSelect = sck & SCLKenable;
 | 
			
		||||
            2'b00: ShiftEdge = ~sck & SCLKenable;
 | 
			
		||||
            2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable);
 | 
			
		||||
            2'b10: ShiftEdge = sck & SCLKenable;
 | 
			
		||||
            2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable);
 | 
			
		||||
            default: ShiftEdge = sck & SCLKenable;
 | 
			
		||||
        endcase
 | 
			
		||||
 | 
			
		||||
    //Transmit shift register
 | 
			
		||||
@ -363,32 +354,31 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
 | 
			
		||||
    always_ff @(posedge PCLK, negedge PRESETn)
 | 
			
		||||
        if(~PRESETn)                        TransmitShiftReg <= 8'b0; 
 | 
			
		||||
        else if (TransmitShiftRegLoad)      TransmitShiftReg <= TransmitDataEndian;
 | 
			
		||||
        else if (sckPhaseSelect & Active)   TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
 | 
			
		||||
        else if (ShiftEdge & Active)   TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
 | 
			
		||||
    
 | 
			
		||||
    assign SPIOut = TransmitShiftReg[7];
 | 
			
		||||
 | 
			
		||||
    //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
 | 
			
		||||
    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)
 | 
			
		||||
        if(~PRESETn)  ReceiveShiftReg <= 8'b0;
 | 
			
		||||
        else if (SampleEdge & SCLKenable) begin
 | 
			
		||||
            if (~Active) ReceiveShiftReg <= 8'b0;
 | 
			
		||||
            else ReceiveShiftReg <= {ReceiveShiftReg[6:0], shiftin};
 | 
			
		||||
            else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
 | 
			
		||||
        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 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];
 | 
			
		||||
 | 
			
		||||
    // Interrupt logic: raise interrupt if any enabled interrupts are pending
 | 
			
		||||
    //Interrupt logic: raise interrupt if any enabled interrupts are pending
 | 
			
		||||
    assign SPIIntr = |(InterruptPending & InterruptEnable);
 | 
			
		||||
 | 
			
		||||
    // Chip select logic
 | 
			
		||||
    
 | 
			
		||||
    //Chip select logic
 | 
			
		||||
    always_comb
 | 
			
		||||
        case(ChipSelectID[1:0])
 | 
			
		||||
            2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
 | 
			
		||||
@ -409,6 +399,13 @@ module SynchFIFO #(parameter M =3 , N= 8)(
 | 
			
		||||
    output logic wfull, rempty,
 | 
			
		||||
    output logic wwatermark, rwatermark);
 | 
			
		||||
 | 
			
		||||
    /* 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
 | 
			
		||||
       are an extra bit larger than address size to determine full/empty conditions. 
 | 
			
		||||
       Watermark comparisons use 2's complement subtraction between the M-1 bit pointers,
 | 
			
		||||
       which are also used to address memory
 | 
			
		||||
    */
 | 
			
		||||
       
 | 
			
		||||
    logic [N-1:0] mem[2**M];
 | 
			
		||||
    logic [M:0] rptr, wptr;
 | 
			
		||||
    logic [M:0] rptrnext, wptrnext;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user