mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-24 05:47:16 -04:00
Merge branch 'spi_debug'
This commit is contained in:
commit
58be9e0556
6 changed files with 190 additions and 13 deletions
|
@ -59,6 +59,16 @@ SDC_SUPPORTED 1
|
|||
PLIC_SDC_ID 32'd20
|
||||
BPRED_SIZE 32'd12
|
||||
|
||||
# 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 [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
|
||||
|
@ -276,9 +288,18 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||
always_ff @(posedge PCLK)
|
||||
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…
Add table
Add a link
Reference in a new issue