mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
hardware interlock
This commit is contained in:
parent
0ff9ce527d
commit
2330f4ee63
@ -1,2 +1,2 @@
|
||||
vsim -do "do wally.do rv64gc wally64priv"
|
||||
vsim -do "do wally.do rv64gc wally64periph"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user