mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge branch 'main' of github.com:openhwgroup/cvw
This commit is contained in:
		
						commit
						33435bfb6a
					
				| @ -65,6 +65,16 @@ EXT_MEM_RANGE       64'h0FFFFFFF | ||||
| deriv fpgavcu108 fpga | ||||
| EXT_MEM_RANGE       64'h7FFFFFFF | ||||
| 
 | ||||
| # temporary spitest configuration | ||||
| deriv spitest rv64gc | ||||
| UNCORE_RAM_RANGE    64'h0FFFFFFF | ||||
| SPI_LOOPBACK_TEST   1 | ||||
| UART_PRESCALE       32'd0 | ||||
| PLIC_NUM_SRC        32'd53 | ||||
| SDC_SUPPORTED       1 | ||||
| PLIC_SDC_ID         32'd20 | ||||
| BPRED_SIZE          32'd12 | ||||
| 
 | ||||
| # The syn configurations are trimmed down for faster synthesis.   | ||||
| deriv   syn_rv32e       rv32e | ||||
| DTIM_RANGE              64'h1FF | ||||
|  | ||||
| @ -100,7 +100,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|     rsrstatetype ReceiveState; | ||||
| 
 | ||||
|     // Transmission signals
 | ||||
|     // logic sck;
 | ||||
|     logic ZeroDiv;                                  // High when SckDiv is 0
 | ||||
|     logic [11:0] DivCounter;                        // Counter for sck 
 | ||||
|     logic SCLKenable;                               // Flip flop enable high every sclk edge
 | ||||
| 
 | ||||
| @ -114,6 +114,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|     logic ZeroDelayHoldMode;                        // High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
 | ||||
| 
 | ||||
|     // Frame counting signals
 | ||||
|     logic FirstFrame; | ||||
|     logic [3:0] FrameCount;                         // Counter for number of frames in transmission
 | ||||
|     logic ReceivePenultimateFrame;                  // High when penultimate frame in transmission has been reached
 | ||||
| 
 | ||||
| @ -128,11 +129,15 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|     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 TransmitShiftRegLoadSingleCycle;          // Version of TransmitShiftRegLoad which is only high for a single SCLK cycle to prevent double loads 
 | ||||
|     logic TransmitShiftRegLoadDelay;                // TransmitShiftRegLoad delayed by an SCLK cycle, inverted and anded with TransmitShiftRegLoad to create a single cycle signal
 | ||||
|     logic TransmitFIFOReadIncrement;                // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read
 | ||||
|     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   
 | ||||
|     logic ShiftEdgeSPICLK;                          // Changes ShiftEdge when SckDiv is 0
 | ||||
| 
 | ||||
|     // CS signals
 | ||||
|     logic [3:0] ChipSelectAuto;                     // Assigns ChipSelect value to selected CS signal based on CS ID
 | ||||
| @ -145,6 +150,10 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|     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
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     // APB access
 | ||||
|     assign Entry = {PADDR[7:2],2'b00};  //  32-bit word-aligned accesses
 | ||||
|     assign Memwrite = PWRITE & PENABLE & PSEL;  // Only write in access phase
 | ||||
| @ -225,7 +234,9 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|     // 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); | ||||
|     // When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK
 | ||||
|     assign ZeroDiv = ~|(SckDiv[10:0]); | ||||
|     assign SCLKenable = ZeroDiv ? PCLK : (DivCounter == SckDiv); | ||||
|     assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv); | ||||
|     always_ff @(posedge PCLK) | ||||
|         if (~PRESETn) DivCounter <= '0; | ||||
| @ -234,6 +245,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
| 
 | ||||
|     // Asserts when transmission is one frame before complete
 | ||||
|     assign ReceivePenultimateFrame = ((FrameCount + 4'b0001) == Format[4:1]); | ||||
|     assign FirstFrame = (FrameCount == 4'b0); | ||||
| 
 | ||||
|     // Computing delays
 | ||||
|     // When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs
 | ||||
| @ -277,8 +289,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|         if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0; | ||||
|         else ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); | ||||
| 
 | ||||
|     assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty)); | ||||
| 
 | ||||
|     always_ff @(posedge PCLK) | ||||
|         if (~PRESETn) TransmitShiftRegLoadDelay <=0; | ||||
|         else if (SCLKenable) TransmitShiftRegLoadDelay <= TransmitShiftRegLoad; | ||||
|     assign TransmitShiftRegLoadSingleCycle = TransmitShiftRegLoad & ~TransmitShiftRegLoadDelay; | ||||
|     always_ff @(posedge PCLK)  | ||||
|         if (~PRESETn) TransmitFIFOReadIncrement <= 0; | ||||
|         else if (SCLKenable) TransmitFIFOReadIncrement <= TransmitShiftRegLoadSingleCycle; | ||||
|     // Tx/Rx FIFOs
 | ||||
