hardware interlock

This commit is contained in:
naichewa 2023-10-30 17:00:20 -07:00
parent 0ff9ce527d
commit 2330f4ee63
5 changed files with 286 additions and 82 deletions

View File

@ -1,2 +1,2 @@
vsim -do "do wally.do rv64gc wally64priv"
vsim -do "do wally.do rv64gc wally64periph"

View File

@ -26,8 +26,11 @@
////////////////////////////////////////////////////////////////////////////////////////////////
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
// Hardware interlocks to ensure transfer finishes before register changes unimplemented
//TODO: change tests to reflect swizzled Delay0, Delay1, Format
// Hardware interlock cs_mode hold interaction
// relook at fifo empty full logic; might be that watermark level is low when full
@ -52,18 +55,18 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
//SPI registers
logic [11:0] SckDiv;
logic [1:0] SckMode;
logic [1:0] ChipSelectID;
logic [3:0] ChipSelectDef;
logic [1:0] ChipSelectMode;
logic [15:0] Delay0, Delay1;
logic [7:0] Format;
logic [11:0] SckDiv, HISckDiv;
logic [1:0] SckMode, HISckMode;
logic [1:0] ChipSelectID, HIChipSelectID;
logic [3:0] ChipSelectDef, HIChipSelectDef;
logic [1:0] ChipSelectMode, HIChipSelectMode;
logic [15:0] Delay0, Delay1, HIDelay0, HIDelay1;
logic [7:0] Format, HIFormat;
logic [8:0] ReceiveData;
logic [8:0] ReceiveDataPlaceholder;
logic [2:0] TransmitWatermark, ReceiveWatermark;
logic [2:0] TransmitWatermark, ReceiveWatermark, HITransmitWatermark, HIReceiveWatermark;
logic [8:0] TransmitData;
logic [1:0] InterruptEnable, InterruptPending;
logic [1:0] InterruptEnable, InterruptPending, HIInterruptEnable;
//bus interface signals
logic [7:0] Entry;
@ -87,7 +90,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
//transmission signals
logic sck;
logic [12:0] DivCounter;
logic SCLKDuty;
logic SCLKenable;
logic [8:0] Delay0Count;
logic [8:0] Delay1Count;
logic Delay0Compare;
@ -131,10 +134,22 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
logic ReceiveShiftFullDelay;
logic SCLKenableDelay;
logic [3:0] shiftin;
logic [7:0] ReceiveShiftRegInvert;
logic ZeroDelayHoldMode;
logic TransmitInactive;
logic SCLKenableEarly;
logic ReceiveShiftFullDelayPCLK;
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
assign Memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
assign PREADY = 1'b1; // spi never takes >1 cycle to respond (float module)
assign PREADY = 1'b1; // tie high if hardware interlock solution doesn't involve bus
//assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock
// account for subword read/write circuitry
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
@ -164,6 +179,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
ReceiveWatermark <= #1 3'b0;
InterruptEnable <= #1 2'b0;
InterruptPending <= #1 2'b0;
HISckDiv <= #1 12'd3;
HISckMode <= #1 2'b0;
HIChipSelectID <= #1 2'b0;
HIChipSelectDef <= #1 4'b1111;
HIChipSelectMode <= #1 0;
HIDelay0 <= #1 {8'b1,8'b1};
HIDelay1 <= #1 {8'b0,8'b1};
HIFormat <= #1 {8'b10000000};
HITransmitWatermark <= #1 3'b0;
HIReceiveWatermark <= #1 3'b0;
HIInterruptEnable <= #1 2'b0;
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
@ -173,19 +199,32 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
/* verilator lint_off CASEINCOMPLETE */
if (Memwrite)
case(Entry) //flop to sample inputs
8'h00: SckDiv <= Din[11:0];
8'h04: SckMode <= Din[1:0];
8'h10: ChipSelectID <= Din[1:0];
8'h14: ChipSelectDef <= Din[3:0];
8'h18: ChipSelectMode <= Din[1:0];
8'h28: Delay0 <= {Din[23:16], Din[7:0]};
8'h2C: Delay1 <= {Din[23:16], Din[7:0]};
8'h40: Format <= {Din[19:16], Din[3:0]};
8'h00: HISckDiv <= Din[11:0];
8'h04: HISckMode <= Din[1:0];
8'h10: HIChipSelectID <= Din[1:0];
8'h14: HIChipSelectDef <= Din[3:0];
8'h18: HIChipSelectMode <= Din[1:0];
8'h28: HIDelay0 <= {Din[23:16], Din[7:0]};
8'h2C: HIDelay1 <= {Din[23:16], Din[7:0]};
8'h40: HIFormat <= {Din[19:16], Din[3:0]};
8'h48: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0];
8'h50: TransmitWatermark <= Din[2:0];
8'h54: ReceiveWatermark <= Din[2:0];
8'h70: InterruptEnable <= Din[1:0];
8'h50: HITransmitWatermark <= Din[2:0];
8'h54: HIReceiveWatermark <= Din[2:0];
8'h70: HIInterruptEnable <= Din[1:0];
endcase
if (TransmitInactive) begin
SckDiv <= HISckDiv;
SckMode <= HISckMode;
ChipSelectID <= HIChipSelectID;
ChipSelectDef <= HIChipSelectDef;
ChipSelectMode <= HIChipSelectMode;
Delay0 <= HIDelay0;
Delay1 <= HIDelay1;
Format <= HIFormat;
TransmitWatermark <= HITransmitWatermark;
ReceiveWatermark <= HIReceiveWatermark;
InterruptEnable <= HIInterruptEnable;
end
/* verilator lint_off CASEINCOMPLETE */
//interrupt clearance
InterruptPending[0] <= TransmitReadMark;
@ -208,6 +247,23 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
default: Dout <= #1 32'b0;
endcase
end
assign SCLKenable = (DivCounter >= {1'b0,SckDiv});
assign SCLKenableEarly = ((DivCounter + 13'b1) >= {1'b0, SckDiv});
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) DivCounter <= #1 0;
else if (SCLKenable) DivCounter <= 0;
else DivCounter <= DivCounter + 13'b1;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) SCLKenableDelay <= 0;
else SCLKenableDelay <= SCLKenable;
//SCK_CONTROL
//multiplies frame count by 2 or 4 if in dual or quad mode
@ -269,18 +325,46 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
// double number of frames in dual or quad mode because we must wait for peripheral to send back
assign FrameCompare = (Format[0] | Format[1]) ? ({Format[7:4], 1'b0}) : {1'b0,Format[7:4]};
// Transmit and Receive FIFOs
//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);
// Producing SCLK
// SCLK = PCLK/(2*(sclk_div + 1))
// SCLKDuty is high every half-period of SCLK
assign SCLKDuty = (DivCounter >= {1'b0,SckDiv});
//calculate tx/rx fifo write and recieve increment signals
assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) DivCounter <= #1 0;
else if (SCLKDuty) DivCounter <= 0;
else DivCounter <= DivCounter + 13'b1;
if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0;
else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement;
assign TransmitFIFOReadIncrement = TransmitShiftEmpty;
assign ReceiveFIFOWriteIncrement = ReceiveShiftFullDelay;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
else if (~ReceiveFIFOReadIncrement) ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL);
else ReceiveFIFOReadIncrement <= 0;
assign TransmitDataEndian = Format[2] ? {TransmitData[0], TransmitData[1], TransmitData[2], TransmitData[3], TransmitData[4], TransmitData[5], TransmitData[6], TransmitData[7]} : TransmitData[7:0];
TransmitSynchFIFO #(3,8) txFIFO(PCLK, SCLKenable, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitFIFOReadIncrement, TransmitDataEndian, TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
ReceiveSynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, PRESETn, ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveShiftFullDelay <= 0;
else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveShiftFullDelayPCLK <= 0;
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
@ -292,7 +376,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
FrameCount <= 5'b0;
/* verilator lint_off CASEINCOMPLETE */
end else if (SCLKDuty) begin
end else if (SCLKenable) begin
case (state)
CS_INACTIVE: begin
Delay0Count <= 9'b1;
@ -346,6 +430,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
end
endcase
end
/* verilator lint_off CASEINCOMPLETE */
@ -353,7 +438,9 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
assign busy = (state == DELAY_0 | state == ACTIVE_0 | ((state == ACTIVE_1) & ~((|(Delay1[15:8]) & (ChipSelectMode[1:0]) == 2'b10) & ((FrameCount << Format[1:0]) >= FrameCompare))) | state == DELAY_1);
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
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);
@ -363,54 +450,20 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
/* verilator lint_off WIDTH */
else if (((ChipSelectMode[1:0] == 2'b10) & (Entry == (8'h18 | 8'h10) | ((Entry == 8'h14) & ((PWDATA[ChipSelectID]) != ChipSelectDef[ChipSelectID])))) & Memwrite) HoldModeDeassert <= 1;
/* verilator lint_on WIDTH */
assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0;
else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement;
assign TransmitFIFOReadIncrement = TransmitShiftEmpty;
assign ReceiveFIFOWriteIncrement = ReceiveShiftFullDelay;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
else if (~ReceiveFIFOReadIncrement) ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL);
else ReceiveFIFOReadIncrement <= 0;
//replace literal 9th bit of ReceiveData register with concatenation of 1 bit empty signal and 8 bits of data
//so that all resets can be handled at the same time
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
assign TransmitDataEndian = Format[2] ? {TransmitData[0], TransmitData[1], TransmitData[2], TransmitData[3], TransmitData[4], TransmitData[5], TransmitData[6], TransmitData[7]} : TransmitData[7:0];
//TransmitFIFO #(3,8) txFIFO(PCLK, SCLKDuty, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitFIFOReadIncrement, TransmitDataEndian,TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
TransmitSynchFIFO #(3,8) txFIFO(PCLK, SCLKDuty, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitFIFOReadIncrement, TransmitDataEndian, TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
//ReceiveFIFO #(3,8) rxFIFO(SCLKDuty, PCLK, PRESETn, ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
ReceiveSynchFIFO #(3,8) rxFIFO(PCLK, SCLKDuty, PRESETn, ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty);
ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKDuty, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull);
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
else if (SCLKDuty) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
logic SCLKDutyDelay;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) SCLKDutyDelay <= 0;
else SCLKDutyDelay <= SCLKDuty;
always_comb
case(SckMode[1:0])
2'b00: sckPhaseSelect = ~sck & SCLKDuty;
2'b01: sckPhaseSelect = (sck & |(FrameCount) & SCLKDuty);
2'b10: sckPhaseSelect = sck & SCLKDuty;
2'b11: sckPhaseSelect = (~sck & |(FrameCount) & SCLKDuty);
default: sckPhaseSelect = sck & SCLKDuty;
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;
endcase
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveShiftFullDelay <= 0;
else if (SCLKDuty) ReceiveShiftFullDelay <= ReceiveShiftFull;
assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
always_ff @(posedge PCLK, negedge PRESETn)
if(~PRESETn) begin
TransmitShiftReg <= 8'b0;
@ -437,11 +490,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
default: SPIOut = {3'b0, TransmitShiftReg[7]};
endcase
end else SPIOut = 4'b0;
logic [3:0] shiftin;
assign shiftin = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
always_ff @(posedge PCLK, negedge PRESETn)
if(~PRESETn) ReceiveShiftReg <= 8'b0;
else if (SampleEdge & SCLKDuty) begin
else if (SampleEdge & SCLKenable) begin
if (~Active) ReceiveShiftReg <= 8'b0;
else if (~Format[3]) begin
case(Format[1:0])
@ -452,7 +505,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
endcase
end
end
logic [7:0] ReceiveShiftRegInvert;
assign ReceiveShiftRegInvert = (Format[2]) ? {ReceiveShiftReg[0], ReceiveShiftReg[1], ReceiveShiftReg[2], ReceiveShiftReg[3], ReceiveShiftReg[4], ReceiveShiftReg[5], ReceiveShiftReg[6], ReceiveShiftReg[7]} : ReceiveShiftReg[7:0];
always_comb
@ -805,7 +858,7 @@ module TransmitShiftFSM(
endmodule
module ReceiveShiftFSM(
input logic PCLK, PRESETn, SCLKDuty,
input logic PCLK, PRESETn, SCLKenable,
input logic ReceivePenultimateFrameBoolean, SampleEdge, SckMode,
output logic ReceiveShiftFull
);
@ -813,7 +866,7 @@ module ReceiveShiftFSM(
statetype ReceiveState, ReceiveNextState;
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState;
else if (SCLKDuty) begin
else if (SCLKenable) begin
case (ReceiveState)
ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState;
ReceiveShiftNotFullState: if (ReceivePenultimateFrameBoolean & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState;

View File

@ -510,7 +510,7 @@ module testbench;
errors = errors+1;
$display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DTIM_SUPPORTED) = %h, signature = %h",
TestName, i, (testadr+i)*(P.XLEN/8), testbench.DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]);
$stop; //***debug
//$stop; //***debug
end
i = i + 1;
end

View File

@ -146,6 +146,46 @@
00000000
0000001F
00000000
00000062 # hardware interlock
00000000
00000026
00000000
000000D2
00000000
0000002D
00000000
00000048
00000000
00000037
00000000
00000026
00000000
00000015
00000000
00000084
00000000
00000073
00000000
00000062
00000000
00000051
00000000
00000046
00000000
00000035
00000000
00000024
00000000
00000013
00000000
00000064
00000000
00000053
00000000
00000042
00000000
00000031
00000000
00000001 #watermark interrupts
00000000
00000000 #read mip

View File

@ -166,7 +166,7 @@ test_cases:
# Test arbitrary cs-sck delay (sck phase 1)
.8byte delay0, 0x00000105, write32_test # set cs-sck delay to 5 cycles
.8byte delay0, 0x00010005, write32_test # set cs-sck delay to 5 cycles
.8byte tx_data, 0x00000048, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000048, read32_test # read rx_data
@ -216,6 +216,7 @@ test_cases:
.8byte delay0, 0x00010001, write32_test # reset delay0 register
.8byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x44332211, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000011, read32_test
@ -226,6 +227,7 @@ test_cases:
#test long inter_cs delay
.8byte delay1, 0x000000A5, write32_test
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x0000007B, write32_test
.8byte 0x0, 0x00000000, spi_data_wait
.8byte rx_data, 0x0000007B, read32_test
@ -234,6 +236,7 @@ test_cases:
# Test inter_cs delay set to 0
.8byte delay1, 0x00000000, write32_test # set inter_cs delay to 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x54433221, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000021, read32_test
@ -276,6 +279,7 @@ test_cases:
# test long inter_xfr delay
.8byte delay1, 0x00A50001, write32_test
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x00000048, write32_test
.8byte 0x0, 0x00000000, spi_data_wait
.8byte rx_data, 0x00000048, read32_test
@ -284,6 +288,7 @@ test_cases:
.8byte delay1, 0x00000001, write32_test # set inter_xfr delay to 0
.8byte delay0, 0x00010005, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0xAABBCCDD, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000DD, read32_test # read rx_data
@ -310,6 +315,7 @@ test_cases:
.8byte sck_mode, 0x00000000, write32_test #reset sckmode register
.8byte cs_mode, 0x00000000, write32_test # set cs_mode to AUTO
.8byte fmt, 0x00040000, write32_test # set frame length to 4
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000F0, read32_test # read rx_data
@ -323,6 +329,7 @@ test_cases:
# test frame length 1 burst
.8byte fmt, 0x00010000, write32_test
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x80008000, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x00000000, read32_test
@ -334,12 +341,14 @@ test_cases:
# Test big endian with frame length = 5
.8byte fmt, 0x00050000, write32_test # set frame length to 5, big endian
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x000000A8, read32_test # read rx_data
# Test big endian burst with frame length = 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x03774FFF, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x000000F8, read32_test
@ -353,12 +362,14 @@ test_cases:
# Test little endian with frame length = 5
.8byte fmt, 0x00050004, write32_test # set frame length to 5, little-endian
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
.8byte rx_data, 0x00000008, read32_test # read rx_data -> 08
#test little endian burst with frame length = 5
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0xFF4F7703, spi_burst_send
.8byte 0x0, 0x00000003, spi_data_wait
.8byte rx_data, 0x00000003, read32_test #03
@ -416,13 +427,110 @@ test_cases:
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
#.8byte rx_data, 0x000000F0, read32_test # read rx_data
#=========== Test Hardware Interlock ================
# interlock in base case
.8byte fmt, 0x00080000, write32_test # reset fmt register
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x00000062, write32_test # initiate transmission
.8byte sck_mode, 0x00000002, write32_test # flip polarity during transmission
.8byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated
.8byte 0x0, 0x00000001, spi_data_wait
.8byte rx_data, 0x00000062, read32_test
.8byte rx_data, 0x00000026, read32_test # clear rx fifo
.8byte sck_mode, 0x00000000, write32_test # reset polarity
# interlock in case where cs_mode is auto, but there is minimal intercs delay
.8byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay
.8byte tx_data, 0x000000D2, write32_test # initiate transmission
.8byte sck_mode, 0x00000002, write32_test # flip sck polarity
.8byte tx_data, 0x0000002D, write32_test # transmit second frame
.8byte 0x0, 0x00000001, spi_data_wait
.8byte rx_data, 0x000000D2, read32_test
.8byte rx_data, 0x0000002D, read32_test # clear rx fifo
.8byte sck_mode, 0x00000000, write32_test # reset polarity
# interlock in case where cs_mode = hold, 0 intercs delay
.8byte delay0, 0x00010001, write32_test # reset delay0
.8byte sck_mode, 0x00000000, write32_test # reset polarity
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
.8byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000048, read32_test
.8byte rx_data, 0x00000037, read32_test
.8byte rx_data, 0x00000026, read32_test
.8byte rx_data, 0x00000015, read32_test #clear rx fifo
# interlock in case where cs_mode = hold, intercs delay
.8byte sck_mode, 0x00000000, write32_test # reset polarity
.8byte delay1, 0x00010001, write32_test # set intercs delay to 1
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000084, read32_test
.8byte rx_data, 0x00000073, read32_test
.8byte rx_data, 0x00000062, read32_test
.8byte rx_data, 0x00000051, read32_test #clear rx fifo
# repeat previous set of tests with cs_mode = off
.8byte cs_mode, 0x00000003, write32_test # set cs_mode to hold
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000046, read32_test
.8byte rx_data, 0x00000035, read32_test
.8byte rx_data, 0x00000024, read32_test
.8byte rx_data, 0x00000013, read32_test #clear rx fifo
# interlock in case where cs_mode = hold, intercs delay
.8byte sck_mode, 0x00000000, write32_test # reset polarity
.8byte delay1, 0x00000000, write32_test # set intercs delay to 0
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
.8byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
.8byte rx_data, 0x00000064, read32_test
.8byte rx_data, 0x00000053, read32_test
.8byte rx_data, 0x00000042, read32_test
.8byte rx_data, 0x00000031, read32_test #clear rx fifo
# =========== Test watermark interrupts ===========
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
SETUP_PLIC
.8byte fmt, 0x00080000, write32_test # reset fmt register
.8byte delay1, 0x0000001, write32_test # reset delay1 register
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode
.8byte tx_mark, 0x00000004, write32_test # set transmit watermark to 4
#.8byte ie, 0x00000000, write32_test # enable transmit interrupt
.8byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
@ -462,6 +570,7 @@ SETUP_PLIC
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
.8byte tx_mark, 0x00000000, write32_test
.8byte 0x0, 0x00000000, claim_m_plic_interrupts
.8byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
.8byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
.8byte ie, 0x0000002, write32_test # enable receive interrupts
@ -475,4 +584,6 @@ SETUP_PLIC
.8byte ip, 0x00000000, read32_test # receive interrupt should be low
.8byte 0x0, 0x00000000, readmip_test
.8byte 0x0, 0x0, terminate_test