mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Remove old 2/4 bit logic, add comments,
clean up unused signals
This commit is contained in:
parent
89a303fbef
commit
2b4cf01a21
@ -27,10 +27,8 @@
|
|||||||
|
|
||||||
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
|
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
|
||||||
|
|
||||||
// Comment on FIFOs: watermark calculations
|
// Attempt to move from >= comparisons by initializing in FSM differently
|
||||||
// Comment all interface and internal signals on the lines they are declared
|
// Parameterize SynchFIFO
|
||||||
// Get tabs correct so things line up
|
|
||||||
// Relook at frame compare/ Delay count logic w/o multibit
|
|
||||||
// look at ReadIncrement/WriteIncrement delay necessity
|
// look at ReadIncrement/WriteIncrement delay necessity
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -56,8 +54,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic SPIIntr
|
output logic SPIIntr
|
||||||
);
|
);
|
||||||
|
|
||||||
//SPI registers
|
//SPI control registers. Refer to SiFive FU540-C000 manual
|
||||||
|
|
||||||
logic [11:0] SckDiv;
|
logic [11:0] SckDiv;
|
||||||
logic [1:0] SckMode;
|
logic [1:0] SckMode;
|
||||||
logic [1:0] ChipSelectID;
|
logic [1:0] ChipSelectID;
|
||||||
@ -65,102 +62,96 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [1:0] ChipSelectMode;
|
logic [1:0] ChipSelectMode;
|
||||||
logic [15:0] Delay0, Delay1;
|
logic [15:0] Delay0, Delay1;
|
||||||
logic [4:0] Format;
|
logic [4:0] Format;
|
||||||
logic [8:0] ReceiveData;
|
logic [7:0] ReceiveData;
|
||||||
logic [8:0] ReceiveDataPlaceholder;
|
|
||||||
logic [2:0] TransmitWatermark, ReceiveWatermark;
|
logic [2:0] TransmitWatermark, ReceiveWatermark;
|
||||||
logic [8:0] TransmitData;
|
logic [8:0] TransmitData;
|
||||||
logic [1:0] InterruptEnable, InterruptPending;
|
logic [1:0] InterruptEnable, InterruptPending;
|
||||||
|
|
||||||
//bus interface signals
|
//Bus interface signals
|
||||||
logic [7:0] Entry;
|
logic [7:0] Entry;
|
||||||
logic Memwrite;
|
logic Memwrite;
|
||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
|
logic TransmitInactive; //High when there is no transmission, used as hardware interlock signal
|
||||||
|
|
||||||
//FIFO FSM signals
|
//FIFO FSM signals
|
||||||
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
|
//Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
|
||||||
|
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
|
||||||
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
|
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
|
||||||
logic TransmitFIFOReadIncrement;
|
logic TransmitFIFOReadIncrement;
|
||||||
logic TransmitFIFOWriteIncrement;
|
logic TransmitFIFOWriteIncrement;
|
||||||
logic ReceiveFIFOReadIncrement;
|
logic ReceiveFIFOReadIncrement;
|
||||||
|
|
||||||
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
||||||
logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
|
logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
|
||||||
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
|
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
|
||||||
|
logic [7:0] ReceiveShiftRegEndian; //reverses ReceiveShiftReg if Format[2] set (little endian transmission)
|
||||||
|
|
||||||
logic TransmitFIFOReadEmptyDelay;
|
//Transmission signals
|
||||||
logic [7:0] ReceiveShiftRegEndian;
|
|
||||||
|
|
||||||
//transmission signals
|
|
||||||
logic sck;
|
logic sck;
|
||||||
logic [11:0] DivCounter;
|
logic [11:0] DivCounter; //counter for sck
|
||||||
logic SCLKenable;
|
logic SCLKenable; //flip flop enable high every sclk edge
|
||||||
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 FrameCompareBoolean;
|
//Delay signals
|
||||||
logic [4:0] ReceivePenultimateFrame;
|
logic [8:0] ImplicitDelay1; //Adds implicit delay to cs-sck delay counter based on phase
|
||||||
logic [4:0] ReceivePenultimateFrameCount;
|
logic [8:0] ImplicitDelay2; //Adds implicit delay to sck-cs delay counter based on phase
|
||||||
logic ReceivePenultimateFrameBoolean;
|
logic [8:0] CS_SCKCount; //Counter for cs-sck delay
|
||||||
logic [4:0] FrameCompareProtocol;
|
logic [8:0] SCK_CSCount; //Counter for sck-cs delay
|
||||||
logic ReceiveShiftFull;
|
logic [8:0] InterCSCount; //Counter for inter cs delay
|
||||||
logic TransmitShiftEmpty;
|
logic [8:0] InterXFRCount; //Counter for inter xfr delay
|
||||||
logic HoldModeDeassert;
|
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
|
//State fsm signals
|
||||||
logic Active;
|
logic Active; //High when state is either Active1 or Active0 (during transmission)
|
||||||
logic Active0;
|
logic Active0; //High when state is Active0
|
||||||
logic Inactive;
|
|
||||||
|
|
||||||
//shift reg signals
|
//Shift reg signals
|
||||||
logic TransmitFIFOWriteIncrementDelay;
|
logic ShiftEdge; //Determines which edge of sck to shift from TransmitShiftReg
|
||||||
logic sckPhaseSelect;
|
logic [7:0] TransmitShiftReg; //Transmit shift register
|
||||||
logic [7:0] TransmitShiftReg;
|
logic [7:0] ReceiveShiftReg; //Receive shift register
|
||||||
logic [7:0] ReceiveShiftReg;
|
logic SampleEdge; //Determines which edge of sck to sample from ReceiveShiftReg
|
||||||
logic SampleEdge;
|
logic [7:0] TransmitDataEndian; //Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
|
||||||
logic [7:0] TransmitDataEndian;
|
logic TransmitShiftRegLoad; //Determines when to load TransmitShiftReg
|
||||||
logic TransmitShiftRegLoad;
|
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
|
//CS signals
|
||||||
logic [3:0] ChipSelectAuto, ChipSelectHold, CSoff;
|
logic [3:0] ChipSelectAuto; //Assigns ChipSelect value to selected CS signal based on CS ID
|
||||||
logic ChipSelectHoldSingle;
|
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;
|
//APB access
|
||||||
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
|
|
||||||
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
||||||
assign Memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
assign Memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||||
assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock
|
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.
|
// -- Note SPI registers are 32 bits no matter what; access them with LW SW.
|
||||||
|
|
||||||
assign Din = PWDATA[31:0];
|
assign Din = PWDATA[31:0];
|
||||||
if (P.XLEN == 64) assign PRDATA = {Dout, Dout};
|
if (P.XLEN == 64) assign PRDATA = {Dout, Dout};
|
||||||
else assign PRDATA = Dout;
|
else assign PRDATA = Dout;
|
||||||
|
|
||||||
// register access *** clean this up
|
//Register access
|
||||||
always_ff@(posedge PCLK, negedge PRESETn)
|
always_ff@(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
SckDiv <= #1 12'd3;
|
SckDiv <= #1 12'd3;
|
||||||
@ -219,8 +210,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
// SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
|
//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
|
//Generates a high signal at the rising and falling edge of SCLK by counting from 0 to SckDiv
|
||||||
assign SCLKenable = (DivCounter == SckDiv);
|
assign SCLKenable = (DivCounter == SckDiv);
|
||||||
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
@ -229,23 +220,25 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
else DivCounter <= DivCounter + 12'b1;
|
else DivCounter <= DivCounter + 12'b1;
|
||||||
|
|
||||||
//Boolean logic that tracks frame progression
|
//Boolean logic that tracks frame progression
|
||||||
assign FrameCompare = {1'b0,Format[4:1]};
|
//assign FrameCompare = {1'b0,Format[4:1]}; mb not needed because of removal of dual/quad
|
||||||
assign FrameCompareBoolean = (FrameCount < FrameCompare);
|
assign FrameCompare = (FrameCount < Format[4:1]);
|
||||||
assign ReceivePenultimateFrameCount = FrameCount + 5'b00001;
|
assign ReceivePenultimateFrameBoolean = ((FrameCount + 4'b0001) == Format[4:1]);
|
||||||
assign ReceivePenultimateFrameBoolean = (ReceivePenultimateFrameCount >= FrameCompare);
|
|
||||||
|
|
||||||
// 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
|
// 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 ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1;
|
||||||
assign Delay1Compare = SckMode[0] ? (Delay1Count >= (({Delay0[15:8], 1'b0}) + 9'b1)) : (Delay1Count >= ({Delay0[15:8], 1'b0}));
|
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 InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0}));
|
||||||
assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 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);
|
TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty);
|
||||||
ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKenable, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull);
|
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);
|
assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
@ -256,7 +249,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
|
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
|
||||||
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
||||||
|
|
||||||
//tx/rx FIFOs
|
//Tx/Tx 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) 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);
|
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 +273,36 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if (~PRESETn) begin state <= CS_INACTIVE;
|
if (~PRESETn) begin state <= CS_INACTIVE;
|
||||||
FrameCount <= 5'b0;
|
FrameCount <= 4'b0;
|
||||||
|
|
||||||
/* verilator lint_off CASEINCOMPLETE */
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
end else if (SCLKenable) begin
|
end else if (SCLKenable) begin
|
||||||
case (state)
|
case (state)
|
||||||
CS_INACTIVE: begin
|
CS_INACTIVE: begin
|
||||||
Delay0Count <= 9'b1;
|
CS_SCKCount <= 9'b1;
|
||||||
Delay1Count <= 9'b10;
|
SCK_CSCount <= 9'b10;
|
||||||
FrameCount <= 5'b0;
|
FrameCount <= 4'b0;
|
||||||
InterCSCount <= 9'b10;
|
InterCSCount <= 9'b10;
|
||||||
InterXFRCount <= 9'b1;
|
InterXFRCount <= 9'b1;
|
||||||
if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0;
|
if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0;
|
||||||
else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) state <= ACTIVE_0;
|
else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) state <= ACTIVE_0;
|
||||||
end
|
end
|
||||||
DELAY_0: begin
|
DELAY_0: begin
|
||||||
Delay0Count <= Delay0Count + 9'b1;
|
CS_SCKCount <= CS_SCKCount + 9'b1;
|
||||||
if (Delay0Compare) state <= ACTIVE_0;
|
if (CS_SCKCompare) state <= ACTIVE_0;
|
||||||
end
|
end
|
||||||
ACTIVE_0: begin
|
ACTIVE_0: begin
|
||||||
FrameCount <= FrameCount + 5'b1;
|
FrameCount <= FrameCount + 4'b1;
|
||||||
state <= ACTIVE_1;
|
state <= ACTIVE_1;
|
||||||
end
|
end
|
||||||
ACTIVE_1: begin
|
ACTIVE_1: begin
|
||||||
InterXFRCount <= 9'b1;
|
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
|
else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
|
||||||
state <= ACTIVE_0;
|
state <= ACTIVE_0;
|
||||||
Delay0Count <= 9'b1;
|
CS_SCKCount <= 9'b1;
|
||||||
Delay1Count <= 9'b10;
|
SCK_CSCount <= 9'b10;
|
||||||
FrameCount <= 5'b0;
|
FrameCount <= 4'b0;
|
||||||
InterCSCount <= 9'b10;
|
InterCSCount <= 9'b10;
|
||||||
end
|
end
|
||||||
else if (ChipSelectMode[1:0] == 2'b10) state <= INTER_XFR;
|
else if (ChipSelectMode[1:0] == 2'b10) state <= INTER_XFR;
|
||||||
@ -317,17 +310,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
else state <= DELAY_1;
|
else state <= DELAY_1;
|
||||||
end
|
end
|
||||||
DELAY_1: begin
|
DELAY_1: begin
|
||||||
Delay1Count <= Delay1Count + 9'b1;
|
SCK_CSCount <= SCK_CSCount + 9'b1;
|
||||||
if (Delay1Compare) state <= INTER_CS;
|
if (SCK_CSCompare) state <= INTER_CS;
|
||||||
end
|
end
|
||||||
INTER_CS: begin
|
INTER_CS: begin
|
||||||
InterCSCount <= InterCSCount + 9'b1;
|
InterCSCount <= InterCSCount + 9'b1;
|
||||||
if (InterCSCompare ) state <= CS_INACTIVE;
|
if (InterCSCompare ) state <= CS_INACTIVE;
|
||||||
end
|
end
|
||||||
INTER_XFR: begin
|
INTER_XFR: begin
|
||||||
Delay0Count <= 9'b1;
|
CS_SCKCount <= 9'b1;
|
||||||
Delay1Count <= 9'b10;
|
SCK_CSCount <= 9'b10;
|
||||||
FrameCount <= 5'b0;
|
FrameCount <= 4'b0;
|
||||||
InterCSCount <= 9'b10;
|
InterCSCount <= 9'b10;
|
||||||
InterXFRCount <= InterXFRCount + 9'b1;
|
InterXFRCount <= InterXFRCount + 9'b1;
|
||||||
if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
|
if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
|
||||||
@ -346,16 +339,15 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
|
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
|
||||||
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
|
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
|
||||||
assign Active0 = (state == ACTIVE_0);
|
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
|
always_comb
|
||||||
case(SckMode[1:0])
|
case(SckMode[1:0])
|
||||||
2'b00: sckPhaseSelect = ~sck & SCLKenable;
|
2'b00: ShiftEdge = ~sck & SCLKenable;
|
||||||
2'b01: sckPhaseSelect = (sck & |(FrameCount) & SCLKenable);
|
2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable);
|
||||||
2'b10: sckPhaseSelect = sck & SCLKenable;
|
2'b10: ShiftEdge = sck & SCLKenable;
|
||||||
2'b11: sckPhaseSelect = (~sck & |(FrameCount) & SCLKenable);
|
2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable);
|
||||||
default: sckPhaseSelect = sck & SCLKenable;
|
default: ShiftEdge = sck & SCLKenable;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
//Transmit shift register
|
//Transmit shift register
|
||||||
@ -363,32 +355,31 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if(~PRESETn) TransmitShiftReg <= 8'b0;
|
if(~PRESETn) TransmitShiftReg <= 8'b0;
|
||||||
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian;
|
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];
|
assign SPIOut = TransmitShiftReg[7];
|
||||||
|
|
||||||
//If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn
|
//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
|
//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)
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
||||||
else if (SampleEdge & SCLKenable) begin
|
else if (SampleEdge & SCLKenable) begin
|
||||||
if (~Active) ReceiveShiftReg <= 8'b0;
|
if (~Active) ReceiveShiftReg <= 8'b0;
|
||||||
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], shiftin};
|
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
|
||||||
end
|
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 LeftShiftAmount = 4'h8 - Format[4:1];
|
||||||
assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
|
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];
|
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);
|
assign SPIIntr = |(InterruptPending & InterruptEnable);
|
||||||
|
|
||||||
// Chip select logic
|
//Chip select logic
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(ChipSelectID[1:0])
|
case(ChipSelectID[1:0])
|
||||||
2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
|
2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
|
||||||
@ -409,6 +400,13 @@ module SynchFIFO #(parameter M =3 , N= 8)(
|
|||||||
output logic wfull, rempty,
|
output logic wfull, rempty,
|
||||||
output logic wwatermark, rwatermark);
|
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 [N-1:0] mem[2**M];
|
||||||
logic [M:0] rptr, wptr;
|
logic [M:0] rptr, wptr;
|
||||||
logic [M:0] rptrnext, wptrnext;
|
logic [M:0] rptrnext, wptrnext;
|
||||||
@ -416,7 +414,7 @@ module SynchFIFO #(parameter M =3 , N= 8)(
|
|||||||
logic wfull_val;
|
logic wfull_val;
|
||||||
logic [M-1:0] raddr;
|
logic [M-1:0] raddr;
|
||||||
logic [M-1:0] waddr;
|
logic [M-1:0] waddr;
|
||||||
|
|
||||||
assign rdata = mem[raddr];
|
assign rdata = mem[raddr];
|
||||||
always_ff @(posedge PCLK)
|
always_ff @(posedge PCLK)
|
||||||
if (winc & ~wfull) mem[waddr] <= wdata;
|
if (winc & ~wfull) mem[waddr] <= wdata;
|
||||||
|
Loading…
Reference in New Issue
Block a user