|     spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], | ||||
|     spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], | ||||
|                             TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark); | ||||
|     spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel,  | ||||
|                             ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark); | ||||
| @ -294,7 +315,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|         if (~PRESETn) ReceiveShiftFullDelayPCLK <= 1'b0; | ||||
|         else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull;  | ||||
| 
 | ||||
|     assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty)); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     // 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; | ||||
| @ -365,7 +387,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( | ||||
|                         FrameCount <= 4'b0; | ||||
|                         InterCSCount <= 9'b10; | ||||
|                         InterXFRCount <= InterXFRCount + 9'b1; | ||||
|                         if ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & ~TransmitFIFOReadEmptyDelay) begin | ||||
|                     if ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & (~TransmitFIFOReadEmptyDelay | ~TransmitShiftEmpty)) begin | ||||
|                           state <= ACTIVE_0; | ||||
|                           SPICLK <= ~SckMode[1]; | ||||
|                         end else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE; | ||||
| @ -384,22 +406,23 @@ 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) | ((state == ACTIVE_1) & ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty) & (FrameCount == Format[4:1])))); | ||||
|     assign Active0 = (state == ACTIVE_0); | ||||
|     assign ShiftEdgeSPICLK = ZeroDiv ? ~SPICLK : SPICLK; | ||||
| 
 | ||||
|   // Signal tracks which edge of sck to shift data
 | ||||
|     always_comb | ||||
|         case(SckMode[1:0]) | ||||
|             2'b00: ShiftEdge = SPICLK & SCLKenable; | ||||
|             2'b01: ShiftEdge = (~SPICLK & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive); | ||||
|             2'b10: ShiftEdge = ~SPICLK & SCLKenable;  | ||||
|             2'b11: ShiftEdge = (SPICLK & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive); | ||||
|             default: ShiftEdge = SPICLK & SCLKenable; | ||||
|             2'b00: ShiftEdge = ShiftEdgeSPICLK & SCLKenable; | ||||
|             2'b01: ShiftEdge = (~ShiftEdgeSPICLK & ~FirstFrame & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive); | ||||
|             2'b10: ShiftEdge = ~ShiftEdgeSPICLK & SCLKenable;  | ||||
|             2'b11: ShiftEdge = (ShiftEdgeSPICLK & ~FirstFrame & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive); | ||||
|             default: ShiftEdge = ShiftEdgeSPICLK & SCLKenable; | ||||
|         endcase | ||||
| 
 | ||||
|     // 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]; | ||||
|     always_ff @(posedge PCLK) | ||||
|         if(~PRESETn)                        TransmitShiftReg <= 8'b0; | ||||
|         else if (TransmitShiftRegLoad)      TransmitShiftReg <= TransmitDataEndian; | ||||
|         else if (TransmitShiftRegLoadSingleCycle)      TransmitShiftReg <= TransmitDataEndian; | ||||
|         else if (ShiftEdge & Active)        TransmitShiftReg <= {TransmitShiftReg[6:0], TransmitShiftReg[0]}; | ||||
|      | ||||
|     assign SPIOut = TransmitShiftReg[7]; | ||||
|  | ||||
| @ -84,6 +84,38 @@ | ||||
| 
 | ||||
| 000000FF | ||||
| 
 | ||||
| 000000AE | ||||
| 
 | ||||
| 000000AD | ||||
| 
 | ||||
| 000000AC | ||||
| 
 | ||||
| 000000AB | ||||
| 
 | ||||
| 000000AE | ||||
| 
 | ||||
| 000000AD | ||||
| 
 | ||||
| 000000AC | ||||
| 
 | ||||
| 000000AB | ||||
| 
 | ||||
| 000000AE | ||||
| 
 | ||||
| 000000AD | ||||
| 
 | ||||
| 000000AC | ||||
| 
 | ||||
| 000000AB | ||||
| 
 | ||||
| 000000AE | ||||
| 
 | ||||
| 000000AD | ||||
| 
 | ||||
| 000000AC | ||||
| 
 | ||||
| 000000AB | ||||
| 
 | ||||
| 000000A0 | ||||
| 
 | ||||
| 0000000B | ||||
|  | ||||
| @ -162,6 +162,45 @@ test_cases: | ||||
| .4byte 0x0, 0x00000000, spi_data_wait           # wait for transmission to end | ||||
| .4byte rx_data, 0x000000FF, read32_test     # read rx_data | ||||
| 
 | ||||
| # Test min sck_div | ||||
| 
 | ||||
| .4byte sck_div, 0x000000000, write32_test   #set sck_div to 0 | ||||
| .4byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .4byte 0x0, 0x00000003, spi_data_wait | ||||
| .4byte rx_data, 0x000000AE, read32_test | ||||
| .4byte rx_data, 0x000000AD, read32_test | ||||
| .4byte rx_data, 0x000000AC, read32_test | ||||
| .4byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| # min sck_div, sckmode 01 | ||||
| 
 | ||||
| .4byte sck_mode, 0x00000001, write32_test | ||||
| .4byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .4byte 0x0, 0x00000003, spi_data_wait | ||||
| .4byte rx_data, 0x000000AE, read32_test | ||||
| .4byte rx_data, 0x000000AD, read32_test | ||||
| .4byte rx_data, 0x000000AC, read32_test | ||||
| .4byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| #min sck_div, sckmode 10 | ||||
| .4byte sck_mode, 0x00000002, write32_test | ||||
| .4byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .4byte 0x0, 0x00000003, spi_data_wait | ||||
| .4byte rx_data, 0x000000AE, read32_test | ||||
| .4byte rx_data, 0x000000AD, read32_test | ||||
| .4byte rx_data, 0x000000AC, read32_test | ||||
| .4byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| #min sck_div, sckmode 11 | ||||
| .4byte sck_mode, 0x00000003, write32_test | ||||
| .4byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .4byte 0x0, 0x00000003, spi_data_wait | ||||
| .4byte rx_data, 0x000000AE, read32_test | ||||
| .4byte rx_data, 0x000000AD, read32_test | ||||
| .4byte rx_data, 0x000000AC, read32_test | ||||
| .4byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| 
 | ||||
| # Test phase | ||||
| 
 | ||||
| .4byte sck_div, 0x00000003, write32_test    # reset sck_div to 0x03 so only sck_mode is different | ||||
|  | ||||
| @ -84,6 +84,38 @@ | ||||
| 00000000 | ||||
| 000000FF | ||||
| 00000000 | ||||
| 000000AE | ||||
| 00000000 | ||||
| 000000AD | ||||
| 00000000 | ||||
| 000000AC | ||||
| 00000000 | ||||
| 000000AB | ||||
| 00000000 | ||||
| 000000AE | ||||
| 00000000 | ||||
| 000000AD | ||||
| 00000000 | ||||
| 000000AC | ||||
| 00000000 | ||||
| 000000AB | ||||
| 00000000 | ||||
| 000000AE | ||||
| 00000000 | ||||
| 000000AD | ||||
| 00000000 | ||||
| 000000AC | ||||
| 00000000 | ||||
| 000000AB | ||||
| 00000000 | ||||
| 000000AE | ||||
| 00000000 | ||||
| 000000AD | ||||
| 00000000 | ||||
| 000000AC | ||||
| 00000000 | ||||
| 000000AB | ||||
| 00000000 | ||||
| 000000A0 | ||||
| 00000000 | ||||
| 0000000B | ||||
|  | ||||
| @ -164,6 +164,47 @@ test_cases: | ||||
| .8byte 0x0, 0x00000000, spi_data_wait           # wait for transmission to end | ||||
| .8byte rx_data, 0x000000FF, read32_test     # read rx_data | ||||
| 
 | ||||
| # Test min sck_div | ||||
| 
 | ||||
| .8byte sck_div, 0x000000000, write32_test   #set sck_div to 0 | ||||
| .8byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .8byte 0x0, 0x00000003, spi_data_wait | ||||
| .8byte rx_data, 0x000000AE, read32_test | ||||
| .8byte rx_data, 0x000000AD, read32_test | ||||
| .8byte rx_data, 0x000000AC, read32_test | ||||
| .8byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| # min sck_div, sckmode 01 | ||||
| 
 | ||||
| .8byte sck_mode, 0x00000001, write32_test | ||||
| .8byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .8byte 0x0, 0x00000003, spi_data_wait | ||||
| .8byte rx_data, 0x000000AE, read32_test | ||||
| .8byte rx_data, 0x000000AD, read32_test | ||||
| .8byte rx_data, 0x000000AC, read32_test | ||||
| .8byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| #min sck_div, sckmode 10 | ||||
| .8byte sck_mode, 0x00000002, write32_test | ||||
| .8byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .8byte 0x0, 0x00000003, spi_data_wait | ||||
| .8byte rx_data, 0x000000AE, read32_test | ||||
| .8byte rx_data, 0x000000AD, read32_test | ||||
| .8byte rx_data, 0x000000AC, read32_test | ||||
| .8byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| #min sck_div, sckmode 11 | ||||
| .8byte sck_mode, 0x00000003, write32_test | ||||
| .8byte tx_data, 0xABACADAE, spi_burst_send | ||||
| .8byte 0x0, 0x00000003, spi_data_wait | ||||
| .8byte rx_data, 0x000000AE, read32_test | ||||
| .8byte rx_data, 0x000000AD, read32_test | ||||
| .8byte rx_data, 0x000000AC, read32_test | ||||
| .8byte rx_data, 0x000000AB, read32_test | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # Test phase | ||||
| 
 | ||||
| .8byte sck_div, 0x00000003, write32_test    # reset sck_div to 0x03 so only sck_mode is different | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user